summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsbaig1@bloomberg.net <sbaig1@bloomberg.net>2014-09-26 16:14:11 +0000
committersbaig1@bloomberg.net <sbaig1@bloomberg.net>2014-09-26 16:14:11 +0000
commit55e3f25dfe2aa3e3321708d4a2a919a1e4577695 (patch)
treec4987ecc0a89aa434a19b5a63d4daba2c2c5ca23
parent05c509393b3fcf42ee8f10ca7da7842df0434ca7 (diff)
downloadgyp-55e3f25dfe2aa3e3321708d4a2a919a1e4577695.tar.gz
ninja: Don't rerun actions/rules based on where gyp was invoked
Right now, ninja generates unique names for actions/rules by combining the action/rule name with a hash on the qualified_target. However, the path of the qualified_target is relative to where gyp was invoked from. So, the following gyp command: gyp --depth=. foo/bar.gyp will generate a different hash than: cd foo gyp --depth=../ bar.gyp Since the hash is different, this causes actions/rules to get rerun based on where gyp happened to be invoked from. This commit fixes this issue by using a qualified_target relative to the toplevel_dir, rather than the current working directory. Also, the self.qualified_target in NinjaWriter is only used for the hash, so we can remove it and replace it with a precomputed hash for all actions/rules. BUG= R=scottmg@chromium.org Review URL: https://codereview.chromium.org/607083002 git-svn-id: http://gyp.googlecode.com/svn/trunk@1987 78cadc50-ecff-11dd-a971-7dbc132099af
-rw-r--r--pylib/gyp/generator/ninja.py16
-rw-r--r--test/ninja/action-rule-hash/gyptest-action-rule-hash.py27
-rw-r--r--test/ninja/action-rule-hash/subdir/action-rule-hash.gyp29
-rw-r--r--test/ninja/action-rule-hash/subdir/emit.py13
4 files changed, 78 insertions, 7 deletions
diff --git a/pylib/gyp/generator/ninja.py b/pylib/gyp/generator/ninja.py
index 7b7f8f23..677ce3c2 100644
--- a/pylib/gyp/generator/ninja.py
+++ b/pylib/gyp/generator/ninja.py
@@ -213,7 +213,7 @@ class Target:
# to the input file name as well as the output target name.
class NinjaWriter:
- def __init__(self, qualified_target, target_outputs, base_dir, build_dir,
+ def __init__(self, hash_for_rules, target_outputs, base_dir, build_dir,
output_file, toplevel_build, output_file_name, flavor,
toplevel_dir=None):
"""
@@ -223,7 +223,7 @@ class NinjaWriter:
toplevel_dir: path to the toplevel directory
"""
- self.qualified_target = qualified_target
+ self.hash_for_rules = hash_for_rules
self.target_outputs = target_outputs
self.base_dir = base_dir
self.build_dir = build_dir
@@ -591,8 +591,7 @@ class NinjaWriter:
all_outputs = []
for action in actions:
# First write out a rule for the action.
- name = '%s_%s' % (action['action_name'],
- hashlib.md5(self.qualified_target).hexdigest())
+ name = '%s_%s' % (action['action_name'], self.hash_for_rules)
description = self.GenerateDescription('ACTION',
action.get('message', None),
name)
@@ -629,8 +628,7 @@ class NinjaWriter:
continue
# First write out a rule for the rule action.
- name = '%s_%s' % (rule['rule_name'],
- hashlib.md5(self.qualified_target).hexdigest())
+ name = '%s_%s' % (rule['rule_name'], self.hash_for_rules)
args = rule['action']
description = self.GenerateDescription(
@@ -2183,6 +2181,10 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params,
build_file = gyp.common.RelativePath(build_file, options.toplevel_dir)
+ qualified_target_for_hash = gyp.common.QualifiedTarget(build_file, name,
+ toolset)
+ hash_for_rules = hashlib.md5(qualified_target_for_hash).hexdigest()
+
base_path = os.path.dirname(build_file)
obj = 'obj'
if toolset != 'target':
@@ -2190,7 +2192,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params,
output_file = os.path.join(obj, base_path, name + '.ninja')
ninja_output = StringIO()
- writer = NinjaWriter(qualified_target, target_outputs, base_path, build_dir,
+ writer = NinjaWriter(hash_for_rules, target_outputs, base_path, build_dir,
ninja_output,
toplevel_build, output_file,
flavor, toplevel_dir=options.toplevel_dir)
diff --git a/test/ninja/action-rule-hash/gyptest-action-rule-hash.py b/test/ninja/action-rule-hash/gyptest-action-rule-hash.py
new file mode 100644
index 00000000..631e176a
--- /dev/null
+++ b/test/ninja/action-rule-hash/gyptest-action-rule-hash.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2014 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Verify that running gyp in a different directory does not cause actions and
+rules to rerun.
+"""
+
+import os
+import sys
+import TestGyp
+
+test = TestGyp.TestGyp(formats=['ninja'])
+
+test.run_gyp('subdir/action-rule-hash.gyp')
+test.build('subdir/action-rule-hash.gyp', test.ALL)
+test.up_to_date('subdir/action-rule-hash.gyp')
+
+# Verify that everything is still up-to-date when we re-invoke gyp from a
+# different directory.
+test.run_gyp('action-rule-hash.gyp', '--depth=../', chdir='subdir')
+test.up_to_date('subdir/action-rule-hash.gyp')
+
+test.pass_test()
diff --git a/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp b/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp
new file mode 100644
index 00000000..0e88a301
--- /dev/null
+++ b/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp
@@ -0,0 +1,29 @@
+# Copyright (c) 2014 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'sources': [
+ '<(INTERMEDIATE_DIR)/main.cc',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'emit_main_cc',
+ 'inputs': ['emit.py'],
+ 'outputs': ['<(INTERMEDIATE_DIR)/main.cc'],
+ 'action': [
+ 'python',
+ 'emit.py',
+ '<(INTERMEDIATE_DIR)/main.cc',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ ],
+}
diff --git a/test/ninja/action-rule-hash/subdir/emit.py b/test/ninja/action-rule-hash/subdir/emit.py
new file mode 100644
index 00000000..fcb715a9
--- /dev/null
+++ b/test/ninja/action-rule-hash/subdir/emit.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2014 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+f = open(sys.argv[1], 'wb')
+f.write('int main() {\n')
+f.write(' return 0;\n')
+f.write('}\n')
+f.close()