OLD | NEW |
1 # Copyright (c) 2012 Google Inc. All rights reserved. | 1 # Copyright (c) 2012 Google Inc. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 # Notes: | 5 # Notes: |
6 # | 6 # |
7 # This is all roughly based on the Makefile system used by the Linux | 7 # This is all roughly based on the Makefile system used by the Linux |
8 # kernel, but is a non-recursive make -- we put the entire dependency | 8 # kernel, but is a non-recursive make -- we put the entire dependency |
9 # graph in front of make and let it figure it out. | 9 # graph in front of make and let it figure it out. |
10 # | 10 # |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 $(call do_postbuilds) | 431 $(call do_postbuilds) |
432 ) | 432 ) |
433 ) | 433 ) |
434 endef | 434 endef |
435 | 435 |
436 # Declare the "%(default_target)s" target first so it is the default, | 436 # Declare the "%(default_target)s" target first so it is the default, |
437 # even though we don't have the deps yet. | 437 # even though we don't have the deps yet. |
438 .PHONY: %(default_target)s | 438 .PHONY: %(default_target)s |
439 %(default_target)s: | 439 %(default_target)s: |
440 | 440 |
| 441 # make looks for ways to re-generate included makefiles, but in our case, we |
| 442 # don't have a direct way. Explicitly telling make that it has nothing to do |
| 443 # for them makes it go faster. |
| 444 %%.d: ; |
| 445 |
441 # Use FORCE_DO_CMD to force a target to run. Should be coupled with | 446 # Use FORCE_DO_CMD to force a target to run. Should be coupled with |
442 # do_cmd. | 447 # do_cmd. |
443 .PHONY: FORCE_DO_CMD | 448 .PHONY: FORCE_DO_CMD |
444 FORCE_DO_CMD: | 449 FORCE_DO_CMD: |
445 | 450 |
446 """) | 451 """) |
447 | 452 |
448 SHARED_HEADER_MAC_COMMANDS = """ | 453 SHARED_HEADER_MAC_COMMANDS = """ |
449 quiet_cmd_objc = CXX($(TOOLSET)) $@ | 454 quiet_cmd_objc = CXX($(TOOLSET)) $@ |
450 cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< | 455 cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 | 521 |
517 SHARED_FOOTER = """\ | 522 SHARED_FOOTER = """\ |
518 # "all" is a concatenation of the "all" targets from all the included | 523 # "all" is a concatenation of the "all" targets from all the included |
519 # sub-makefiles. This is just here to clarify. | 524 # sub-makefiles. This is just here to clarify. |
520 all: | 525 all: |
521 | 526 |
522 # Add in dependency-tracking rules. $(all_deps) is the list of every single | 527 # Add in dependency-tracking rules. $(all_deps) is the list of every single |
523 # target in our tree. Only consider the ones with .d (dependency) info: | 528 # target in our tree. Only consider the ones with .d (dependency) info: |
524 d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) | 529 d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) |
525 ifneq ($(d_files),) | 530 ifneq ($(d_files),) |
526 # Rather than include each individual .d file, concatenate them into a | 531 include $(d_files) |
527 # single file which make is able to load faster. We split this into | |
528 # commands that take 1000 files at a time to avoid overflowing the | |
529 # command line. | |
530 $(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps) | |
531 %(generate_all_deps)s | |
532 # make looks for ways to re-generate included makefiles, but in our case, we | |
533 # don't have a direct way. Explicitly telling make that it has nothing to do | |
534 # for them makes it go faster. | |
535 $(depsdir)/all.deps: ; | |
536 | |
537 include $(depsdir)/all.deps | |
538 endif | 532 endif |
539 """ | 533 """ |
540 | 534 |
541 header = """\ | 535 header = """\ |
542 # This file is generated by gyp; do not edit. | 536 # This file is generated by gyp; do not edit. |
543 | 537 |
544 """ | 538 """ |
545 | 539 |
546 # Maps every compilable file extension to the do_cmd that compiles it. | 540 # Maps every compilable file extension to the do_cmd that compiles it. |
547 COMPILABLE_EXTENSIONS = { | 541 COMPILABLE_EXTENSIONS = { |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 | 640 |
647 class MakefileWriter: | 641 class MakefileWriter: |
648 """MakefileWriter packages up the writing of one target-specific foobar.mk. | 642 """MakefileWriter packages up the writing of one target-specific foobar.mk. |
649 | 643 |
650 Its only real entry point is Write(), and is mostly used for namespacing. | 644 Its only real entry point is Write(), and is mostly used for namespacing. |
651 """ | 645 """ |
652 | 646 |
653 def __init__(self, generator_flags, flavor): | 647 def __init__(self, generator_flags, flavor): |
654 self.generator_flags = generator_flags | 648 self.generator_flags = generator_flags |
655 self.flavor = flavor | 649 self.flavor = flavor |
656 # Keep track of the total number of outputs for this makefile. | |
657 self._num_outputs = 0 | |
658 | 650 |
659 self.suffix_rules_srcdir = {} | 651 self.suffix_rules_srcdir = {} |
660 self.suffix_rules_objdir1 = {} | 652 self.suffix_rules_objdir1 = {} |
661 self.suffix_rules_objdir2 = {} | 653 self.suffix_rules_objdir2 = {} |
662 | 654 |
663 # Generate suffix rules for all compilable extensions. | 655 # Generate suffix rules for all compilable extensions. |
664 for ext in COMPILABLE_EXTENSIONS.keys(): | 656 for ext in COMPILABLE_EXTENSIONS.keys(): |
665 # Suffix rules for source folder. | 657 # Suffix rules for source folder. |
666 self.suffix_rules_srcdir.update({ext: ("""\ | 658 self.suffix_rules_srcdir.update({ext: ("""\ |
667 $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD | 659 $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD |
668 @$(call do_cmd,%s,1) | 660 @$(call do_cmd,%s,1) |
669 """ % (ext, COMPILABLE_EXTENSIONS[ext]))}) | 661 """ % (ext, COMPILABLE_EXTENSIONS[ext]))}) |
670 | 662 |
671 # Suffix rules for generated source files. | 663 # Suffix rules for generated source files. |
672 self.suffix_rules_objdir1.update({ext: ("""\ | 664 self.suffix_rules_objdir1.update({ext: ("""\ |
673 $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD | 665 $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD |
674 @$(call do_cmd,%s,1) | 666 @$(call do_cmd,%s,1) |
675 """ % (ext, COMPILABLE_EXTENSIONS[ext]))}) | 667 """ % (ext, COMPILABLE_EXTENSIONS[ext]))}) |
676 self.suffix_rules_objdir2.update({ext: ("""\ | 668 self.suffix_rules_objdir2.update({ext: ("""\ |
677 $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD | 669 $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD |
678 @$(call do_cmd,%s,1) | 670 @$(call do_cmd,%s,1) |
679 """ % (ext, COMPILABLE_EXTENSIONS[ext]))}) | 671 """ % (ext, COMPILABLE_EXTENSIONS[ext]))}) |
680 | 672 |
681 | 673 |
682 def NumOutputs(self): | |
683 return self._num_outputs | |
684 | |
685 | |
686 def Write(self, qualified_target, base_path, output_filename, spec, configs, | 674 def Write(self, qualified_target, base_path, output_filename, spec, configs, |
687 part_of_all): | 675 part_of_all): |
688 """The main entry point: writes a .mk file for a single target. | 676 """The main entry point: writes a .mk file for a single target. |
689 | 677 |
690 Arguments: | 678 Arguments: |
691 qualified_target: target we're generating | 679 qualified_target: target we're generating |
692 base_path: path relative to source root we're building in, used to resolve | 680 base_path: path relative to source root we're building in, used to resolve |
693 target-relative paths | 681 target-relative paths |
694 output_filename: output .mk file name to write | 682 output_filename: output .mk file name to write |
695 spec, configs: gyp info | 683 spec, configs: gyp info |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
988 # Only write the 'obj' and 'builddir' rules for the "primary" output | 976 # Only write the 'obj' and 'builddir' rules for the "primary" output |
989 # (:1); it's superfluous for the "extra outputs", and this avoids | 977 # (:1); it's superfluous for the "extra outputs", and this avoids |
990 # accidentally writing duplicate dummy rules for those outputs. | 978 # accidentally writing duplicate dummy rules for those outputs. |
991 self.WriteLn('%s: obj := $(abs_obj)' % outputs[0]) | 979 self.WriteLn('%s: obj := $(abs_obj)' % outputs[0]) |
992 self.WriteLn('%s: builddir := $(abs_builddir)' % outputs[0]) | 980 self.WriteLn('%s: builddir := $(abs_builddir)' % outputs[0]) |
993 self.WriteMakeRule(outputs, inputs + ['FORCE_DO_CMD'], actions) | 981 self.WriteMakeRule(outputs, inputs + ['FORCE_DO_CMD'], actions) |
994 for output in outputs: | 982 for output in outputs: |
995 assert ' ' not in output, ( | 983 assert ' ' not in output, ( |
996 "Spaces in rule filenames not yet supported (%s)" % output) | 984 "Spaces in rule filenames not yet supported (%s)" % output) |
997 self.WriteLn('all_deps += %s' % ' '.join(outputs)) | 985 self.WriteLn('all_deps += %s' % ' '.join(outputs)) |
998 self._num_outputs += len(outputs) | |
999 | 986 |
1000 action = [self.ExpandInputRoot(ac, rule_source_root, | 987 action = [self.ExpandInputRoot(ac, rule_source_root, |
1001 rule_source_dirname) | 988 rule_source_dirname) |
1002 for ac in rule['action']] | 989 for ac in rule['action']] |
1003 mkdirs = '' | 990 mkdirs = '' |
1004 if len(dirs) > 0: | 991 if len(dirs) > 0: |
1005 mkdirs = 'mkdir -p %s; ' % ' '.join(dirs) | 992 mkdirs = 'mkdir -p %s; ' % ' '.join(dirs) |
1006 cd_action = 'cd %s; ' % Sourceify(self.path or '.') | 993 cd_action = 'cd %s; ' % Sourceify(self.path or '.') |
1007 | 994 |
1008 # action, cd_action, and mkdirs get written to a toplevel variable | 995 # action, cd_action, and mkdirs get written to a toplevel variable |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1174 compilable = filter(Compilable, sources) | 1161 compilable = filter(Compilable, sources) |
1175 objs = map(self.Objectify, map(self.Absolutify, map(Target, compilable))) | 1162 objs = map(self.Objectify, map(self.Absolutify, map(Target, compilable))) |
1176 self.WriteList(objs, 'OBJS') | 1163 self.WriteList(objs, 'OBJS') |
1177 | 1164 |
1178 for obj in objs: | 1165 for obj in objs: |
1179 assert ' ' not in obj, ( | 1166 assert ' ' not in obj, ( |
1180 "Spaces in object filenames not supported (%s)" % obj) | 1167 "Spaces in object filenames not supported (%s)" % obj) |
1181 self.WriteLn('# Add to the list of files we specially track ' | 1168 self.WriteLn('# Add to the list of files we specially track ' |
1182 'dependencies for.') | 1169 'dependencies for.') |
1183 self.WriteLn('all_deps += $(OBJS)') | 1170 self.WriteLn('all_deps += $(OBJS)') |
1184 self._num_outputs += len(objs) | |
1185 self.WriteLn() | 1171 self.WriteLn() |
1186 | 1172 |
1187 # Make sure our dependencies are built first. | 1173 # Make sure our dependencies are built first. |
1188 if deps: | 1174 if deps: |
1189 self.WriteMakeRule(['$(OBJS)'], deps, | 1175 self.WriteMakeRule(['$(OBJS)'], deps, |
1190 comment = 'Make sure our dependencies are built ' | 1176 comment = 'Make sure our dependencies are built ' |
1191 'before any of us.', | 1177 'before any of us.', |
1192 order_only = True) | 1178 order_only = True) |
1193 | 1179 |
1194 # Make sure the actions and rules run first. | 1180 # Make sure the actions and rules run first. |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1631 self.WriteMakeRule(outputs, inputs, | 1617 self.WriteMakeRule(outputs, inputs, |
1632 actions = ['$(call do_cmd,%s%s)' % (command, suffix)], | 1618 actions = ['$(call do_cmd,%s%s)' % (command, suffix)], |
1633 comment = comment, | 1619 comment = comment, |
1634 force = True) | 1620 force = True) |
1635 # Add our outputs to the list of targets we read depfiles from. | 1621 # Add our outputs to the list of targets we read depfiles from. |
1636 # all_deps is only used for deps file reading, and for deps files we replace | 1622 # all_deps is only used for deps file reading, and for deps files we replace |
1637 # spaces with ? because escaping doesn't work with make's $(sort) and | 1623 # spaces with ? because escaping doesn't work with make's $(sort) and |
1638 # other functions. | 1624 # other functions. |
1639 outputs = [QuoteSpaces(o, SPACE_REPLACEMENT) for o in outputs] | 1625 outputs = [QuoteSpaces(o, SPACE_REPLACEMENT) for o in outputs] |
1640 self.WriteLn('all_deps += %s' % ' '.join(outputs)) | 1626 self.WriteLn('all_deps += %s' % ' '.join(outputs)) |
1641 self._num_outputs += len(outputs) | |
1642 | 1627 |
1643 | 1628 |
1644 def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, | 1629 def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, |
1645 order_only=False, force=False, phony=False, | 1630 order_only=False, force=False, phony=False, |
1646 multiple_output_trick=True): | 1631 multiple_output_trick=True): |
1647 """Write a Makefile rule, with some extra tricks. | 1632 """Write a Makefile rule, with some extra tricks. |
1648 | 1633 |
1649 outputs: a list of outputs for the rule (note: this is not directly | 1634 outputs: a list of outputs for the rule (note: this is not directly |
1650 supported by make; see comments below) | 1635 supported by make; see comments below) |
1651 inputs: a list of inputs for the rule | 1636 inputs: a list of inputs for the rule |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2054 # Put build-time support tools next to the root Makefile. | 2039 # Put build-time support tools next to the root Makefile. |
2055 dest_path = os.path.dirname(makefile_path) | 2040 dest_path = os.path.dirname(makefile_path) |
2056 gyp.common.CopyTool(flavor, dest_path) | 2041 gyp.common.CopyTool(flavor, dest_path) |
2057 | 2042 |
2058 # Find the list of targets that derive from the gyp file(s) being built. | 2043 # Find the list of targets that derive from the gyp file(s) being built. |
2059 needed_targets = set() | 2044 needed_targets = set() |
2060 for build_file in params['build_files']: | 2045 for build_file in params['build_files']: |
2061 for target in gyp.common.AllTargets(target_list, target_dicts, build_file): | 2046 for target in gyp.common.AllTargets(target_list, target_dicts, build_file): |
2062 needed_targets.add(target) | 2047 needed_targets.add(target) |
2063 | 2048 |
2064 num_outputs = 0 | |
2065 build_files = set() | 2049 build_files = set() |
2066 include_list = set() | 2050 include_list = set() |
2067 for qualified_target in target_list: | 2051 for qualified_target in target_list: |
2068 build_file, target, toolset = gyp.common.ParseQualifiedTarget( | 2052 build_file, target, toolset = gyp.common.ParseQualifiedTarget( |
2069 qualified_target) | 2053 qualified_target) |
2070 | 2054 |
2071 this_make_global_settings = data[build_file].get('make_global_settings', {}) | 2055 this_make_global_settings = data[build_file].get('make_global_settings', {}) |
2072 assert make_global_settings_dict == this_make_global_settings, ( | 2056 assert make_global_settings_dict == this_make_global_settings, ( |
2073 "make_global_settings needs to be the same for all targets.") | 2057 "make_global_settings needs to be the same for all targets.") |
2074 | 2058 |
(...skipping 20 matching lines...) Expand all Loading... |
2095 | 2079 |
2096 spec = target_dicts[qualified_target] | 2080 spec = target_dicts[qualified_target] |
2097 configs = spec['configurations'] | 2081 configs = spec['configurations'] |
2098 | 2082 |
2099 if flavor == 'mac': | 2083 if flavor == 'mac': |
2100 gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec) | 2084 gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec) |
2101 | 2085 |
2102 writer = MakefileWriter(generator_flags, flavor) | 2086 writer = MakefileWriter(generator_flags, flavor) |
2103 writer.Write(qualified_target, base_path, output_file, spec, configs, | 2087 writer.Write(qualified_target, base_path, output_file, spec, configs, |
2104 part_of_all=qualified_target in needed_targets) | 2088 part_of_all=qualified_target in needed_targets) |
2105 num_outputs += writer.NumOutputs() | |
2106 | 2089 |
2107 # Our root_makefile lives at the source root. Compute the relative path | 2090 # Our root_makefile lives at the source root. Compute the relative path |
2108 # from there to the output_file for including. | 2091 # from there to the output_file for including. |
2109 mkfile_rel_path = gyp.common.RelativePath(output_file, | 2092 mkfile_rel_path = gyp.common.RelativePath(output_file, |
2110 os.path.dirname(makefile_path)) | 2093 os.path.dirname(makefile_path)) |
2111 include_list.add(mkfile_rel_path) | 2094 include_list.add(mkfile_rel_path) |
2112 | 2095 |
2113 # Write out per-gyp (sub-project) Makefiles. | 2096 # Write out per-gyp (sub-project) Makefiles. |
2114 depth_rel_path = gyp.common.RelativePath(options.depth, os.getcwd()) | 2097 depth_rel_path = gyp.common.RelativePath(options.depth, os.getcwd()) |
2115 for build_file in build_files: | 2098 for build_file in build_files: |
(...skipping 26 matching lines...) Expand all Loading... |
2142 "ifeq ($(strip $(foreach prefix,$(NO_LOAD),\\\n" | 2125 "ifeq ($(strip $(foreach prefix,$(NO_LOAD),\\\n" |
2143 " $(findstring $(join ^,$(prefix)),\\\n" | 2126 " $(findstring $(join ^,$(prefix)),\\\n" |
2144 " $(join ^," + include_file + ")))),)\n") | 2127 " $(join ^," + include_file + ")))),)\n") |
2145 root_makefile.write(" include " + include_file + "\n") | 2128 root_makefile.write(" include " + include_file + "\n") |
2146 root_makefile.write("endif\n") | 2129 root_makefile.write("endif\n") |
2147 root_makefile.write('\n') | 2130 root_makefile.write('\n') |
2148 | 2131 |
2149 if generator_flags.get('auto_regeneration', True): | 2132 if generator_flags.get('auto_regeneration', True): |
2150 WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files) | 2133 WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files) |
2151 | 2134 |
2152 # Write the rule to load dependencies. We batch 1000 files at a time to | 2135 root_makefile.write(SHARED_FOOTER) |
2153 # avoid overflowing the command line. | |
2154 all_deps = "" | |
2155 for i in range(1001, num_outputs, 1000): | |
2156 all_deps += (""" | |
2157 ifneq ($(word %(start)d,$(d_files)),) | |
2158 $(shell cat $(wordlist %(start)d,%(end)d,$(d_files)) >> $(depsdir)/all.deps) | |
2159 endif""" % { 'start': i, 'end': i + 999 }) | |
2160 | |
2161 # Add a check to make sure we tried to process all the .d files. | |
2162 all_deps += """ | |
2163 ifneq ($(word %(last)d,$(d_files)),) | |
2164 $(error Found unprocessed dependency files (gyp didn't generate enough rules
!)) | |
2165 endif | |
2166 """ % { 'last': ((num_outputs / 1000) + 1) * 1000 + 1 } | |
2167 | |
2168 root_makefile.write(SHARED_FOOTER % { 'generate_all_deps': all_deps }) | |
2169 | 2136 |
2170 root_makefile.close() | 2137 root_makefile.close() |
OLD | NEW |