| 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 |
| (...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 |
| 733 # Make sure we sort extra_bindings so that output is deterministic. |
| 732 self.ninja.build(outputs, rule_name, self.GypPathToNinja(source), | 734 self.ninja.build(outputs, rule_name, self.GypPathToNinja(source), |
| 733 implicit=inputs, | 735 implicit=inputs, |
| 734 order_only=prebuild, | 736 order_only=prebuild, |
| 735 variables=extra_bindings) | 737 variables=sorted(extra_bindings)) |
| 736 | 738 |
| 737 all_outputs.extend(outputs) | 739 all_outputs.extend(outputs) |
| 738 | 740 |
| 739 return all_outputs | 741 return all_outputs |
| 740 | 742 |
| 741 def WriteCopies(self, copies, prebuild, mac_bundle_depends): | 743 def WriteCopies(self, copies, prebuild, mac_bundle_depends): |
| 742 outputs = [] | 744 outputs = [] |
| 743 env = self.GetToolchainEnv() | 745 env = self.GetToolchainEnv() |
| 744 for copy in copies: | 746 for copy in copies: |
| 745 for path in copy['files']: | 747 for path in copy['files']: |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1243 output = [output, output + '.TOC'] | 1245 output = [output, output + '.TOC'] |
| 1244 else: | 1246 else: |
| 1245 command = command + '_notoc' | 1247 command = command + '_notoc' |
| 1246 elif self.flavor == 'win': | 1248 elif self.flavor == 'win': |
| 1247 extra_bindings.append(('binary', output)) | 1249 extra_bindings.append(('binary', output)) |
| 1248 pdbname = self.msvs_settings.GetPDBName( | 1250 pdbname = self.msvs_settings.GetPDBName( |
| 1249 config_name, self.ExpandSpecial, output + '.pdb') | 1251 config_name, self.ExpandSpecial, output + '.pdb') |
| 1250 if pdbname: | 1252 if pdbname: |
| 1251 output = [output, pdbname] | 1253 output = [output, pdbname] |
| 1252 | 1254 |
| 1255 # Sort the solibs here so that they're outputted deterministically. |
| 1256 if len(solibs): |
| 1257 extra_bindings.append(('solibs', |
| 1258 gyp.common.EncodePOSIXShellList(sorted(solibs)))) |
| 1253 | 1259 |
| 1254 if len(solibs): | 1260 # Sort outputs so that they're deterministically ordered. |
| 1255 extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs))) | |
| 1256 | |
| 1257 ninja_file.build(output, command + command_suffix, link_deps, | 1261 ninja_file.build(output, command + command_suffix, link_deps, |
| 1258 implicit=list(implicit_deps), | 1262 implicit=sorted(implicit_deps), |
| 1259 order_only=list(order_deps), | 1263 order_only=sorted(order_deps), |
| 1260 variables=extra_bindings) | 1264 variables=sorted(extra_bindings)) |
| 1261 return linked_binary | 1265 return linked_binary |
| 1262 | 1266 |
| 1263 def WriteTarget(self, spec, config_name, config, link_deps, compile_deps): | 1267 def WriteTarget(self, spec, config_name, config, link_deps, compile_deps): |
| 1264 extra_link_deps = any(self.target_outputs.get(dep).Linkable() | 1268 extra_link_deps = any(self.target_outputs.get(dep).Linkable() |
| 1265 for dep in spec.get('dependencies', []) | 1269 for dep in spec.get('dependencies', []) |
| 1266 if dep in self.target_outputs) | 1270 if dep in self.target_outputs) |
| 1267 if spec['type'] == 'none' or (not link_deps and not extra_link_deps): | 1271 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 | 1272 # 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. | 1273 # it doesn't do anything, and we fake out a 'binary' with a stamp file. |
| 1270 self.target.binary = compile_deps | 1274 self.target.binary = compile_deps |
| (...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2247 'stamp', | 2251 'stamp', |
| 2248 description='STAMP $out', | 2252 description='STAMP $out', |
| 2249 command='${postbuilds}touch $out') | 2253 command='${postbuilds}touch $out') |
| 2250 master_ninja.rule( | 2254 master_ninja.rule( |
| 2251 'copy', | 2255 'copy', |
| 2252 description='COPY $in $out', | 2256 description='COPY $in $out', |
| 2253 command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)') | 2257 command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)') |
| 2254 master_ninja.newline() | 2258 master_ninja.newline() |
| 2255 | 2259 |
| 2256 all_targets = set() | 2260 all_targets = set() |
| 2257 for build_file in params['build_files']: | 2261 # Iterate over build files deterministically so they're consistently ordered. |
| 2262 for build_file in sorted(params['build_files']): |
| 2258 for target in gyp.common.AllTargets(target_list, | 2263 for target in gyp.common.AllTargets(target_list, |
| 2259 target_dicts, | 2264 target_dicts, |
| 2260 os.path.normpath(build_file)): | 2265 os.path.normpath(build_file)): |
| 2261 all_targets.add(target) | 2266 all_targets.add(target) |
| 2262 all_outputs = set() | 2267 all_outputs = set() |
| 2263 | 2268 |
| 2264 # target_outputs is a map from qualified target name to a Target object. | 2269 # target_outputs is a map from qualified target name to a Target object. |
| 2265 target_outputs = {} | 2270 target_outputs = {} |
| 2266 # target_short_names is a map from target short name to a list of Target | 2271 # target_short_names is a map from target short name to a list of Target |
| 2267 # objects. | 2272 # objects. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2330 non_empty_target_names.add(name) | 2335 non_empty_target_names.add(name) |
| 2331 else: | 2336 else: |
| 2332 empty_target_names.add(name) | 2337 empty_target_names.add(name) |
| 2333 | 2338 |
| 2334 if target_short_names: | 2339 if target_short_names: |
| 2335 # Write a short name to build this target. This benefits both the | 2340 # 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 | 2341 # "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. | 2342 # able to run actions and build libraries by their short name. |
| 2338 master_ninja.newline() | 2343 master_ninja.newline() |
| 2339 master_ninja.comment('Short names for targets.') | 2344 master_ninja.comment('Short names for targets.') |
| 2340 for short_name in target_short_names: | 2345 |
| 2346 # Iterate over the target short names in a deterministic order by sorting. |
| 2347 for short_name in sorted(target_short_names): |
| 2341 master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in | 2348 master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in |
| 2342 target_short_names[short_name]]) | 2349 target_short_names[short_name]]) |
| 2343 | 2350 |
| 2344 # Write phony targets for any empty targets that weren't written yet. As | 2351 # 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 | 2352 # short names are not necessarily unique only do this for short names that |
| 2346 # haven't already been output for another target. | 2353 # haven't already been output for another target. |
| 2347 empty_target_names = empty_target_names - non_empty_target_names | 2354 empty_target_names = empty_target_names - non_empty_target_names |
| 2348 if empty_target_names: | 2355 if empty_target_names: |
| 2349 master_ninja.newline() | 2356 master_ninja.newline() |
| 2350 master_ninja.comment('Empty targets (output for completeness).') | 2357 master_ninja.comment('Empty targets (output for completeness).') |
| 2358 |
| 2359 # Iterate over empty target names in a deterministic order by sorting. |
| 2351 for name in sorted(empty_target_names): | 2360 for name in sorted(empty_target_names): |
| 2352 master_ninja.build(name, 'phony') | 2361 master_ninja.build(name, 'phony') |
| 2353 | 2362 |
| 2354 if all_outputs: | 2363 if all_outputs: |
| 2355 master_ninja.newline() | 2364 master_ninja.newline() |
| 2356 master_ninja.build('all', 'phony', list(all_outputs)) | 2365 master_ninja.build('all', 'phony', list(all_outputs)) |
| 2357 master_ninja.default(generator_flags.get('default_target', 'all')) | 2366 master_ninja.default(generator_flags.get('default_target', 'all')) |
| 2358 | 2367 |
| 2359 master_ninja_file.close() | 2368 master_ninja_file.close() |
| 2360 | 2369 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2401 arglists.append( | 2410 arglists.append( |
| 2402 (target_list, target_dicts, data, params, config_name)) | 2411 (target_list, target_dicts, data, params, config_name)) |
| 2403 pool.map(CallGenerateOutputForConfig, arglists) | 2412 pool.map(CallGenerateOutputForConfig, arglists) |
| 2404 except KeyboardInterrupt, e: | 2413 except KeyboardInterrupt, e: |
| 2405 pool.terminate() | 2414 pool.terminate() |
| 2406 raise e | 2415 raise e |
| 2407 else: | 2416 else: |
| 2408 for config_name in config_names: | 2417 for config_name in config_names: |
| 2409 GenerateOutputForConfig(target_list, target_dicts, data, params, | 2418 GenerateOutputForConfig(target_list, target_dicts, data, params, |
| 2410 config_name) | 2419 config_name) |
| OLD | NEW |