| OLD | NEW |
| 1 # Copyright (c) 2013 Google Inc. All rights reserved. | 1 # Copyright (c) 2013 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 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs] | 1012 outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs] |
| 1013 inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs] | 1013 inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs] |
| 1014 | 1014 |
| 1015 outputs = map(self.Absolutify, outputs) | 1015 outputs = map(self.Absolutify, outputs) |
| 1016 all_outputs += outputs | 1016 all_outputs += outputs |
| 1017 # Only write the 'obj' and 'builddir' rules for the "primary" output | 1017 # Only write the 'obj' and 'builddir' rules for the "primary" output |
| 1018 # (:1); it's superfluous for the "extra outputs", and this avoids | 1018 # (:1); it's superfluous for the "extra outputs", and this avoids |
| 1019 # accidentally writing duplicate dummy rules for those outputs. | 1019 # accidentally writing duplicate dummy rules for those outputs. |
| 1020 self.WriteLn('%s: obj := $(abs_obj)' % outputs[0]) | 1020 self.WriteLn('%s: obj := $(abs_obj)' % outputs[0]) |
| 1021 self.WriteLn('%s: builddir := $(abs_builddir)' % outputs[0]) | 1021 self.WriteLn('%s: builddir := $(abs_builddir)' % outputs[0]) |
| 1022 self.WriteMakeRule(outputs, inputs + ['FORCE_DO_CMD'], actions) | 1022 self.WriteMakeRule(outputs, inputs, actions, |
| 1023 command="%s_%d" % (name, count)) |
| 1023 # Spaces in rule filenames are not supported, but rule variables have | 1024 # Spaces in rule filenames are not supported, but rule variables have |
| 1024 # spaces in them (e.g. RULE_INPUT_PATH expands to '$(abspath $<)'). | 1025 # spaces in them (e.g. RULE_INPUT_PATH expands to '$(abspath $<)'). |
| 1025 # The spaces within the variables are valid, so remove the variables | 1026 # The spaces within the variables are valid, so remove the variables |
| 1026 # before checking. | 1027 # before checking. |
| 1027 variables_with_spaces = re.compile(r'\$\([^ ]* \$<\)') | 1028 variables_with_spaces = re.compile(r'\$\([^ ]* \$<\)') |
| 1028 for output in outputs: | 1029 for output in outputs: |
| 1029 output = re.sub(variables_with_spaces, '', output) | 1030 output = re.sub(variables_with_spaces, '', output) |
| 1030 assert ' ' not in output, ( | 1031 assert ' ' not in output, ( |
| 1031 "Spaces in rule filenames not yet supported (%s)" % output) | 1032 "Spaces in rule filenames not yet supported (%s)" % output) |
| 1032 self.WriteLn('all_deps += %s' % ' '.join(outputs)) | 1033 self.WriteLn('all_deps += %s' % ' '.join(outputs)) |
| (...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1681 This makes the outputs dependent on the command line that was run, | 1682 This makes the outputs dependent on the command line that was run, |
| 1682 as well as support the V= make command line flag. | 1683 as well as support the V= make command line flag. |
| 1683 """ | 1684 """ |
| 1684 suffix = '' | 1685 suffix = '' |
| 1685 if postbuilds: | 1686 if postbuilds: |
| 1686 assert ',' not in command | 1687 assert ',' not in command |
| 1687 suffix = ',,1' # Tell do_cmd to honor $POSTBUILDS | 1688 suffix = ',,1' # Tell do_cmd to honor $POSTBUILDS |
| 1688 self.WriteMakeRule(outputs, inputs, | 1689 self.WriteMakeRule(outputs, inputs, |
| 1689 actions = ['$(call do_cmd,%s%s)' % (command, suffix)], | 1690 actions = ['$(call do_cmd,%s%s)' % (command, suffix)], |
| 1690 comment = comment, | 1691 comment = comment, |
| 1692 command = command, |
| 1691 force = True) | 1693 force = True) |
| 1692 # Add our outputs to the list of targets we read depfiles from. | 1694 # Add our outputs to the list of targets we read depfiles from. |
| 1693 # all_deps is only used for deps file reading, and for deps files we replace | 1695 # all_deps is only used for deps file reading, and for deps files we replace |
| 1694 # spaces with ? because escaping doesn't work with make's $(sort) and | 1696 # spaces with ? because escaping doesn't work with make's $(sort) and |
| 1695 # other functions. | 1697 # other functions. |
| 1696 outputs = [QuoteSpaces(o, SPACE_REPLACEMENT) for o in outputs] | 1698 outputs = [QuoteSpaces(o, SPACE_REPLACEMENT) for o in outputs] |
| 1697 self.WriteLn('all_deps += %s' % ' '.join(outputs)) | 1699 self.WriteLn('all_deps += %s' % ' '.join(outputs)) |
| 1698 | 1700 |
| 1699 | 1701 |
| 1700 def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, | 1702 def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, |
| 1701 order_only=False, force=False, phony=False): | 1703 order_only=False, force=False, phony=False, command=None): |
| 1702 """Write a Makefile rule, with some extra tricks. | 1704 """Write a Makefile rule, with some extra tricks. |
| 1703 | 1705 |
| 1704 outputs: a list of outputs for the rule (note: this is not directly | 1706 outputs: a list of outputs for the rule (note: this is not directly |
| 1705 supported by make; see comments below) | 1707 supported by make; see comments below) |
| 1706 inputs: a list of inputs for the rule | 1708 inputs: a list of inputs for the rule |
| 1707 actions: a list of shell commands to run for the rule | 1709 actions: a list of shell commands to run for the rule |
| 1708 comment: a comment to put in the Makefile above the rule (also useful | 1710 comment: a comment to put in the Makefile above the rule (also useful |
| 1709 for making this Python script's code self-documenting) | 1711 for making this Python script's code self-documenting) |
| 1710 order_only: if true, makes the dependency order-only | 1712 order_only: if true, makes the dependency order-only |
| 1711 force: if true, include FORCE_DO_CMD as an order-only dep | 1713 force: if true, include FORCE_DO_CMD as an order-only dep |
| 1712 phony: if true, the rule does not actually generate the named output, the | 1714 phony: if true, the rule does not actually generate the named output, the |
| 1713 output is just a name to run the rule | 1715 output is just a name to run the rule |
| 1716 command: (optional) command name to generate unambiguous labels |
| 1714 """ | 1717 """ |
| 1715 outputs = map(QuoteSpaces, outputs) | 1718 outputs = map(QuoteSpaces, outputs) |
| 1716 inputs = map(QuoteSpaces, inputs) | 1719 inputs = map(QuoteSpaces, inputs) |
| 1717 | 1720 |
| 1718 if comment: | 1721 if comment: |
| 1719 self.WriteLn('# ' + comment) | 1722 self.WriteLn('# ' + comment) |
| 1720 if phony: | 1723 if phony: |
| 1721 self.WriteLn('.PHONY: ' + ' '.join(outputs)) | 1724 self.WriteLn('.PHONY: ' + ' '.join(outputs)) |
| 1722 # TODO(evanm): just make order_only a list of deps instead of these hacks. | |
| 1723 if order_only: | |
| 1724 order_insert = '| ' | |
| 1725 pick_output = ' '.join(outputs) | |
| 1726 else: | |
| 1727 order_insert = '' | |
| 1728 pick_output = outputs[0] | |
| 1729 if force: | |
| 1730 force_append = ' FORCE_DO_CMD' | |
| 1731 else: | |
| 1732 force_append = '' | |
| 1733 if actions: | 1725 if actions: |
| 1734 self.WriteLn("%s: TOOLSET := $(TOOLSET)" % outputs[0]) | 1726 self.WriteLn("%s: TOOLSET := $(TOOLSET)" % outputs[0]) |
| 1735 self.WriteLn('%s: %s%s%s' % (pick_output, order_insert, ' '.join(inputs), | 1727 force_append = ' FORCE_DO_CMD' if force else '' |
| 1736 force_append)) | 1728 |
| 1729 if order_only: |
| 1730 # Order only rule: Just write a simple rule. |
| 1731 # TODO(evanm): just make order_only a list of deps instead of this hack. |
| 1732 self.WriteLn('%s: | %s%s' % |
| 1733 (' '.join(outputs), ' '.join(inputs), force_append)) |
| 1734 elif len(outputs) == 1: |
| 1735 # Regular rule, one output: Just write a simple rule. |
| 1736 self.WriteLn('%s: %s%s' % (outputs[0], ' '.join(inputs), force_append)) |
| 1737 else: |
| 1738 # Regular rule, more than one output: Multiple outputs are tricky in |
| 1739 # make. We will write three rules: |
| 1740 # - All outputs depend on an intermediate file. |
| 1741 # - Make .INTERMEDIATE depend on the intermediate. |
| 1742 # - The intermediate file depends on the inputs and executes the |
| 1743 # actual command. |
| 1744 # |
| 1745 # For an explanation of the problem and several solutions that don't |
| 1746 # work, see this: |
| 1747 # http://www.gnu.org/software/hello/manual/automake/Multiple-Outputs.html |
| 1748 intermediate = "%s.intermediate" % (command if command else self.target) |
| 1749 self.WriteLn('%s: %s' % (' '.join(outputs), intermediate)) |
| 1750 self.WriteLn('%s: %s' % ('.INTERMEDIATE', intermediate)) |
| 1751 self.WriteLn('%s: %s%s' % |
| 1752 (intermediate, ' '.join(inputs), force_append)) |
| 1753 |
| 1737 if actions: | 1754 if actions: |
| 1738 for action in actions: | 1755 for action in actions: |
| 1739 self.WriteLn('\t%s' % action) | 1756 self.WriteLn('\t%s' % action) |
| 1740 if not order_only and len(outputs) > 1: | |
| 1741 # If we have more than one output, a rule like | |
| 1742 # foo bar: baz | |
| 1743 # that for *each* output we must run the action, potentially | |
| 1744 # in parallel. That is not what we're trying to write -- what | |
| 1745 # we want is that we run the action once and it generates all | |
| 1746 # the files. | |
| 1747 # http://www.gnu.org/software/hello/manual/automake/Multiple-Outputs.html | |
| 1748 # discusses this problem and has this solution: | |
| 1749 # 1) Write the naive rule that would produce parallel runs of | |
| 1750 # the action. | |
| 1751 # 2) Make the outputs seralized on each other, so we won't start | |
| 1752 # a parallel run until the first run finishes, at which point | |
| 1753 # we'll have generated all the outputs and we're done. | |
| 1754 self.WriteLn('%s: %s' % (' '.join(outputs[1:]), outputs[0])) | |
| 1755 # Add a dummy command to the "extra outputs" rule, otherwise make seems to | |
| 1756 # think these outputs haven't (couldn't have?) changed, and thus doesn't | |
| 1757 # flag them as changed (i.e. include in '$?') when evaluating dependent | |
| 1758 # rules, which in turn causes do_cmd() to skip running dependent commands. | |
| 1759 self.WriteLn('%s: ;' % (' '.join(outputs[1:]))) | |
| 1760 self.WriteLn() | 1757 self.WriteLn() |
| 1761 | 1758 |
| 1762 | 1759 |
| 1763 def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps): | 1760 def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps): |
| 1764 """Write a set of LOCAL_XXX definitions for Android NDK. | 1761 """Write a set of LOCAL_XXX definitions for Android NDK. |
| 1765 | 1762 |
| 1766 These variable definitions will be used by Android NDK but do nothing for | 1763 These variable definitions will be used by Android NDK but do nothing for |
| 1767 non-Android applications. | 1764 non-Android applications. |
| 1768 | 1765 |
| 1769 Arguments: | 1766 Arguments: |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2203 root_makefile.write("endif\n") | 2200 root_makefile.write("endif\n") |
| 2204 root_makefile.write('\n') | 2201 root_makefile.write('\n') |
| 2205 | 2202 |
| 2206 if (not generator_flags.get('standalone') | 2203 if (not generator_flags.get('standalone') |
| 2207 and generator_flags.get('auto_regeneration', True)): | 2204 and generator_flags.get('auto_regeneration', True)): |
| 2208 WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files) | 2205 WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files) |
| 2209 | 2206 |
| 2210 root_makefile.write(SHARED_FOOTER) | 2207 root_makefile.write(SHARED_FOOTER) |
| 2211 | 2208 |
| 2212 root_makefile.close() | 2209 root_makefile.close() |
| OLD | NEW |