summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Chromium Automerger <chromium-automerger@android>2014-07-31 02:31:31 +0000
committerAndroid Chromium Automerger <chromium-automerger@android>2014-07-31 02:31:31 +0000
commit184447a86e6c01ecb2a0b9bed8d08290d252c989 (patch)
treef6f76ef714a625269daf1492f9016a5c576579a1
parentca71079834e202e1e137343d755322b4795f6084 (diff)
parentac2684beed6e8ca04ac5f837c9db869eefec7bb5 (diff)
downloadgyp-184447a86e6c01ecb2a0b9bed8d08290d252c989.tar.gz
Merge tools/gyp from https://chromium.googlesource.com/external/gyp.git at ac2684beed6e8ca04ac5f837c9db869eefec7bb5
This commit was generated by merge_from_chromium.py. Change-Id: I36616486742ab4c073a2b5e3baf84a21d3150b97
-rw-r--r--pylib/gyp/generator/analyzer.py39
-rw-r--r--pylib/gyp/input.py38
-rw-r--r--pylib/gyp/xcodeproj_file.py4
-rw-r--r--test/analyzer/gyptest-analyzer.new.py199
-rw-r--r--test/mac/gyptest-loadable-module-bundle-product-extension.py28
-rw-r--r--test/mac/loadable-module-bundle-product-extension/src.cc7
-rw-r--r--test/mac/loadable-module-bundle-product-extension/test.gyp24
7 files changed, 314 insertions, 25 deletions
diff --git a/pylib/gyp/generator/analyzer.py b/pylib/gyp/generator/analyzer.py
index 6f3b610c..dc55da67 100644
--- a/pylib/gyp/generator/analyzer.py
+++ b/pylib/gyp/generator/analyzer.py
@@ -9,11 +9,15 @@ and targets to search for. The following keys are supported:
files: list of paths (relative) of the files to search for.
targets: list of targets to search for. The target names are unqualified.
-The following (as JSON) is output:
+The following is output:
error: only supplied if there is an error.
+warning: only supplied if there is a warning.
targets: the set of targets passed in via targets that either directly or
indirectly depend upon the set of paths supplied in files.
status: indicates if any of the supplied files matched at least one target.
+
+If the generator flag analyzer_output_path is specified, output is written
+there. Otherwise output is written to stdout.
"""
import gyp.common
@@ -293,6 +297,20 @@ def _GetTargetsDependingOn(all_targets, possible_targets):
found.append(gyp.common.ParseQualifiedTarget(target)[1])
return found
+def _WriteOutput(params, **values):
+ """Writes the output, either to stdout or a file is specified."""
+ output_path = params.get('generator_flags', {}).get(
+ 'analyzer_output_path', None)
+ if not output_path:
+ print json.dumps(values)
+ return
+ try:
+ f = open(output_path, 'w')
+ f.write(json.dumps(values) + '\n')
+ f.close()
+ except IOError as e:
+ print 'Error writing to output file', output_path, str(e)
+
def CalculateVariables(default_variables, params):
"""Calculate additional variables for use in the build (called by gyp)."""
flavor = gyp.common.GetFlavor(params)
@@ -342,6 +360,7 @@ def GenerateOutput(target_list, target_dicts, data, params):
print found_dependency_string if matched else no_dependency_string
return
+ warning = None
if matched:
unqualified_mapping = _GetUnqualifiedToQualifiedMapping(
all_targets, config.targets)
@@ -350,15 +369,21 @@ def GenerateOutput(target_list, target_dicts, data, params):
for target in config.targets:
if not target in unqualified_mapping:
not_found.append(target)
- raise Exception('Unable to find all targets: ' + str(not_found))
- qualified_targets = [unqualified_mapping[x] for x in config.targets]
+ warning = 'Unable to find all targets: ' + str(not_found)
+ qualified_targets = []
+ for target in config.targets:
+ if target in unqualified_mapping:
+ qualified_targets.append(unqualified_mapping[target])
output_targets = _GetTargetsDependingOn(all_targets, qualified_targets)
else:
output_targets = []
- print json.dumps(
- {'targets': output_targets,
- 'status': found_dependency_string if matched else no_dependency_string })
+ result_dict = { 'targets': output_targets,
+ 'status': found_dependency_string if matched else
+ no_dependency_string }
+ if warning:
+ result_dict['warning'] = warning
+ _WriteOutput(params, **result_dict)
except Exception as e:
- print json.dumps({'error': str(e)})
+ _WriteOutput(params, error=str(e))
diff --git a/pylib/gyp/input.py b/pylib/gyp/input.py
index e0813f35..bb853a54 100644
--- a/pylib/gyp/input.py
+++ b/pylib/gyp/input.py
@@ -994,23 +994,29 @@ def ExpandVariables(input, phase, variables, build_file):
# Prepare for the next match iteration.
input_str = output
- # Look for more matches now that we've replaced some, to deal with
- # expanding local variables (variables defined in the same
- # variables block as this one).
- gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Found output %r, recursing.", output)
- if type(output) is list:
- if output and type(output[0]) is list:
- # Leave output alone if it's a list of lists.
- # We don't want such lists to be stringified.
- pass
- else:
- new_output = []
- for item in output:
- new_output.append(
- ExpandVariables(item, phase, variables, build_file))
- output = new_output
+ if output == input:
+ gyp.DebugOutput(gyp.DEBUG_VARIABLES,
+ "Found only identity matches on %r, avoiding infinite "
+ "recursion.",
+ output)
else:
- output = ExpandVariables(output, phase, variables, build_file)
+ # Look for more matches now that we've replaced some, to deal with
+ # expanding local variables (variables defined in the same
+ # variables block as this one).
+ gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Found output %r, recursing.", output)
+ if type(output) is list:
+ if output and type(output[0]) is list:
+ # Leave output alone if it's a list of lists.
+ # We don't want such lists to be stringified.
+ pass
+ else:
+ new_output = []
+ for item in output:
+ new_output.append(
+ ExpandVariables(item, phase, variables, build_file))
+ output = new_output
+ else:
+ output = ExpandVariables(output, phase, variables, build_file)
# Convert all strings that are canonically-represented integers into integers.
if type(output) is list:
diff --git a/pylib/gyp/xcodeproj_file.py b/pylib/gyp/xcodeproj_file.py
index 2b91f5fb..7c7f1fbd 100644
--- a/pylib/gyp/xcodeproj_file.py
+++ b/pylib/gyp/xcodeproj_file.py
@@ -2316,11 +2316,11 @@ class PBXNativeTarget(XCTarget):
if force_extension is not None:
# If it's a wrapper (bundle), set WRAPPER_EXTENSION.
+ # Extension override.
+ suffix = '.' + force_extension
if filetype.startswith('wrapper.'):
self.SetBuildSetting('WRAPPER_EXTENSION', force_extension)
else:
- # Extension override.
- suffix = '.' + force_extension
self.SetBuildSetting('EXECUTABLE_EXTENSION', force_extension)
if filetype.startswith('compiled.mach-o.executable'):
diff --git a/test/analyzer/gyptest-analyzer.new.py b/test/analyzer/gyptest-analyzer.new.py
new file mode 100644
index 00000000..db7e1251
--- /dev/null
+++ b/test/analyzer/gyptest-analyzer.new.py
@@ -0,0 +1,199 @@
+#!/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.
+
+"""Tests for analyzer
+"""
+
+import json
+import TestGyp
+
+# TODO(sky): when done migrating recipes rename to gyptest-analyzer and nuke
+# existing gyptest-analyzer.
+
+found = 'Found dependency'
+not_found = 'No dependencies'
+
+def _CreateTestFile(files, targets):
+ f = open('test_file', 'w')
+ to_write = {'files': files, 'targets': targets }
+ json.dump(to_write, f)
+ f.close()
+
+def _CreateBogusTestFile():
+ f = open('test_file','w')
+ f.write('bogus')
+ f.close()
+
+def _ReadOutputFileContents():
+ f = open('analyzer_output', 'r')
+ result = json.load(f)
+ f.close()
+ return result
+
+# NOTE: this would be clearer if it subclassed TestGypCustom, but that trips
+# over a bug in pylint (E1002).
+test = TestGyp.TestGypCustom(format='analyzer')
+
+def run_analyzer(*args, **kw):
+ """Runs the test specifying a particular config and output path."""
+ args += ('-Gconfig_path=test_file',
+ '-Ganalyzer_output_path=analyzer_output')
+ test.run_gyp('test.gyp', *args, **kw)
+
+def EnsureContains(targets=set(), matched=False):
+ """Verifies output contains |targets| and |direct_targets|."""
+ result = _ReadOutputFileContents()
+ if result.get('error', None):
+ print 'unexpected error', result.get('error')
+ test.fail_test()
+
+ if result.get('warning', None):
+ print 'unexpected warning', result.get('warning')
+ test.fail_test()
+
+ actual_targets = set(result['targets'])
+ if actual_targets != targets:
+ print 'actual targets:', actual_targets, '\nexpected targets:', targets
+ test.fail_test()
+
+ if matched and result['status'] != found:
+ print 'expected', found, 'got', result['status']
+ test.fail_test()
+ elif not matched and result['status'] != not_found:
+ print 'expected', not_found, 'got', result['status']
+ test.fail_test()
+
+def EnsureError(expected_error_string):
+ """Verifies output contains the error string."""
+ result = _ReadOutputFileContents()
+ if result.get('error', '').find(expected_error_string) == -1:
+ print 'actual error:', result.get('error', ''), '\nexpected error:', \
+ expected_error_string
+ test.fail_test()
+
+def EnsureWarning(expected_warning_string):
+ """Verifies output contains the warning string."""
+ result = _ReadOutputFileContents()
+ if result.get('warning', '').find(expected_warning_string) == -1:
+ print 'actual warning:', result.get('warning', ''), \
+ '\nexpected warning:', expected_warning_string
+ test.fail_test()
+
+# Verifies file_path must be specified.
+test.run_gyp('test.gyp',
+ stdout='Must specify files to analyze via file_path generator '
+ 'flag\n')
+
+# Verifies config_path must point to a valid file.
+test.run_gyp('test.gyp', '-Gconfig_path=bogus_file',
+ '-Ganalyzer_output_path=analyzer_output')
+EnsureError('Unable to open file bogus_file')
+
+# Verify get error when bad target is specified.
+_CreateTestFile(['exe2.c'], ['bad_target'])
+run_analyzer()
+EnsureWarning('Unable to find all targets')
+
+# Verifies config_path must point to a valid json file.
+_CreateBogusTestFile()
+run_analyzer()
+EnsureError('Unable to parse config file test_file')
+
+# Trivial test of a source.
+_CreateTestFile(['foo.c'], [])
+run_analyzer()
+EnsureContains(matched=True)
+
+# Conditional source that is excluded.
+_CreateTestFile(['conditional_source.c'], [])
+run_analyzer()
+EnsureContains(matched=False)
+
+# Conditional source that is included by way of argument.
+_CreateTestFile(['conditional_source.c'], [])
+run_analyzer('-Dtest_variable=1')
+EnsureContains(matched=True)
+
+# Two unknown files.
+_CreateTestFile(['unknown1.c', 'unoknow2.cc'], [])
+run_analyzer()
+EnsureContains()
+
+# Two unknown files.
+_CreateTestFile(['unknown1.c', 'subdir/subdir_sourcex.c'], [])
+run_analyzer()
+EnsureContains()
+
+# Included dependency
+_CreateTestFile(['unknown1.c', 'subdir/subdir_source.c'], [])
+run_analyzer()
+EnsureContains(matched=True)
+
+# Included inputs to actions.
+_CreateTestFile(['action_input.c'], [])
+run_analyzer()
+EnsureContains(matched=True)
+
+# Don't consider outputs.
+_CreateTestFile(['action_output.c'], [])
+run_analyzer()
+EnsureContains(matched=False)
+
+# Rule inputs.
+_CreateTestFile(['rule_input.c'], [])
+run_analyzer()
+EnsureContains(matched=True)
+
+# Ignore path specified with PRODUCT_DIR.
+_CreateTestFile(['product_dir_input.c'], [])
+run_analyzer()
+EnsureContains(matched=False)
+
+# Path specified via a variable.
+_CreateTestFile(['subdir/subdir_source2.c'], [])
+run_analyzer()
+EnsureContains(matched=True)
+
+# Verifies paths with // are fixed up correctly.
+_CreateTestFile(['parent_source.c'], [])
+run_analyzer()
+EnsureContains(matched=True)
+
+# Verifies relative paths are resolved correctly.
+_CreateTestFile(['subdir/subdir_source.h'], [])
+run_analyzer()
+EnsureContains(matched=True)
+
+# Various permutations when passing in targets.
+_CreateTestFile(['exe2.c', 'subdir/subdir2b_source.c'], ['exe', 'exe3'])
+run_analyzer()
+EnsureContains(matched=True, targets={'exe3'})
+
+_CreateTestFile(['exe2.c', 'subdir/subdir2b_source.c'], ['exe'])
+run_analyzer()
+EnsureContains(matched=True)
+
+# Verifies duplicates are ignored.
+_CreateTestFile(['exe2.c', 'subdir/subdir2b_source.c'], ['exe', 'exe'])
+run_analyzer()
+EnsureContains(matched=True)
+
+_CreateTestFile(['exe2.c'], ['exe'])
+run_analyzer()
+EnsureContains(matched=True)
+
+_CreateTestFile(['exe2.c'], [])
+run_analyzer()
+EnsureContains(matched=True)
+
+_CreateTestFile(['subdir/subdir2b_source.c', 'exe2.c'], [])
+run_analyzer()
+EnsureContains(matched=True)
+
+_CreateTestFile(['exe2.c'], [])
+run_analyzer()
+EnsureContains(matched=True)
+
+test.pass_test()
diff --git a/test/mac/gyptest-loadable-module-bundle-product-extension.py b/test/mac/gyptest-loadable-module-bundle-product-extension.py
new file mode 100644
index 00000000..90c20837
--- /dev/null
+++ b/test/mac/gyptest-loadable-module-bundle-product-extension.py
@@ -0,0 +1,28 @@
+#!/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.
+
+"""
+Tests that loadable_modules don't collide when using the same name with
+different file extensions.
+"""
+
+import TestGyp
+
+import os
+import struct
+import sys
+
+if sys.platform == 'darwin':
+ test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'])
+
+ CHDIR = 'loadable-module-bundle-product-extension'
+ test.run_gyp('test.gyp', chdir=CHDIR)
+ test.build('test.gyp', test.ALL, chdir=CHDIR)
+
+ test.must_exist(test.built_file_path('Collide.foo', chdir=CHDIR))
+ test.must_exist(test.built_file_path('Collide.bar', chdir=CHDIR))
+
+ test.pass_test()
diff --git a/test/mac/loadable-module-bundle-product-extension/src.cc b/test/mac/loadable-module-bundle-product-extension/src.cc
new file mode 100644
index 00000000..3d878e96
--- /dev/null
+++ b/test/mac/loadable-module-bundle-product-extension/src.cc
@@ -0,0 +1,7 @@
+// 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.
+
+int test() {
+ return 1337;
+}
diff --git a/test/mac/loadable-module-bundle-product-extension/test.gyp b/test/mac/loadable-module-bundle-product-extension/test.gyp
new file mode 100644
index 00000000..684a2c02
--- /dev/null
+++ b/test/mac/loadable-module-bundle-product-extension/test.gyp
@@ -0,0 +1,24 @@
+# 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': 'test',
+ 'type': 'none',
+ 'dependencies': ['child_one', 'child_two'],
+ }, {
+ 'target_name': 'child_one',
+ 'product_name': 'Collide',
+ 'product_extension': 'bar',
+ 'sources': ['src.cc'],
+ 'type': 'loadable_module',
+ 'mac_bundle': 1,
+ }, {
+ 'target_name': 'child_two',
+ 'product_name': 'Collide',
+ 'product_extension': 'foo',
+ 'sources': ['src.cc'],
+ 'type': 'loadable_module',
+ 'mac_bundle': 1,
+ }],
+}