1 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """This is a simplified Makefile generator for single-target gyp files.
6 It was originally designed for generating readable Makefiles for the
10 # pylint: disable=C0301
14 from gyp
.common
import GetEnvironFallback
15 from gyp
.generator
.make
import QuoteIfNecessary
17 generator_default_variables
= {
18 'EXECUTABLE_PREFIX': '',
19 'EXECUTABLE_SUFFIX': '',
20 'STATIC_LIB_PREFIX': 'lib',
21 'SHARED_LIB_PREFIX': 'lib',
22 'STATIC_LIB_SUFFIX': '.a',
23 'INTERMEDIATE_DIR': '$(BUILDDIR)/$(BUILDTYPE)/obj',
24 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen',
25 'PRODUCT_DIR': '$(BUILDDIR)/$(BUILDTYPE)',
26 'CONFIGURATION_NAME': '$(BUILDTYPE)',
30 generator_additional_non_configuration_keys
= [
31 'make_valid_configurations',
37 # GNU Make based build file. For details on GNU Make see:
38 # http://www.gnu.org/software/make/manual/make.html
40 # This file was generated by gyp (http://code.google.com/p/gyp/)
42 # Default build configuration
43 BUILDTYPE = %(default_config)s
45 # All possible build configurations
46 BUILDTYPES = %(all_configs)s
48 # Check for valid build configuration
49 ifeq (,$(findstring $(BUILDTYPE),$(BUILDTYPES)))
50 $(warning Possible build configurations are: $(BUILDTYPES))
51 $(warning Cannot use BUILDTYPE=$(BUILDTYPE) with this Makefile.)
56 CC.target ?= %(CC.target)s
57 CFLAGS.target ?= $(CFLAGS)
58 CXX.target ?= %(CXX.target)s
59 CXXFLAGS.target ?= $(CXXFLAGS)
60 LINK.target ?= %(LINK.target)s
61 LDFLAGS.target ?= $(LDFLAGS)
62 AR.target ?= %(AR.target)s
63 ARFLAGS.target ?= %(ARFLAGS.target)s
73 ARFLAGS.host := %(ARFLAGS.host)s
90 TARGET = $(BUILDDIR)/$(BUILDTYPE)/%(target)s.stamp
103 SOURCES = %(sources)s
105 LIBS_%(target_name_var)s_$(BUILDTYPE) = %(libs)s
109 DEPFILES += $(OBJS:%%.o=%%.d)
111 # Suffix rules, putting all outputs into build folder.
112 $(BUILDDIR)/$(BUILDTYPE)/obj_%(target)s/%%.o: %%.c
113 \t@mkdir -p $(dir $@)
114 \t$(CC.%(toolset)s) $(CFLAGS_%(target_name_var)s_$(BUILDTYPE)) -c -o $@ $<
116 $(BUILDDIR)/$(BUILDTYPE)/obj_%(target)s/%%.o: %%.cc
117 \t@mkdir -p $(dir $@)
118 \t$(CXX.%(toolset)s) $(CXXFLAGS_%(target_name_var)s_$(BUILDTYPE)) -c -o $@ $<
124 \t@mkdir -p $(dir $@)
125 \t$(AR.%(toolset)s) $(ARFLAGS.%(toolset)s) $(ARFLAGS_%(target_name_var)s_$(BUILDTYPE)) $@ $^
131 \t@mkdir -p $(dir $@)
132 \t$(LINK.%(toolset)s) $(LDFLAGS_%(target_name_var)s_$(BUILDTYPE)) $(LDFLAGS.%(toolset)s) -o $@ -Wl,--start-group $^ $(LIBS_%(target_name_var)s_$(BUILDTYPE)) -Wl,--end-group
136 def MakeList(value_list
, prefix
='', quoter
=QuoteIfNecessary
, initial_indent
=0):
137 """Construct from a list of values a string that can be assigned to a make
138 variable. This uses line continuations and limits line length to 80 chars.
143 value_list
= [quoter(prefix
+ l
) for l
in value_list
]
145 line
= ' ' * initial_indent
146 for value
in value_list
:
147 if len(line
) + len(value
) >= 79:
154 rtn
= ' \\\n\t'.join(lines
)
158 def WriteList(makefile
, value_list
, variable
, prefix
='', quoter
=QuoteIfNecessary
):
159 values
= MakeList(value_list
, prefix
, quoter
, initial_indent
=len(variable
)+4)
160 makefile
.write("\n%s := %s\n" % (variable
, values
))
163 def WriteConfig(makefile
, name
, config
, target_type
):
164 WriteList(makefile
, config
.get('defines', []), 'DEFS_%s' % name
, '-D')
165 WriteList(makefile
, config
.get('cflags', []), 'CPPFLAGS_%s' % name
)
166 WriteList(makefile
, config
.get('arflags', []), 'ARFLAGS_%s' % name
)
167 ldflags
= config
.get('ldflags', [])
168 if target_type
== 'shared_library':
169 ldflags
.insert(0, '-shared')
170 WriteList(makefile
, ldflags
, 'LDFLAGS_%s' % name
)
172 include_dirs
= config
.get('include_dirs', [])
173 include_dirs
= ["-I%s" % i
for i
in include_dirs
]
174 common_flags
= ['$(CPPFLAGS_%s)' % name
, '$(DEFS_%s)' % name
, '$(DEPFLAGS)']
175 common_flags
+= include_dirs
176 WriteList(makefile
, common_flags
+ config
.get('cflags_c', []), 'CFLAGS_%s' % name
)
177 WriteList(makefile
, common_flags
+ config
.get('cflags_cc', []), 'CXXFLAGS_%s' % name
)
180 def WriteActions(makefile
, actions
, target_type
):
181 for action
in actions
:
182 cmd
= gyp
.common
.EncodePOSIXShellList(action
['action'])
183 makefile
.write("\t%s\n" % cmd
)
184 if target_type
== 'none':
185 makefile
.write("\ttouch $@\n")
189 def WriteTarget(makefile
, target_info
):
190 valid_conf
= ' '.join(target_info
.get('make_valid_configurations', []))
192 makefile
.write("\nifneq (,$(findstring $(BUILDTYPE),%s))\n" % valid_conf
)
196 # Settings for the '%(target_name)s'
200 sources
= target_info
.get('sources', [])
201 exts
= ['.cc', '.c', '.cxx', '.cpp']
202 sources
= [s
for s
in sources
if os
.path
.splitext(s
)[1] in exts
]
203 objects
= [os
.path
.splitext(src
)[0] for src
in sources
]
204 objects
= [obj
+ '.o' for obj
in objects
]
206 target_name_var
= target_info
['target_name']
207 target_name_var
= target_name_var
.replace('.', '_')
209 for name
, config
in target_info
['configurations'].items():
210 name
= target_name_var
+ '_' + name
211 WriteConfig(makefile
, name
, config
, target_info
['type'])
213 actions
= target_info
.get('actions', [])
216 'target': target_info
['target_name'],
217 'product': target_info
['target_name'],
218 'target_name_var': target_name_var
,
221 if 'product_name' in target_info
:
222 params
['product'] = target_info
['product_name']
224 if target_info
['type'] == 'static_library':
226 elif target_info
['type'] == 'shared_library':
231 if prefix
and not params
['product'].startswith(prefix
):
232 params
['product'] = prefix
+ params
['product']
234 dirname
= target_info
.get('product_dir', '$(BUILDDIR)/$(BUILDTYPE)')
235 params
['product'] = os
.path
.join(dirname
, params
['product'])
237 if target_info
['type'] == 'none':
239 'inputs': MakeList(actions
[0]['inputs'])
241 makefile
.write(none_section
% params
)
243 builddir
= '$(BUILDDIR)/$(BUILDTYPE)/obj_%s' % target_info
['target_name']
245 'sources': MakeList(sources
),
246 'libs': MakeList(target_info
['libraries']),
247 'objs': MakeList(["%s/%s" % (builddir
, obj
) for obj
in objects
]),
248 'toolset': target_info
['toolset']
251 makefile
.write(target_section
% params
)
252 if target_info
['type'] == 'static_library':
253 makefile
.write(lib_section
% params
)
255 makefile
.write(link_section
% params
)
257 WriteActions(makefile
, actions
, target_info
['type'])
259 makefile
.write('endif\n')
262 def GenerateOutput(target_list
, target_dicts
, data
, params
):
263 """Main entry point for this generator.
265 gyp will call this function.
267 options
= params
['options']
268 makefilename
= os
.path
.join(options
.toplevel_dir
, 'Makefile')
269 makefile
= open(makefilename
, 'w')
271 build_file
, _
, _
= gyp
.common
.ParseQualifiedTarget(target_list
[0])
272 make_global_settings
= data
[build_file
].get('make_global_settings', [])
273 settings_map
= dict((key
, value
) for key
, value
in make_global_settings
)
275 target_info
= target_dicts
[target_list
[0]]
278 'CC.target': GetEnvironFallback(['CC_target'], '$(CC)'),
279 'AR.target': GetEnvironFallback(['AR_target'], '$(AR)'),
280 'ARFLAGS.target': GetEnvironFallback(['ARFLAGS_target'], 'crs'),
281 'CXX.target': GetEnvironFallback(['CXX_target'], '$(CXX)'),
282 'LINK.target': GetEnvironFallback(['LINK_target'], '$(LINK)') ,
284 'ARFLAGS.host': GetEnvironFallback(['ARFLAGS_host'], 'crs'),
286 'default_config': target_info
['default_configuration'],
287 'all_configs': ' '.join(target_info
['configurations'].keys()),
290 params
.update(settings_map
)
291 makefile
.write(preamble
% params
)
293 for target_info
in target_dicts
.values():
294 WriteTarget(makefile
, target_info
)
297 # include (if they exists) the .d dependency files that the compiler generates