Index: pylib/gyp/generator/ninja.py |
diff --git a/pylib/gyp/generator/ninja.py b/pylib/gyp/generator/ninja.py |
index b13affe0a172392ae115201874d5f44223b38c38..95aca57d3bdd188291a1f01bd9af3e48f09a4ad8 100644 |
--- a/pylib/gyp/generator/ninja.py |
+++ b/pylib/gyp/generator/ninja.py |
@@ -69,6 +69,9 @@ def StripPrefix(arg, prefix): |
return arg[len(prefix):] |
return arg |
+def OrderDeterministically(l, **kwargs): |
+ """ Sorts l so that it is ordered deterministically. """ |
+ return sorted(l, **kwargs) |
mithro-old
2015/12/10 03:15:27
I think this should be in gyp.common with OrderedS
Zachary Forman
2015/12/30 02:18:43
Yeah, you caught me mid refactor. Good spot for it
|
def QuoteShellArgument(arg, flavor): |
"""Quote a string such that it will be interpreted as a single argument |
@@ -421,10 +424,10 @@ class NinjaWriter(object): |
compile_depends.append(target.PreCompileInput()) |
actions_depends = filter(None, actions_depends) |
compile_depends = filter(None, compile_depends) |
- actions_depends = self.WriteCollapsedDependencies('actions_depends', |
- actions_depends) |
- compile_depends = self.WriteCollapsedDependencies('compile_depends', |
- compile_depends) |
+ actions_depends = self.WriteCollapsedDependencies( |
+ 'actions_depends', OrderDeterministically(actions_depends)) |
+ compile_depends = self.WriteCollapsedDependencies( |
+ 'compile_depends', OrderDeterministically(compile_depends)) |
self.target.preaction_stamp = actions_depends |
self.target.precompile_stamp = compile_depends |
@@ -559,7 +562,8 @@ class NinjaWriter(object): |
if 'sources' in spec and self.flavor == 'win': |
outputs += self.WriteWinIdlFiles(spec, prebuild) |
- stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs) |
+ stamp = self.WriteCollapsedDependencies('actions_rules_copies', |
+ OrderDeterministically(outputs)) |
if self.is_mac_bundle: |
xcassets = self.WriteMacBundleResources( |
@@ -657,6 +661,8 @@ class NinjaWriter(object): |
if '${%s}' % var in argument: |
needed_variables.add(var) |
+ needed_variables = OrderDeterministically(needed_variables) |
+ |
def cygwin_munge(path): |
# pylint: disable=cell-var-from-loop |
if is_cygwin: |
@@ -674,7 +680,7 @@ class NinjaWriter(object): |
num_inputs += 1 |
if num_inputs > 2 and len(sources) > 2: |
inputs = [self.WriteCollapsedDependencies( |
- rule['rule_name'], inputs, order_only=prebuild)] |
+ rule['rule_name'], OrderDeterministically(inputs), order_only=prebuild)] |
prebuild = [] |
# For each source file, write an edge that generates all the outputs. |
@@ -729,6 +735,8 @@ class NinjaWriter(object): |
# WriteNewNinjaRule uses unique_name for creating an rsp file on win. |
extra_bindings.append(('unique_name', |
hashlib.md5(outputs[0]).hexdigest())) |
+ |
+ # Make sure we sort extra_bindings so that output is deterministic. |
self.ninja.build(outputs, rule_name, self.GypPathToNinja(source), |
implicit=inputs, |
order_only=prebuild, |
@@ -1134,6 +1142,8 @@ class NinjaWriter(object): |
if not linkable or final_output != target.binary: |
implicit_deps.add(final_output) |
+ link_deps = OrderDeterministically(link_deps) |
+ |
extra_bindings = [] |
if self.uses_cpp and self.flavor != 'win': |
extra_bindings.append(('ld', '$ldxx')) |
@@ -1250,13 +1260,13 @@ class NinjaWriter(object): |
if pdbname: |
output = [output, pdbname] |
- |
if len(solibs): |
- extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs))) |
+ extra_bindings.append(('solibs', |
+ gyp.common.EncodePOSIXShellList(OrderDeterministically(solibs)))) |
ninja_file.build(output, command + command_suffix, link_deps, |
- implicit=list(implicit_deps), |
- order_only=list(order_deps), |
+ implicit=OrderDeterministically(implicit_deps), |
+ order_only=order_deps, |
variables=extra_bindings) |
return linked_binary |
@@ -2337,9 +2347,10 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, |
# able to run actions and build libraries by their short name. |
master_ninja.newline() |
master_ninja.comment('Short names for targets.') |
- for short_name in target_short_names: |
- master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in |
- target_short_names[short_name]]) |
+ |
+ for short_name in OrderDeterministically(target_short_names): |
+ master_ninja.build(short_name, 'phony', ([x.FinalOutput() for x in |
+ target_short_names[short_name]])) |
# Write phony targets for any empty targets that weren't written yet. As |
# short names are not necessarily unique only do this for short names that |
@@ -2348,12 +2359,14 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, |
if empty_target_names: |
master_ninja.newline() |
master_ninja.comment('Empty targets (output for completeness).') |
- for name in sorted(empty_target_names): |
+ |
+ # Iterate over empty target names in a deterministic order by sorting. |
+ for name in OrderDeterministically(empty_target_names): |
master_ninja.build(name, 'phony') |
if all_outputs: |
master_ninja.newline() |
- master_ninja.build('all', 'phony', list(all_outputs)) |
+ master_ninja.build('all', 'phony', OrderDeterministically(all_outputs)) |
master_ninja.default(generator_flags.get('default_target', 'all')) |
master_ninja_file.close() |