OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 # Copyright (c) 2009 Google Inc. All rights reserved. | 3 # Copyright (c) 2009 Google Inc. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 # Notes: | 7 # Notes: |
8 # | 8 # |
9 # This is all roughly based on the Makefile system used by the Linux | 9 # This is all roughly based on the Makefile system used by the Linux |
10 # kernel, but is a non-recursive make -- we put the entire dependency | 10 # kernel, but is a non-recursive make -- we put the entire dependency |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 # Used in building shared-library-based executables. | 496 # Used in building shared-library-based executables. |
497 target_link_deps = {} | 497 target_link_deps = {} |
498 | 498 |
499 | 499 |
500 class MakefileWriter: | 500 class MakefileWriter: |
501 """MakefileWriter packages up the writing of one target-specific foobar.mk. | 501 """MakefileWriter packages up the writing of one target-specific foobar.mk. |
502 | 502 |
503 Its only real entry point is Write(), and is mostly used for namespacing. | 503 Its only real entry point is Write(), and is mostly used for namespacing. |
504 """ | 504 """ |
505 | 505 |
506 def __init__(self): | 506 def __init__(self, generator_flags): |
| 507 self.generator_flags = generator_flags |
507 # Keep track of the total number of outputs for this makefile. | 508 # Keep track of the total number of outputs for this makefile. |
508 self._num_outputs = 0 | 509 self._num_outputs = 0 |
509 | 510 |
510 | 511 |
511 def NumOutputs(self): | 512 def NumOutputs(self): |
512 return self._num_outputs | 513 return self._num_outputs |
513 | 514 |
514 | 515 |
515 def Write(self, qualified_target, base_path, output_filename, spec, configs, | 516 def Write(self, qualified_target, base_path, output_filename, spec, configs, |
516 part_of_all): | 517 part_of_all): |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 target_outputs[qualified_target] = install_path | 598 target_outputs[qualified_target] = install_path |
598 | 599 |
599 # Update global list of link dependencies. | 600 # Update global list of link dependencies. |
600 if self.type == 'static_library': | 601 if self.type == 'static_library': |
601 target_link_deps[qualified_target] = [self.output] | 602 target_link_deps[qualified_target] = [self.output] |
602 elif self.type == 'shared_library': | 603 elif self.type == 'shared_library': |
603 # Anyone that uses us transitively depend on all of our link | 604 # Anyone that uses us transitively depend on all of our link |
604 # dependencies. | 605 # dependencies. |
605 target_link_deps[qualified_target] = [self.output] + link_deps | 606 target_link_deps[qualified_target] = [self.output] + link_deps |
606 | 607 |
| 608 # Currently any versions have the same effect, but in future the behavior |
| 609 # could be different. |
| 610 if self.generator_flags.get('android_ndk_version', None): |
| 611 self.WriteAndroidNdkModuleRule(self.target, all_sources, link_deps) |
| 612 |
607 self.fp.close() | 613 self.fp.close() |
608 | 614 |
609 | 615 |
610 def WriteSubMake(self, output_filename, makefile_path, targets, build_dir): | 616 def WriteSubMake(self, output_filename, makefile_path, targets, build_dir): |
611 """Write a "sub-project" Makefile. | 617 """Write a "sub-project" Makefile. |
612 | 618 |
613 This is a small, wrapper Makefile that calls the top-level Makefile to build | 619 This is a small, wrapper Makefile that calls the top-level Makefile to build |
614 the targets from a single gyp file (i.e. a sub-project). | 620 the targets from a single gyp file (i.e. a sub-project). |
615 | 621 |
616 Arguments: | 622 Arguments: |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 # we'll have generated all the outputs and we're done. | 1145 # we'll have generated all the outputs and we're done. |
1140 self.WriteLn('%s: %s' % (' '.join(outputs[1:]), outputs[0])) | 1146 self.WriteLn('%s: %s' % (' '.join(outputs[1:]), outputs[0])) |
1141 # Add a dummy command to the "extra outputs" rule, otherwise make seems to | 1147 # Add a dummy command to the "extra outputs" rule, otherwise make seems to |
1142 # think these outputs haven't (couldn't have?) changed, and thus doesn't | 1148 # think these outputs haven't (couldn't have?) changed, and thus doesn't |
1143 # flag them as changed (i.e. include in '$?') when evaluating dependent | 1149 # flag them as changed (i.e. include in '$?') when evaluating dependent |
1144 # rules, which in turn causes do_cmd() to skip running dependent commands. | 1150 # rules, which in turn causes do_cmd() to skip running dependent commands. |
1145 self.WriteLn('%s: ;' % (' '.join(outputs[1:]))) | 1151 self.WriteLn('%s: ;' % (' '.join(outputs[1:]))) |
1146 self.WriteLn() | 1152 self.WriteLn() |
1147 | 1153 |
1148 | 1154 |
| 1155 def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps): |
| 1156 """Write a set of LOCAL_XXX definitions for Android NDK. |
| 1157 |
| 1158 These variable definitions will be used by Android NDK but do nothing for |
| 1159 non-Android applications. |
| 1160 |
| 1161 Arguments: |
| 1162 module_name: Android NDK module name, which must be unique among all |
| 1163 module names. |
| 1164 all_sources: A list of source files (will be filtered by Compilable). |
| 1165 link_deps: A list of link dependencies, which must be sorted in |
| 1166 the order from dependencies to dependents. |
| 1167 """ |
| 1168 if self.type not in ('executable', 'shared_library', 'static_library'): |
| 1169 return |
| 1170 |
| 1171 self.WriteLn('# Variable definitions for Android applications') |
| 1172 self.WriteLn('include $(CLEAR_VARS)') |
| 1173 self.WriteLn('LOCAL_MODULE := ' + module_name) |
| 1174 self.WriteLn('LOCAL_CFLAGS := $(CFLAGS_$(BUILDTYPE)) ' |
| 1175 '$(DEFS_$(BUILDTYPE)) ' |
| 1176 # LOCAL_CFLAGS is applied to both of C and C++. There is |
| 1177 # no way to specify $(CFLAGS_C_$(BUILDTYPE)) only for C |
| 1178 # sources. |
| 1179 '$(CFLAGS_C_$(BUILDTYPE)) ' |
| 1180 # $(INCS_$(BUILDTYPE)) includes the prefix '-I' while |
| 1181 # LOCAL_C_INCLUDES does not expect it. So put it in |
| 1182 # LOCAL_CFLAGS. |
| 1183 '$(INCS_$(BUILDTYPE))') |
| 1184 # LOCAL_CXXFLAGS is obsolete and LOCAL_CPPFLAGS is preferred. |
| 1185 self.WriteLn('LOCAL_CPPFLAGS := $(CFLAGS_CC_$(BUILDTYPE))') |
| 1186 self.WriteLn('LOCAL_C_INCLUDES :=') |
| 1187 self.WriteLn('LOCAL_LDLIBS := $(LDFLAGS_$(BUILDTYPE)) $(LIBS)') |
| 1188 |
| 1189 # Detect the C++ extension. |
| 1190 cpp_ext = {'.cc': 0, '.cpp': 0, '.cxx': 0} |
| 1191 default_cpp_ext = '.cpp' |
| 1192 for filename in all_sources: |
| 1193 ext = os.path.splitext(filename)[1] |
| 1194 if ext in cpp_ext: |
| 1195 cpp_ext[ext] += 1 |
| 1196 if cpp_ext[ext] > cpp_ext[default_cpp_ext]: |
| 1197 default_cpp_ext = ext |
| 1198 self.WriteLn('LOCAL_CPP_EXTENSION := ' + default_cpp_ext) |
| 1199 |
| 1200 self.WriteList(map(self.Absolutify, filter(Compilable, all_sources)), |
| 1201 'LOCAL_SRC_FILES') |
| 1202 |
| 1203 # Filter out those which do not match prefix and suffix and produce |
| 1204 # the resulting list without prefix and suffix. |
| 1205 def DepsToModules(deps, prefix, suffix): |
| 1206 modules = [] |
| 1207 for filepath in deps: |
| 1208 filename = os.path.basename(filepath) |
| 1209 if filename.startswith(prefix) and filename.endswith(suffix): |
| 1210 modules.append(filename[len(prefix):-len(suffix)]) |
| 1211 return modules |
| 1212 |
| 1213 self.WriteList( |
| 1214 DepsToModules(link_deps, |
| 1215 generator_default_variables['SHARED_LIB_PREFIX'], |
| 1216 generator_default_variables['SHARED_LIB_SUFFIX']), |
| 1217 'LOCAL_SHARED_LIBRARIES') |
| 1218 self.WriteList( |
| 1219 DepsToModules(link_deps, |
| 1220 generator_default_variables['STATIC_LIB_PREFIX'], |
| 1221 generator_default_variables['STATIC_LIB_SUFFIX']), |
| 1222 'LOCAL_STATIC_LIBRARIES') |
| 1223 |
| 1224 if self.type == 'executable': |
| 1225 self.WriteLn('include $(BUILD_EXECUTABLE)') |
| 1226 elif self.type == 'shared_library': |
| 1227 self.WriteLn('include $(BUILD_SHARED_LIBRARY)') |
| 1228 elif self.type == 'static_library': |
| 1229 self.WriteLn('include $(BUILD_STATIC_LIBRARY)') |
| 1230 self.WriteLn() |
| 1231 |
| 1232 |
1149 def WriteLn(self, text=''): | 1233 def WriteLn(self, text=''): |
1150 self.fp.write(text + '\n') | 1234 self.fp.write(text + '\n') |
1151 | 1235 |
1152 | 1236 |
1153 def Objectify(self, path): | 1237 def Objectify(self, path): |
1154 """Convert a path to its output directory form.""" | 1238 """Convert a path to its output directory form.""" |
1155 if '$(' in path: | 1239 if '$(' in path: |
1156 path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/' % self.toolset) | 1240 path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/' % self.toolset) |
1157 return path | 1241 return path |
1158 return '$(obj).%s/$(TARGET)/%s' % (self.toolset, path) | 1242 return '$(obj).%s/$(TARGET)/%s' % (self.toolset, path) |
1159 | 1243 |
| 1244 |
1160 def Absolutify(self, path): | 1245 def Absolutify(self, path): |
1161 """Convert a subdirectory-relative path into a base-relative path. | 1246 """Convert a subdirectory-relative path into a base-relative path. |
1162 Skips over paths that contain variables.""" | 1247 Skips over paths that contain variables.""" |
1163 if '$(' in path: | 1248 if '$(' in path: |
1164 return path | 1249 return path |
1165 return os.path.normpath(os.path.join(self.path, path)) | 1250 return os.path.normpath(os.path.join(self.path, path)) |
1166 | 1251 |
1167 | 1252 |
1168 def FixupArgPath(self, arg): | 1253 def FixupArgPath(self, arg): |
1169 if '/' in arg or '.h.' in arg: | 1254 if '/' in arg or '.h.' in arg: |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1263 """Calculate additional variables for use in the build (called by gyp).""" | 1348 """Calculate additional variables for use in the build (called by gyp).""" |
1264 cc_target = os.environ.get('CC.target', os.environ.get('CC', 'cc')) | 1349 cc_target = os.environ.get('CC.target', os.environ.get('CC', 'cc')) |
1265 default_variables['LINKER_SUPPORTS_ICF'] = \ | 1350 default_variables['LINKER_SUPPORTS_ICF'] = \ |
1266 gyp.system_test.TestLinkerSupportsICF(cc_command=cc_target) | 1351 gyp.system_test.TestLinkerSupportsICF(cc_command=cc_target) |
1267 | 1352 |
1268 | 1353 |
1269 def GenerateOutput(target_list, target_dicts, data, params): | 1354 def GenerateOutput(target_list, target_dicts, data, params): |
1270 options = params['options'] | 1355 options = params['options'] |
1271 generator_flags = params.get('generator_flags', {}) | 1356 generator_flags = params.get('generator_flags', {}) |
1272 builddir_name = generator_flags.get('output_dir', 'out') | 1357 builddir_name = generator_flags.get('output_dir', 'out') |
| 1358 android_ndk_version = generator_flags.get('android_ndk_version', None) |
1273 | 1359 |
1274 def CalculateMakefilePath(build_file, base_name): | 1360 def CalculateMakefilePath(build_file, base_name): |
1275 """Determine where to write a Makefile for a given gyp file.""" | 1361 """Determine where to write a Makefile for a given gyp file.""" |
1276 # Paths in gyp files are relative to the .gyp file, but we want | 1362 # Paths in gyp files are relative to the .gyp file, but we want |
1277 # paths relative to the source root for the master makefile. Grab | 1363 # paths relative to the source root for the master makefile. Grab |
1278 # the path of the .gyp file as the base to relativize against. | 1364 # the path of the .gyp file as the base to relativize against. |
1279 # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp". | 1365 # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp". |
1280 base_path = gyp.common.RelativePath(os.path.dirname(build_file), | 1366 base_path = gyp.common.RelativePath(os.path.dirname(build_file), |
1281 options.depth) | 1367 options.depth) |
1282 # We write the file in the base_path directory. | 1368 # We write the file in the base_path directory. |
(...skipping 29 matching lines...) Expand all Loading... |
1312 header_params = { | 1398 header_params = { |
1313 'srcdir': srcdir, | 1399 'srcdir': srcdir, |
1314 'builddir': builddir_name, | 1400 'builddir': builddir_name, |
1315 'default_configuration': default_configuration, | 1401 'default_configuration': default_configuration, |
1316 } | 1402 } |
1317 header_params.update(RunSystemTests()) | 1403 header_params.update(RunSystemTests()) |
1318 | 1404 |
1319 ensure_directory_exists(makefile_path) | 1405 ensure_directory_exists(makefile_path) |
1320 root_makefile = open(makefile_path, 'w') | 1406 root_makefile = open(makefile_path, 'w') |
1321 root_makefile.write(SHARED_HEADER % header_params) | 1407 root_makefile.write(SHARED_HEADER % header_params) |
| 1408 # Currently any versions have the same effect, but in future the behavior |
| 1409 # could be different. |
| 1410 if android_ndk_version: |
| 1411 root_makefile.write( |
| 1412 '# Define LOCAL_PATH for build of Android applications.\n' |
| 1413 'LOCAL_PATH := $(call my-dir)\n' |
| 1414 '\n') |
1322 for toolset in toolsets: | 1415 for toolset in toolsets: |
1323 root_makefile.write('TOOLSET := %s\n' % toolset) | 1416 root_makefile.write('TOOLSET := %s\n' % toolset) |
1324 root_makefile.write(ROOT_HEADER_SUFFIX_RULES) | 1417 root_makefile.write(ROOT_HEADER_SUFFIX_RULES) |
1325 | 1418 |
1326 # Find the list of targets that derive from the gyp file(s) being built. | 1419 # Find the list of targets that derive from the gyp file(s) being built. |
1327 needed_targets = set() | 1420 needed_targets = set() |
1328 for build_file in params['build_files']: | 1421 for build_file in params['build_files']: |
1329 for target in gyp.common.AllTargets(target_list, target_dicts, build_file): | 1422 for target in gyp.common.AllTargets(target_list, target_dicts, build_file): |
1330 needed_targets.add(target) | 1423 needed_targets.add(target) |
1331 | 1424 |
(...skipping 20 matching lines...) Expand all Loading... |
1352 build_files.add(abs_include_file) | 1445 build_files.add(abs_include_file) |
1353 else: | 1446 else: |
1354 build_files.add(relative_include_file) | 1447 build_files.add(relative_include_file) |
1355 | 1448 |
1356 base_path, output_file = CalculateMakefilePath(build_file, | 1449 base_path, output_file = CalculateMakefilePath(build_file, |
1357 target + '.' + toolset + options.suffix + '.mk') | 1450 target + '.' + toolset + options.suffix + '.mk') |
1358 | 1451 |
1359 spec = target_dicts[qualified_target] | 1452 spec = target_dicts[qualified_target] |
1360 configs = spec['configurations'] | 1453 configs = spec['configurations'] |
1361 | 1454 |
1362 writer = MakefileWriter() | 1455 writer = MakefileWriter(generator_flags) |
1363 writer.Write(qualified_target, base_path, output_file, spec, configs, | 1456 writer.Write(qualified_target, base_path, output_file, spec, configs, |
1364 part_of_all=qualified_target in needed_targets) | 1457 part_of_all=qualified_target in needed_targets) |
1365 num_outputs += writer.NumOutputs() | 1458 num_outputs += writer.NumOutputs() |
1366 | 1459 |
1367 # Our root_makefile lives at the source root. Compute the relative path | 1460 # Our root_makefile lives at the source root. Compute the relative path |
1368 # from there to the output_file for including. | 1461 # from there to the output_file for including. |
1369 mkfile_rel_path = gyp.common.RelativePath(output_file, | 1462 mkfile_rel_path = gyp.common.RelativePath(output_file, |
1370 os.path.dirname(makefile_path)) | 1463 os.path.dirname(makefile_path)) |
1371 include_list.add(mkfile_rel_path) | 1464 include_list.add(mkfile_rel_path) |
1372 | 1465 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1421 # Add a check to make sure we tried to process all the .d files. | 1514 # Add a check to make sure we tried to process all the .d files. |
1422 all_deps += """ | 1515 all_deps += """ |
1423 ifneq ($(word %(last)d,$(d_files)),) | 1516 ifneq ($(word %(last)d,$(d_files)),) |
1424 $(error Found unprocessed dependency files (gyp didn't generate enough rules
!)) | 1517 $(error Found unprocessed dependency files (gyp didn't generate enough rules
!)) |
1425 endif | 1518 endif |
1426 """ % { 'last': ((num_outputs / 1000) + 1) * 1000 + 1 } | 1519 """ % { 'last': ((num_outputs / 1000) + 1) * 1000 + 1 } |
1427 | 1520 |
1428 root_makefile.write(SHARED_FOOTER % { 'generate_all_deps': all_deps }) | 1521 root_makefile.write(SHARED_FOOTER % { 'generate_all_deps': all_deps }) |
1429 | 1522 |
1430 root_makefile.close() | 1523 root_makefile.close() |
OLD | NEW |