Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(588)

Side by Side Diff: pylib/gyp/generator/ninja.py

Issue 1506733002: GYP: Make GYP build deterministic (Closed) Base URL: https://chromium.googlesource.com/external/gyp.git@master
Patch Set: Shrinks test case down, more thorough testing. Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pylib/gyp/input.py » ('j') | pylib/gyp/ninja_syntax.py » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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)
OLDNEW
« no previous file with comments | « no previous file | pylib/gyp/input.py » ('j') | pylib/gyp/ninja_syntax.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698