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 import collections | 5 import collections |
6 import copy | 6 import copy |
7 import hashlib | 7 import hashlib |
8 import json | 8 import json |
9 import multiprocessing | 9 import multiprocessing |
10 import os.path | 10 import os.path |
11 import re | 11 import re |
12 import signal | 12 import signal |
13 import subprocess | 13 import subprocess |
14 import sys | 14 import sys |
15 import gyp | 15 import gyp |
16 import gyp.common | 16 import gyp.common |
17 from gyp.common import OrderedSet | 17 from gyp.common import OrderedSet |
| 18 from gyp.common import OrderDeterministically |
| 19 |
18 import gyp.msvs_emulation | 20 import gyp.msvs_emulation |
19 import gyp.MSVSUtil as MSVSUtil | 21 import gyp.MSVSUtil as MSVSUtil |
20 import gyp.xcode_emulation | 22 import gyp.xcode_emulation |
21 from cStringIO import StringIO | 23 from cStringIO import StringIO |
22 | 24 |
23 from gyp.common import GetEnvironFallback | 25 from gyp.common import GetEnvironFallback |
24 import gyp.ninja_syntax as ninja_syntax | 26 import gyp.ninja_syntax as ninja_syntax |
25 | 27 |
26 generator_default_variables = { | 28 generator_default_variables = { |
27 'EXECUTABLE_PREFIX': '', | 29 'EXECUTABLE_PREFIX': '', |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 | 651 |
650 # Rules can potentially make use of some special variables which | 652 # Rules can potentially make use of some special variables which |
651 # must vary per source file. | 653 # must vary per source file. |
652 # Compute the list of variables we'll need to provide. | 654 # Compute the list of variables we'll need to provide. |
653 special_locals = ('source', 'root', 'dirname', 'ext', 'name') | 655 special_locals = ('source', 'root', 'dirname', 'ext', 'name') |
654 needed_variables = set(['source']) | 656 needed_variables = set(['source']) |
655 for argument in args: | 657 for argument in args: |
656 for var in special_locals: | 658 for var in special_locals: |
657 if '${%s}' % var in argument: | 659 if '${%s}' % var in argument: |
658 needed_variables.add(var) | 660 needed_variables.add(var) |
| 661 needed_variables = OrderDeterministically(needed_variables) |
659 | 662 |
660 def cygwin_munge(path): | 663 def cygwin_munge(path): |
661 # pylint: disable=cell-var-from-loop | 664 # pylint: disable=cell-var-from-loop |
662 if is_cygwin: | 665 if is_cygwin: |
663 return path.replace('\\', '/') | 666 return path.replace('\\', '/') |
664 return path | 667 return path |
665 | 668 |
666 inputs = [self.GypPathToNinja(i, env) for i in rule.get('inputs', [])] | 669 inputs = [self.GypPathToNinja(i, env) for i in rule.get('inputs', [])] |
667 | 670 |
668 # If there are n source files matching the rule, and m additional rule | 671 # If there are n source files matching the rule, and m additional rule |
(...skipping 11 matching lines...) Expand all Loading... |
680 # For each source file, write an edge that generates all the outputs. | 683 # For each source file, write an edge that generates all the outputs. |
681 for source in sources: | 684 for source in sources: |
682 source = os.path.normpath(source) | 685 source = os.path.normpath(source) |
683 dirname, basename = os.path.split(source) | 686 dirname, basename = os.path.split(source) |
684 root, ext = os.path.splitext(basename) | 687 root, ext = os.path.splitext(basename) |
685 | 688 |
686 # Gather the list of inputs and outputs, expanding $vars if possible. | 689 # Gather the list of inputs and outputs, expanding $vars if possible. |
687 outputs = [self.ExpandRuleVariables(o, root, dirname, | 690 outputs = [self.ExpandRuleVariables(o, root, dirname, |
688 source, ext, basename) | 691 source, ext, basename) |
689 for o in rule['outputs']] | 692 for o in rule['outputs']] |
690 | |
691 if int(rule.get('process_outputs_as_sources', False)): | 693 if int(rule.get('process_outputs_as_sources', False)): |
692 extra_sources += outputs | 694 extra_sources += outputs |
693 | |
694 was_mac_bundle_resource = source in mac_bundle_resources | 695 was_mac_bundle_resource = source in mac_bundle_resources |
695 if was_mac_bundle_resource or \ | 696 if was_mac_bundle_resource or \ |
696 int(rule.get('process_outputs_as_mac_bundle_resources', False)): | 697 int(rule.get('process_outputs_as_mac_bundle_resources', False)): |
697 extra_mac_bundle_resources += outputs | 698 extra_mac_bundle_resources += outputs |
698 # Note: This is n_resources * n_outputs_in_rule. Put to-be-removed | 699 # Note: This is n_resources * n_outputs_in_rule. Put to-be-removed |
699 # items in a set and remove them all in a single pass if this becomes | 700 # items in a set and remove them all in a single pass if this becomes |
700 # a performance issue. | 701 # a performance issue. |
701 if was_mac_bundle_resource: | 702 if was_mac_bundle_resource: |
702 mac_bundle_resources.remove(source) | 703 mac_bundle_resources.remove(source) |
703 | |
704 extra_bindings = [] | 704 extra_bindings = [] |
705 for var in needed_variables: | 705 for var in needed_variables: |
706 if var == 'root': | 706 if var == 'root': |
707 extra_bindings.append(('root', cygwin_munge(root))) | 707 extra_bindings.append(('root', cygwin_munge(root))) |
708 elif var == 'dirname': | 708 elif var == 'dirname': |
709 # '$dirname' is a parameter to the rule action, which means | 709 # '$dirname' is a parameter to the rule action, which means |
710 # it shouldn't be converted to a Ninja path. But we don't | 710 # it shouldn't be converted to a Ninja path. But we don't |
711 # want $!PRODUCT_DIR in there either. | 711 # want $!PRODUCT_DIR in there either. |
712 dirname_expanded = self.ExpandSpecial(dirname, self.base_to_build) | 712 dirname_expanded = self.ExpandSpecial(dirname, self.base_to_build) |
713 extra_bindings.append(('dirname', cygwin_munge(dirname_expanded))) | 713 extra_bindings.append(('dirname', cygwin_munge(dirname_expanded))) |
714 elif var == 'source': | 714 elif var == 'source': |
715 # '$source' is a parameter to the rule action, which means | 715 # '$source' is a parameter to the rule action, which means |
716 # it shouldn't be converted to a Ninja path. But we don't | 716 # it shouldn't be converted to a Ninja path. But we don't |
717 # want $!PRODUCT_DIR in there either. | 717 # want $!PRODUCT_DIR in there either. |
718 source_expanded = self.ExpandSpecial(source, self.base_to_build) | 718 source_expanded = self.ExpandSpecial(source, self.base_to_build) |
719 extra_bindings.append(('source', cygwin_munge(source_expanded))) | 719 extra_bindings.append(('source', cygwin_munge(source_expanded))) |
720 elif var == 'ext': | 720 elif var == 'ext': |
721 extra_bindings.append(('ext', ext)) | 721 extra_bindings.append(('ext', ext)) |
722 elif var == 'name': | 722 elif var == 'name': |
723 extra_bindings.append(('name', cygwin_munge(basename))) | 723 extra_bindings.append(('name', cygwin_munge(basename))) |
724 else: | 724 else: |
725 assert var == None, repr(var) | 725 assert var == None, repr(var) |
726 | 726 |
727 outputs = [self.GypPathToNinja(o, env) for o in outputs] | 727 outputs = [self.GypPathToNinja(o, env) for o in outputs] |
728 if self.flavor == 'win': | 728 if self.flavor == 'win': |
729 # WriteNewNinjaRule uses unique_name for creating an rsp file on win. | 729 # WriteNewNinjaRule uses unique_name for creating an rsp file on win. |
730 extra_bindings.append(('unique_name', | 730 extra_bindings.append(('unique_name', |
731 hashlib.md5(outputs[0]).hexdigest())) | 731 hashlib.md5(outputs[0]).hexdigest())) |
| 732 |
732 self.ninja.build(outputs, rule_name, self.GypPathToNinja(source), | 733 self.ninja.build(outputs, rule_name, self.GypPathToNinja(source), |
733 implicit=inputs, | 734 implicit=inputs, |
734 order_only=prebuild, | 735 order_only=prebuild, |
735 variables=extra_bindings) | 736 variables=extra_bindings) |
736 | 737 |
737 all_outputs.extend(outputs) | 738 all_outputs.extend(outputs) |
738 | 739 |
739 return all_outputs | 740 return all_outputs |
740 | 741 |
741 def WriteCopies(self, copies, prebuild, mac_bundle_depends): | 742 def WriteCopies(self, copies, prebuild, mac_bundle_depends): |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1245 command = command + '_notoc' | 1246 command = command + '_notoc' |
1246 elif self.flavor == 'win': | 1247 elif self.flavor == 'win': |
1247 extra_bindings.append(('binary', output)) | 1248 extra_bindings.append(('binary', output)) |
1248 pdbname = self.msvs_settings.GetPDBName( | 1249 pdbname = self.msvs_settings.GetPDBName( |
1249 config_name, self.ExpandSpecial, output + '.pdb') | 1250 config_name, self.ExpandSpecial, output + '.pdb') |
1250 if pdbname: | 1251 if pdbname: |
1251 output = [output, pdbname] | 1252 output = [output, pdbname] |
1252 | 1253 |
1253 | 1254 |
1254 if len(solibs): | 1255 if len(solibs): |
1255 extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs))) | 1256 extra_bindings.append(('solibs', |
| 1257 gyp.common.EncodePOSIXShellList(OrderDeterministically(solibs)))) |
1256 | 1258 |
1257 ninja_file.build(output, command + command_suffix, link_deps, | 1259 ninja_file.build(output, command + command_suffix, link_deps, |
1258 implicit=list(implicit_deps), | 1260 implicit=OrderDeterministically(implicit_deps), |
1259 order_only=list(order_deps), | 1261 order_only=order_deps, |
1260 variables=extra_bindings) | 1262 variables=extra_bindings) |
1261 return linked_binary | 1263 return linked_binary |
1262 | 1264 |
1263 def WriteTarget(self, spec, config_name, config, link_deps, compile_deps): | 1265 def WriteTarget(self, spec, config_name, config, link_deps, compile_deps): |
1264 extra_link_deps = any(self.target_outputs.get(dep).Linkable() | 1266 extra_link_deps = any(self.target_outputs.get(dep).Linkable() |
1265 for dep in spec.get('dependencies', []) | 1267 for dep in spec.get('dependencies', []) |
1266 if dep in self.target_outputs) | 1268 if dep in self.target_outputs) |
1267 if spec['type'] == 'none' or (not link_deps and not extra_link_deps): | 1269 if spec['type'] == 'none' or (not link_deps and not extra_link_deps): |
1268 # TODO(evan): don't call this function for 'none' target types, as | 1270 # TODO(evan): don't call this function for 'none' target types, as |
1269 # it doesn't do anything, and we fake out a 'binary' with a stamp file. | 1271 # it doesn't do anything, and we fake out a 'binary' with a stamp file. |
(...skipping 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2330 non_empty_target_names.add(name) | 2332 non_empty_target_names.add(name) |
2331 else: | 2333 else: |
2332 empty_target_names.add(name) | 2334 empty_target_names.add(name) |
2333 | 2335 |
2334 if target_short_names: | 2336 if target_short_names: |
2335 # Write a short name to build this target. This benefits both the | 2337 # Write a short name to build this target. This benefits both the |
2336 # "build chrome" case as well as the gyp tests, which expect to be | 2338 # "build chrome" case as well as the gyp tests, which expect to be |
2337 # able to run actions and build libraries by their short name. | 2339 # able to run actions and build libraries by their short name. |
2338 master_ninja.newline() | 2340 master_ninja.newline() |
2339 master_ninja.comment('Short names for targets.') | 2341 master_ninja.comment('Short names for targets.') |
2340 for short_name in target_short_names: | 2342 for short_name in OrderDeterministically(target_short_names): |
2341 master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in | 2343 master_ninja.build(short_name, 'phony', ([x.FinalOutput() for x in |
2342 target_short_names[short_name]]) | 2344 target_short_names[short_name]])) |
2343 | 2345 |
2344 # Write phony targets for any empty targets that weren't written yet. As | 2346 # Write phony targets for any empty targets that weren't written yet. As |
2345 # short names are not necessarily unique only do this for short names that | 2347 # short names are not necessarily unique only do this for short names that |
2346 # haven't already been output for another target. | 2348 # haven't already been output for another target. |
2347 empty_target_names = empty_target_names - non_empty_target_names | 2349 empty_target_names = empty_target_names - non_empty_target_names |
2348 if empty_target_names: | 2350 if empty_target_names: |
2349 master_ninja.newline() | 2351 master_ninja.newline() |
2350 master_ninja.comment('Empty targets (output for completeness).') | 2352 master_ninja.comment('Empty targets (output for completeness).') |
2351 for name in sorted(empty_target_names): | 2353 for name in OrderDeterministically(empty_target_names): |
2352 master_ninja.build(name, 'phony') | 2354 master_ninja.build(name, 'phony') |
2353 | 2355 |
2354 if all_outputs: | 2356 if all_outputs: |
2355 master_ninja.newline() | 2357 master_ninja.newline() |
2356 master_ninja.build('all', 'phony', list(all_outputs)) | 2358 master_ninja.build('all', 'phony', OrderDeterministically(all_outputs)) |
2357 master_ninja.default(generator_flags.get('default_target', 'all')) | 2359 master_ninja.default(generator_flags.get('default_target', 'all')) |
2358 | 2360 |
2359 master_ninja_file.close() | 2361 master_ninja_file.close() |
2360 | 2362 |
2361 | 2363 |
2362 def PerformBuild(data, configurations, params): | 2364 def PerformBuild(data, configurations, params): |
2363 options = params['options'] | 2365 options = params['options'] |
2364 for config in configurations: | 2366 for config in configurations: |
2365 builddir = os.path.join(options.toplevel_dir, 'out', config) | 2367 builddir = os.path.join(options.toplevel_dir, 'out', config) |
2366 arguments = ['ninja', '-C', builddir] | 2368 arguments = ['ninja', '-C', builddir] |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2401 arglists.append( | 2403 arglists.append( |
2402 (target_list, target_dicts, data, params, config_name)) | 2404 (target_list, target_dicts, data, params, config_name)) |
2403 pool.map(CallGenerateOutputForConfig, arglists) | 2405 pool.map(CallGenerateOutputForConfig, arglists) |
2404 except KeyboardInterrupt, e: | 2406 except KeyboardInterrupt, e: |
2405 pool.terminate() | 2407 pool.terminate() |
2406 raise e | 2408 raise e |
2407 else: | 2409 else: |
2408 for config_name in config_names: | 2410 for config_name in config_names: |
2409 GenerateOutputForConfig(target_list, target_dicts, data, params, | 2411 GenerateOutputForConfig(target_list, target_dicts, data, params, |
2410 config_name) | 2412 config_name) |
OLD | NEW |