summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Chromium Automerger <chromium-automerger@android>2014-06-06 10:22:41 +0000
committerAndroid Chromium Automerger <chromium-automerger@android>2014-06-06 10:22:41 +0000
commit1ab1f9a545b0f568929f38e6952b39055276efef (patch)
tree8f35e94e2eef8136e4fc5ba567ddd737d7d26b68
parent12fc9e9c1b483568b72ed83628097dcbe3aa6684 (diff)
parent0ff4e1aa19641cda58e3ed98399e0d96e6ccd7c2 (diff)
downloadgyp-1ab1f9a545b0f568929f38e6952b39055276efef.tar.gz
Merge tools/gyp from https://chromium.googlesource.com/external/gyp.git at 0ff4e1aa19641cda58e3ed98399e0d96e6ccd7c2
This commit was generated by merge_from_chromium.py. Change-Id: I5cbee9e1d503218e58da79bf5bb37ccb08cbc750
-rwxr-xr-xbuildbot/buildbot_run.py10
-rw-r--r--pylib/gyp/MSVSSettings.py4
-rw-r--r--pylib/gyp/generator/android.py15
-rw-r--r--pylib/gyp/generator/msvs.py35
-rwxr-xr-xpylib/gyp/win_tool.py7
-rw-r--r--test/android/file.in1
-rwxr-xr-xtest/android/gyptest-make-functions.py24
-rwxr-xr-xtest/android/gyptest-space-filenames.py19
-rw-r--r--test/android/make_functions.gyp31
-rw-r--r--test/android/space_filenames.gyp18
-rw-r--r--test/ios/gyptest-xcode-ninja.py8
-rw-r--r--test/lib/TestGyp.py142
-rw-r--r--test/lib/TestWin.py101
-rwxr-xr-xtest/rules-dirname/gyptest-dirname.py19
-rw-r--r--test/rules-dirname/src/subdir/input-rule-dirname.gyp71
-rwxr-xr-xtest/rules/gyptest-all.py4
-rwxr-xr-xtest/rules/gyptest-default.py4
-rw-r--r--test/rules/src/actions.gyp1
-rw-r--r--test/rules/src/subdir2/both_rule_and_action_input.gyp50
-rw-r--r--test/rules/src/subdir2/program.c12
-rw-r--r--test/win/gyptest-midl-excluded.py22
-rw-r--r--test/win/gyptest-midl-rules.py4
-rw-r--r--test/win/idl-excluded/bad.idl6
-rw-r--r--test/win/idl-excluded/copy-file.py11
-rw-r--r--test/win/idl-excluded/idl-excluded.gyp58
-rw-r--r--test/win/idl-excluded/program.cc7
26 files changed, 616 insertions, 68 deletions
diff --git a/buildbot/buildbot_run.py b/buildbot/buildbot_run.py
index 979073c7..cc3a25ae 100755
--- a/buildbot/buildbot_run.py
+++ b/buildbot/buildbot_run.py
@@ -107,7 +107,7 @@ def PrepareAndroidTree():
cwd=ANDROID_DIR)
-def GypTestFormat(title, format=None, msvs_version=None):
+def GypTestFormat(title, format=None, msvs_version=None, tests=[]):
"""Run the gyp tests for a given format, emitting annotator tags.
See annotator docs at:
@@ -131,7 +131,7 @@ def GypTestFormat(title, format=None, msvs_version=None):
'--passed',
'--format', format,
'--path', CMAKE_BIN_DIR,
- '--chdir', 'trunk'])
+ '--chdir', 'trunk'] + tests)
if format == 'android':
# gyptest needs the environment setup from envsetup/lunch in order to build
# using the 'android' backend, so this is done in a single shell.
@@ -173,6 +173,12 @@ def GypBuild():
elif sys.platform == 'win32':
retcode += GypTestFormat('ninja')
if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-win64':
+ retcode += GypTestFormat('msvs-ninja-2012', format='msvs-ninja',
+ msvs_version='2012',
+ tests=[
+ 'test\generator-output\gyptest-actions.py',
+ 'test\generator-output\gyptest-relocate.py',
+ 'test\generator-output\gyptest-rules.py'])
retcode += GypTestFormat('msvs-2010', format='msvs', msvs_version='2010')
retcode += GypTestFormat('msvs-2012', format='msvs', msvs_version='2012')
else:
diff --git a/pylib/gyp/MSVSSettings.py b/pylib/gyp/MSVSSettings.py
index 205b3b5b..b4e0a789 100644
--- a/pylib/gyp/MSVSSettings.py
+++ b/pylib/gyp/MSVSSettings.py
@@ -417,11 +417,11 @@ def ConvertVCMacrosToMSBuild(s):
if '$' in s:
replace_map = {
'$(ConfigurationName)': '$(Configuration)',
- '$(InputDir)': '%(RootDir)%(Directory)',
+ '$(InputDir)': '%(RelativeDir)',
'$(InputExt)': '%(Extension)',
'$(InputFileName)': '%(Filename)%(Extension)',
'$(InputName)': '%(Filename)',
- '$(InputPath)': '%(FullPath)',
+ '$(InputPath)': '%(Identity)',
'$(ParentName)': '$(ProjectFileName)',
'$(PlatformName)': '$(Platform)',
'$(SafeInputName)': '%(Filename)',
diff --git a/pylib/gyp/generator/android.py b/pylib/gyp/generator/android.py
index 39884749..3c95143b 100644
--- a/pylib/gyp/generator/android.py
+++ b/pylib/gyp/generator/android.py
@@ -317,12 +317,19 @@ class AndroidMkWriter(object):
self.WriteLn('%s: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))'
% main_output)
+ # Don't allow spaces in input/output filenames, but make an exception for
+ # filenames which start with '$(' since it's okay for there to be spaces
+ # inside of make function/macro invocations.
for input in inputs:
- assert ' ' not in input, (
- "Spaces in action input filenames not supported (%s)" % input)
+ if not input.startswith('$(') and ' ' in input:
+ raise gyp.common.GypError(
+ 'Action input filename "%s" in target %s contains a space' %
+ (input, self.target))
for output in outputs:
- assert ' ' not in output, (
- "Spaces in action output filenames not supported (%s)" % output)
+ if not output.startswith('$(') and ' ' in output:
+ raise gyp.common.GypError(
+ 'Action output filename "%s" in target %s contains a space' %
+ (output, self.target))
self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' %
(main_output, ' '.join(map(self.LocalPathify, inputs))))
diff --git a/pylib/gyp/generator/msvs.py b/pylib/gyp/generator/msvs.py
index f361571c..a4ebd7c5 100644
--- a/pylib/gyp/generator/msvs.py
+++ b/pylib/gyp/generator/msvs.py
@@ -12,6 +12,7 @@ import sys
import gyp.common
import gyp.easy_xml as easy_xml
+import gyp.generator.ninja as ninja_generator
import gyp.MSVSNew as MSVSNew
import gyp.MSVSProject as MSVSProject
import gyp.MSVSSettings as MSVSSettings
@@ -284,7 +285,7 @@ def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path,
if [x for x in cmd if '$(InputDir)' in x]:
input_dir_preamble = (
'set INPUTDIR=$(InputDir)\n'
- 'set INPUTDIR=%INPUTDIR:$(ProjectDir)=%\n'
+ 'if NOT DEFINED INPUTDIR set INPUTDIR=.\\\n'
'set INPUTDIR=%INPUTDIR:~0,-1%\n'
)
else:
@@ -819,17 +820,21 @@ def _GenerateRulesForMSVS(p, output_dir, options, spec,
def _AdjustSourcesForRules(spec, rules, sources, excluded_sources):
# Add outputs generated by each rule (if applicable).
for rule in rules:
- # Done if not processing outputs as sources.
- if int(rule.get('process_outputs_as_sources', False)):
- # Add in the outputs from this rule.
- trigger_files = _FindRuleTriggerFiles(rule, sources)
- for trigger_file in trigger_files:
+ # Add in the outputs from this rule.
+ trigger_files = _FindRuleTriggerFiles(rule, sources)
+ for trigger_file in trigger_files:
+ # Remove trigger_file from excluded_sources to let the rule be triggered
+ # (e.g. rule trigger ax_enums.idl is added to excluded_sources
+ # because it's also in an action's inputs in the same project)
+ excluded_sources.discard(_FixPath(trigger_file))
+ # Done if not processing outputs as sources.
+ if int(rule.get('process_outputs_as_sources', False)):
inputs, outputs = _RuleInputsAndOutputs(rule, trigger_file)
inputs = OrderedSet(_FixPaths(inputs))
outputs = OrderedSet(_FixPaths(outputs))
inputs.remove(_FixPath(trigger_file))
sources.update(inputs)
- if spec['type'] != 'none' and not spec.get('msvs_external_builder'):
+ if not spec.get('msvs_external_builder'):
excluded_sources.update(inputs)
sources.update(outputs)
@@ -1388,7 +1393,7 @@ def _PrepareListOfSources(spec, generator_flags, gyp_file):
# Add all inputs to sources and excluded sources.
inputs = OrderedSet(inputs)
sources.update(inputs)
- if spec['type'] != 'none' and not spec.get('msvs_external_builder'):
+ if not spec.get('msvs_external_builder'):
excluded_sources.update(inputs)
if int(a.get('process_outputs_as_sources', False)):
_AddNormalizedSources(sources, a.get('outputs', []))
@@ -1783,7 +1788,7 @@ def _CreateProjectObjects(target_list, target_dicts, options, msvs_version):
return projects
-def _InitNinjaFlavor(options, target_list, target_dicts):
+def _InitNinjaFlavor(params, target_list, target_dicts):
"""Initialize targets for the ninja flavor.
This sets up the necessary variables in the targets to generate msvs projects
@@ -1791,7 +1796,7 @@ def _InitNinjaFlavor(options, target_list, target_dicts):
if they have not been set. This allows individual specs to override the
default values initialized here.
Arguments:
- options: Options provided to the generator.
+ params: Params provided to the generator.
target_list: List of target pairs: 'base/base.gyp:base'.
target_dicts: Dict of target properties keyed on target pair.
"""
@@ -1805,8 +1810,12 @@ def _InitNinjaFlavor(options, target_list, target_dicts):
spec['msvs_external_builder'] = 'ninja'
if not spec.get('msvs_external_builder_out_dir'):
- spec['msvs_external_builder_out_dir'] = \
- options.depth + '/out/$(Configuration)'
+ gyp_file, _, _ = gyp.common.ParseQualifiedTarget(qualified_target)
+ gyp_dir = os.path.dirname(gyp_file)
+ spec['msvs_external_builder_out_dir'] = os.path.join(
+ gyp.common.RelativePath(params['options'].toplevel_dir, gyp_dir),
+ ninja_generator.ComputeOutputDir(params),
+ '$(Configuration)')
if not spec.get('msvs_external_builder_build_cmd'):
spec['msvs_external_builder_build_cmd'] = [
path_to_ninja,
@@ -1901,7 +1910,7 @@ def GenerateOutput(target_list, target_dicts, data, params):
# Optionally configure each spec to use ninja as the external builder.
if params.get('flavor') == 'ninja':
- _InitNinjaFlavor(options, target_list, target_dicts)
+ _InitNinjaFlavor(params, target_list, target_dicts)
# Prepare the set of configurations.
configs = set()
diff --git a/pylib/gyp/win_tool.py b/pylib/gyp/win_tool.py
index 7e2d968e..44e1b076 100755
--- a/pylib/gyp/win_tool.py
+++ b/pylib/gyp/win_tool.py
@@ -248,10 +248,11 @@ class WinTool(object):
# Processing C:\Program Files (x86)\Microsoft SDKs\...\include\objidl.idl
# objidl.idl
lines = out.splitlines()
- prefix = 'Processing '
- processing = set(os.path.basename(x) for x in lines if x.startswith(prefix))
+ prefixes = ('Processing ', '64 bit Processing ')
+ processing = set(os.path.basename(x)
+ for x in lines if x.startswith(prefixes))
for line in lines:
- if not line.startswith(prefix) and line not in processing:
+ if not line.startswith(prefixes) and line not in processing:
print line
return popen.returncode
diff --git a/test/android/file.in b/test/android/file.in
new file mode 100644
index 00000000..68016f01
--- /dev/null
+++ b/test/android/file.in
@@ -0,0 +1 @@
+A boring test file
diff --git a/test/android/gyptest-make-functions.py b/test/android/gyptest-make-functions.py
new file mode 100755
index 00000000..cdf0e0ed
--- /dev/null
+++ b/test/android/gyptest-make-functions.py
@@ -0,0 +1,24 @@
+#!/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.
+
+"""
+Verifies that it's possible for gyp actions to use the result of calling a make
+function with "$()".
+"""
+
+import TestGyp
+
+test = TestGyp.TestGyp(formats=['android'])
+
+test.run_gyp('make_functions.gyp')
+
+test.build('make_functions.gyp', test.ALL)
+
+file_content = 'A boring test file\n'
+test.built_file_must_match('file.in', file_content)
+test.built_file_must_match('file.out', file_content)
+
+test.pass_test()
diff --git a/test/android/gyptest-space-filenames.py b/test/android/gyptest-space-filenames.py
new file mode 100755
index 00000000..c6caf264
--- /dev/null
+++ b/test/android/gyptest-space-filenames.py
@@ -0,0 +1,19 @@
+#!/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.
+
+"""
+Verifies that action input/output filenames with spaces are rejected.
+"""
+
+import TestGyp
+
+test = TestGyp.TestGyp(formats=['android'])
+
+stderr = ('gyp: Action input filename "name with spaces" in target do_actions '
+ 'contains a space\n')
+test.run_gyp('space_filenames.gyp', status=1, stderr=stderr)
+
+test.pass_test()
diff --git a/test/android/make_functions.gyp b/test/android/make_functions.gyp
new file mode 100644
index 00000000..4b617cc9
--- /dev/null
+++ b/test/android/make_functions.gyp
@@ -0,0 +1,31 @@
+# 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': 'file-in',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)',
+ 'files': [ 'file.in' ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'file-out',
+ 'type': 'none',
+ 'dependencies': [ 'file-in' ],
+ 'actions': [
+ {
+ 'action_name': 'copy-file',
+ 'inputs': [ '$(strip <(PRODUCT_DIR)/file.in)' ],
+ 'outputs': [ '<(PRODUCT_DIR)/file.out' ],
+ 'action': [ 'cp', '$(strip <(PRODUCT_DIR)/file.in)', '<(PRODUCT_DIR)/file.out' ],
+ }
+ ],
+ },
+ ],
+}
diff --git a/test/android/space_filenames.gyp b/test/android/space_filenames.gyp
new file mode 100644
index 00000000..487ac551
--- /dev/null
+++ b/test/android/space_filenames.gyp
@@ -0,0 +1,18 @@
+# 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': 'do_actions',
+ 'type': 'none',
+ 'actions': [{
+ 'action_name': 'should_be_forbidden',
+ 'inputs': [ 'name with spaces' ],
+ 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/name with spaces' ],
+ 'action': [ 'true' ],
+ }],
+ },
+ ],
+}
diff --git a/test/ios/gyptest-xcode-ninja.py b/test/ios/gyptest-xcode-ninja.py
index d2ff3338..609db8c9 100644
--- a/test/ios/gyptest-xcode-ninja.py
+++ b/test/ios/gyptest-xcode-ninja.py
@@ -16,12 +16,8 @@ import sys
if sys.platform == 'darwin':
test = TestGyp.TestGyp(formats=['xcode'])
- # Run ninja first
- test.format = 'ninja'
- test.run_gyp('test.gyp', chdir='app-bundle')
-
- # Then run xcode-ninja
- test.format = 'xcode-ninja'
+ # Run ninja and xcode-ninja
+ test.formats = ['ninja', 'xcode-ninja']
test.run_gyp('test.gyp', chdir='app-bundle')
# If it builds the target, it works.
diff --git a/test/lib/TestGyp.py b/test/lib/TestGyp.py
index 36b6281c..cde04cac 100644
--- a/test/lib/TestGyp.py
+++ b/test/lib/TestGyp.py
@@ -78,6 +78,7 @@ class TestGypBase(TestCommon.TestCommon):
configuration and to run executables generated by those builds.
"""
+ formats = []
build_tool = None
build_tool_list = []
@@ -113,6 +114,8 @@ class TestGypBase(TestCommon.TestCommon):
self.gyp = os.path.abspath(gyp)
self.no_parallel = False
+ self.formats = [self.format]
+
self.initialize_build_tool()
kw.setdefault('match', TestCommon.match_exact)
@@ -130,10 +133,11 @@ class TestGypBase(TestCommon.TestCommon):
super(TestGypBase, self).__init__(*args, **kw)
+ real_format = self.format.split('-')[-1]
excluded_formats = set([f for f in formats if f[0] == '!'])
included_formats = set(formats) - excluded_formats
- if ('!'+self.format in excluded_formats or
- included_formats and self.format not in included_formats):
+ if ('!'+real_format in excluded_formats or
+ included_formats and real_format not in included_formats):
msg = 'Invalid test for %r format; skipping test.\n'
self.skip_test(msg % self.format)
@@ -272,9 +276,13 @@ class TestGypBase(TestCommon.TestCommon):
# TODO: --depth=. works around Chromium-specific tree climbing.
depth = kw.pop('depth', '.')
- run_args = ['--depth='+depth, '--format='+self.format, gyp_file]
+ run_args = ['--depth='+depth]
+ run_args.extend(['--format='+f for f in self.formats]);
+ run_args.append(gyp_file)
if self.no_parallel:
run_args += ['--no-parallel']
+ # TODO: if extra_args contains a '--build' flag
+ # we really want that to only apply to the last format (self.format).
run_args.extend(self.extra_args)
run_args.extend(args)
return self.run(program=self.gyp, arguments=run_args, **kw)
@@ -747,6 +755,53 @@ def ConvertToCygpath(path):
return path
+def FindMSBuildInstallation(msvs_version = 'auto'):
+ """Returns path to MSBuild for msvs_version or latest available.
+
+ Looks in the registry to find install location of MSBuild.
+ MSBuild before v4.0 will not build c++ projects, so only use newer versions.
+ """
+ import TestWin
+ registry = TestWin.Registry()
+
+ msvs_to_msbuild = {
+ '2013': r'12.0',
+ '2012': r'4.0', # Really v4.0.30319 which comes with .NET 4.5.
+ '2010': r'4.0'}
+
+ msbuild_basekey = r'HKLM\SOFTWARE\Microsoft\MSBuild\ToolsVersions'
+ if not registry.KeyExists(msbuild_basekey):
+ print 'Error: could not find MSBuild base registry entry'
+ return None
+
+ msbuild_version = None
+ if msvs_version in msvs_to_msbuild:
+ msbuild_test_version = msvs_to_msbuild[msvs_version]
+ if registry.KeyExists(msbuild_basekey + '\\' + msbuild_test_version):
+ msbuild_version = msbuild_test_version
+ else:
+ print ('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" '
+ 'but corresponding MSBuild "%s" was not found.' %
+ (msvs_version, msbuild_version))
+ if not msbuild_version:
+ for msvs_version in sorted(msvs_to_msbuild, reverse=True):
+ msbuild_test_version = msvs_to_msbuild[msvs_version]
+ if registry.KeyExists(msbuild_basekey + '\\' + msbuild_test_version):
+ msbuild_version = msbuild_test_version
+ break
+ if not msbuild_version:
+ print 'Error: could not find MSBuild registry entry'
+ return None
+
+ msbuild_path = registry.GetValue(msbuild_basekey + '\\' + msbuild_version,
+ 'MSBuildToolsPath')
+ if not msbuild_path:
+ print 'Error: could not get MSBuild registry entry value'
+ return None
+
+ return os.path.join(msbuild_path, 'MSBuild.exe')
+
+
def FindVisualStudioInstallation():
"""Returns appropriate values for .build_tool and .uses_msbuild fields
of TestGypBase for Visual Studio.
@@ -772,39 +827,28 @@ def FindVisualStudioInstallation():
msvs_version = flag.split('=')[-1]
msvs_version = os.environ.get('GYP_MSVS_VERSION', msvs_version)
- build_tool = None
if msvs_version in possible_paths:
# Check that the path to the specified GYP_MSVS_VERSION exists.
path = possible_paths[msvs_version]
for r in possible_roots:
- bt = os.path.join(r, path)
- if os.path.exists(bt):
- build_tool = bt
+ build_tool = os.path.join(r, path)
+ if os.path.exists(build_tool):
uses_msbuild = msvs_version >= '2010'
- return build_tool, uses_msbuild
+ msbuild_path = FindMSBuildInstallation(msvs_version)
+ return build_tool, uses_msbuild, msbuild_path
else:
print ('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" '
'but corresponding "%s" was not found.' % (msvs_version, path))
- if build_tool:
- # We found 'devenv' on the path, use that and try to guess the version.
- for version, path in possible_paths.iteritems():
- if build_tool.find(path) >= 0:
- uses_msbuild = version >= '2010'
- return build_tool, uses_msbuild
- else:
- # If not, assume not MSBuild.
- uses_msbuild = False
- return build_tool, uses_msbuild
# Neither GYP_MSVS_VERSION nor the path help us out. Iterate through
# the choices looking for a match.
for version in sorted(possible_paths, reverse=True):
path = possible_paths[version]
for r in possible_roots:
- bt = os.path.join(r, path)
- if os.path.exists(bt):
- build_tool = bt
+ build_tool = os.path.join(r, path)
+ if os.path.exists(build_tool):
uses_msbuild = msvs_version >= '2010'
- return build_tool, uses_msbuild
+ msbuild_path = FindMSBuildInstallation(msvs_version)
+ return build_tool, uses_msbuild, msbuild_path
print 'Error: could not find devenv'
sys.exit(1)
@@ -822,7 +866,8 @@ class TestGypOnMSToolchain(TestGypBase):
def initialize_build_tool(self):
super(TestGypOnMSToolchain, self).initialize_build_tool()
if sys.platform in ('win32', 'cygwin'):
- self.devenv_path, self.uses_msbuild = FindVisualStudioInstallation()
+ build_tools = FindVisualStudioInstallation()
+ self.devenv_path, self.uses_msbuild, self.msbuild_path = build_tools
self.vsvars_path = TestGypOnMSToolchain._ComputeVsvarsPath(
self.devenv_path)
@@ -1002,6 +1047,56 @@ class TestGypMSVS(TestGypOnMSToolchain):
return self.workpath(*result)
+class TestGypMSVSNinja(TestGypNinja):
+ """
+ Subclass for testing the GYP Visual Studio Ninja generator.
+ """
+ format = 'msvs-ninja'
+
+ def initialize_build_tool(self):
+ super(TestGypMSVSNinja, self).initialize_build_tool()
+ # When using '--build', make sure ninja is first in the format list.
+ self.formats.insert(0, 'ninja')
+
+ def build(self, gyp_file, target=None, rebuild=False, clean=False, **kw):
+ """
+ Runs a Visual Studio build using the configuration generated
+ from the specified gyp_file.
+ """
+ arguments = kw.get('arguments', [])[:]
+ if target in (None, self.ALL, self.DEFAULT):
+ # Note: the Visual Studio generator doesn't add an explicit 'all' target.
+ # This will build each project. This will work if projects are hermetic,
+ # but may fail if they are not (a project may run more than once).
+ # It would be nice to supply an all.metaproj for MSBuild.
+ arguments.extend([gyp_file.replace('.gyp', '.sln')])
+ else:
+ # MSBuild documentation claims that one can specify a sln but then build a
+ # project target like 'msbuild a.sln /t:proj:target' but this format only
+ # supports 'Clean', 'Rebuild', and 'Publish' (with none meaning Default).
+ # This limitation is due to the .sln -> .sln.metaproj conversion.
+ # The ':' is not special, 'proj:target' is a target in the metaproj.
+ arguments.extend([target+'.vcxproj'])
+
+ if clean:
+ build = 'Clean'
+ elif rebuild:
+ build = 'Rebuild'
+ else:
+ build = 'Build'
+ arguments.extend(['/target:'+build])
+ configuration = self.configuration_buildname()
+ config = configuration.split('|')
+ arguments.extend(['/property:Configuration='+config[0]])
+ if len(config) > 1:
+ arguments.extend(['/property:Platform='+config[1]])
+ arguments.extend(['/property:BuildInParallel=false'])
+ arguments.extend(['/verbosity:minimal'])
+
+ kw['arguments'] = arguments
+ return self.run(program=self.msbuild_path, **kw)
+
+
class TestGypXcode(TestGypBase):
"""
Subclass for testing the GYP Xcode generator.
@@ -1118,6 +1213,7 @@ format_class_list = [
TestGypCMake,
TestGypMake,
TestGypMSVS,
+ TestGypMSVSNinja,
TestGypNinja,
TestGypXcode,
]
diff --git a/test/lib/TestWin.py b/test/lib/TestWin.py
new file mode 100644
index 00000000..1571c851
--- /dev/null
+++ b/test/lib/TestWin.py
@@ -0,0 +1,101 @@
+# 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.
+
+"""
+TestWin.py: a collection of helpers for testing on Windows.
+"""
+
+import errno
+import os
+import re
+import sys
+import subprocess
+
+class Registry(object):
+ def _QueryBase(self, sysdir, key, value):
+ """Use reg.exe to read a particular key.
+
+ While ideally we might use the win32 module, we would like gyp to be
+ python neutral, so for instance cygwin python lacks this module.
+
+ Arguments:
+ sysdir: The system subdirectory to attempt to launch reg.exe from.
+ key: The registry key to read from.
+ value: The particular value to read.
+ Return:
+ stdout from reg.exe, or None for failure.
+ """
+ # Skip if not on Windows or Python Win32 setup issue
+ if sys.platform not in ('win32', 'cygwin'):
+ return None
+ # Setup params to pass to and attempt to launch reg.exe
+ cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'),
+ 'query', key]
+ if value:
+ cmd.extend(['/v', value])
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ # Get the stdout from reg.exe, reading to the end so p.returncode is valid
+ # Note that the error text may be in [1] in some cases
+ text = p.communicate()[0]
+ # Check return code from reg.exe; officially 0==success and 1==error
+ if p.returncode:
+ return None
+ return text
+
+ def Query(self, key, value=None):
+ """Use reg.exe to read a particular key through _QueryBase.
+
+ First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If
+ that fails, it falls back to System32. Sysnative is available on Vista and
+ up and available on Windows Server 2003 and XP through KB patch 942589. Note
+ that Sysnative will always fail if using 64-bit python due to it being a
+ virtual directory and System32 will work correctly in the first place.
+
+ KB 942589 - http://support.microsoft.com/kb/942589/en-us.
+
+ Arguments:
+ key: The registry key.
+ value: The particular registry value to read (optional).
+ Return:
+ stdout from reg.exe, or None for failure.
+ """
+ text = None
+ try:
+ text = self._QueryBase('Sysnative', key, value)
+ except OSError, e:
+ if e.errno == errno.ENOENT:
+ text = self._QueryBase('System32', key, value)
+ else:
+ raise
+ return text
+
+ def GetValue(self, key, value):
+ """Use reg.exe to obtain the value of a registry key.
+
+ Args:
+ key: The registry key.
+ value: The particular registry value to read.
+ Return:
+ contents of the registry key's value, or None on failure.
+ """
+ text = self.Query(key, value)
+ if not text:
+ return None
+ # Extract value.
+ match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text)
+ if not match:
+ return None
+ return match.group(1)
+
+ def KeyExists(self, key):
+ """Use reg.exe to see if a key exists.
+
+ Args:
+ key: The registry key to check.
+ Return:
+ True if the key exists
+ """
+ if not self.Query(key):
+ return False
+ return True
diff --git a/test/rules-dirname/gyptest-dirname.py b/test/rules-dirname/gyptest-dirname.py
index 46f3a1b5..420b80f0 100755
--- a/test/rules-dirname/gyptest-dirname.py
+++ b/test/rules-dirname/gyptest-dirname.py
@@ -10,8 +10,9 @@ Verifies simple rules when using an explicit build target of 'all'.
import TestGyp
import os
+import sys
-test = TestGyp.TestGyp(formats=['make', 'ninja', 'android', 'xcode'])
+test = TestGyp.TestGyp(formats=['make', 'ninja', 'android', 'xcode', 'msvs'])
test.run_gyp('actions.gyp', chdir='src')
@@ -29,9 +30,21 @@ if test.format == 'xcode':
else:
chdir = 'relocate/src'
test.run_built_executable('gencc_int_output', chdir=chdir, stdout=expect)
+if test.format == 'msvs':
+ test.run_built_executable('gencc_int_output_external', chdir=chdir,
+ stdout=expect)
-test.must_match('relocate/src/subdir/foo/bar/baz.printed',
+test.must_match('relocate/src/subdir/foo/bar/baz.dirname',
os.path.join('foo', 'bar'))
-test.must_match('relocate/src/subdir/a/b/c.printed', os.path.join('a', 'b'))
+test.must_match('relocate/src/subdir/a/b/c.dirname',
+ os.path.join('a', 'b'))
+
+# FIXME the xcode and make generators incorrectly convert RULE_INPUT_PATH
+# to an absolute path, making the tests below fail!
+if test.format != 'xcode' and test.format != 'make':
+ test.must_match('relocate/src/subdir/foo/bar/baz.path',
+ os.path.join('foo', 'bar', 'baz.printvars'))
+ test.must_match('relocate/src/subdir/a/b/c.path',
+ os.path.join('a', 'b', 'c.printvars'))
test.pass_test()
diff --git a/test/rules-dirname/src/subdir/input-rule-dirname.gyp b/test/rules-dirname/src/subdir/input-rule-dirname.gyp
index 36676f12..da749a22 100644
--- a/test/rules-dirname/src/subdir/input-rule-dirname.gyp
+++ b/test/rules-dirname/src/subdir/input-rule-dirname.gyp
@@ -5,7 +5,7 @@
{
'targets': [
{
- 'target_name': 'print_rule_input_path',
+ 'target_name': 'print_rule_input_dirname',
'type': 'none',
'msvs_cygwin_shell': 0,
'sources': [
@@ -20,7 +20,7 @@
'printvars.py',
],
'outputs': [
- '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).printed',
+ '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).dirname',
],
'action': [
'python', '<@(_inputs)', '<(RULE_INPUT_DIRNAME)', '<@(_outputs)',
@@ -29,28 +29,43 @@
],
},
{
+ 'target_name': 'print_rule_input_path',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'foo/bar/baz.printvars',
+ 'a/b/c.printvars',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'printvars',
+ 'extension': 'printvars',
+ 'inputs': [
+ 'printvars.py',
+ ],
+ 'outputs': [
+ '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).path',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ },
+ ],
+ },
+ {
'target_name': 'gencc_int_output',
'type': 'executable',
'msvs_cygwin_shell': 0,
- 'msvs_cygwin_dirs': ['../../../../../../<(DEPTH)/third_party/cygwin'],
'sources': [
'nodir.gencc',
'foo/bar/baz.gencc',
'a/b/c.gencc',
- 'main.cc',
- ],
- 'conditions': [
- ['OS=="win"', {
- 'dependencies': [
- 'cygwin',
- ],
- }],
+ 'main.cc',
],
'rules': [
{
'rule_name': 'gencc',
'extension': 'gencc',
- 'msvs_external_rule': 1,
'inputs': [
'<(DEPTH)/copy-file.py',
],
@@ -69,6 +84,38 @@
['OS=="win"', {
'targets': [
{
+ 'target_name': 'gencc_int_output_external',
+ 'type': 'executable',
+ 'msvs_cygwin_shell': 0,
+ 'msvs_cygwin_dirs': ['../../../../../../<(DEPTH)/third_party/cygwin'],
+ 'sources': [
+ 'nodir.gencc',
+ 'foo/bar/baz.gencc',
+ 'a/b/c.gencc',
+ 'main.cc',
+ ],
+ 'dependencies': [
+ 'cygwin',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'gencc',
+ 'extension': 'gencc',
+ 'msvs_external_rule': 1,
+ 'inputs': [
+ '<(DEPTH)/copy-file.py',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).cc',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ {
'target_name': 'cygwin',
'type': 'none',
'actions': [
diff --git a/test/rules/gyptest-all.py b/test/rules/gyptest-all.py
index d869fd3a..99b2109a 100755
--- a/test/rules/gyptest-all.py
+++ b/test/rules/gyptest-all.py
@@ -50,6 +50,10 @@ test.must_match('relocate/src/subdir2/file2.out', 'Hello from file2.in\n')
test.must_match('relocate/src/subdir2/file1.out2', 'Hello from file1.in\n')
test.must_match('relocate/src/subdir2/file2.out2', 'Hello from file2.in\n')
+test.must_match('relocate/src/subdir2/file1.out4', 'Hello from file1.in\n')
+test.must_match('relocate/src/subdir2/file2.out4', 'Hello from file2.in\n')
+test.must_match('relocate/src/subdir2/file1.copy', 'Hello from file1.in\n')
+
test.must_match('relocate/src/external/file1.external_rules.out',
'Hello from file1.in\n')
test.must_match('relocate/src/external/file2.external_rules.out',
diff --git a/test/rules/gyptest-default.py b/test/rules/gyptest-default.py
index 117c53db..048c93ca 100755
--- a/test/rules/gyptest-default.py
+++ b/test/rules/gyptest-default.py
@@ -47,6 +47,10 @@ test.must_match('relocate/src/subdir2/file2.out', 'Hello from file2.in\n')
test.must_match('relocate/src/subdir2/file1.out2', 'Hello from file1.in\n')
test.must_match('relocate/src/subdir2/file2.out2', 'Hello from file2.in\n')
+test.must_match('relocate/src/subdir2/file1.out4', 'Hello from file1.in\n')
+test.must_match('relocate/src/subdir2/file2.out4', 'Hello from file2.in\n')
+test.must_match('relocate/src/subdir2/file1.copy', 'Hello from file1.in\n')
+
test.must_match('relocate/src/external/file1.external_rules.out',
'Hello from file1.in\n')
test.must_match('relocate/src/external/file2.external_rules.out',
diff --git a/test/rules/src/actions.gyp b/test/rules/src/actions.gyp
index 5c0a40b0..84376a71 100644
--- a/test/rules/src/actions.gyp
+++ b/test/rules/src/actions.gyp
@@ -9,6 +9,7 @@
'type': 'none',
'dependencies': [
'subdir1/executable.gyp:*',
+ 'subdir2/both_rule_and_action_input.gyp:*',
'subdir2/never_used.gyp:*',
'subdir2/no_inputs.gyp:*',
'subdir2/no_action.gyp:*',
diff --git a/test/rules/src/subdir2/both_rule_and_action_input.gyp b/test/rules/src/subdir2/both_rule_and_action_input.gyp
new file mode 100644
index 00000000..e5e6f3ec
--- /dev/null
+++ b/test/rules/src/subdir2/both_rule_and_action_input.gyp
@@ -0,0 +1,50 @@
+# 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 if a rule input is also an action input, both the rule and action
+# are executed
+{
+ 'targets': [
+ {
+ 'target_name': 'files_both_rule_and_action_input',
+ 'type': 'executable',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'program.c',
+ 'file1.in',
+ 'file2.in',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'copy_file',
+ 'extension': 'in',
+ 'inputs': [
+ '../copy-file.py',
+ ],
+ 'outputs': [
+ '<(RULE_INPUT_ROOT).out4',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ },
+ ],
+ 'actions': [
+ {
+ 'action_name': 'copy_file1_in',
+ 'inputs': [
+ '../copy-file.py',
+ 'file1.in',
+ ],
+ 'outputs': [
+ 'file1.copy',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(_outputs)'
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/test/rules/src/subdir2/program.c b/test/rules/src/subdir2/program.c
new file mode 100644
index 00000000..c9ae7cd5
--- /dev/null
+++ b/test/rules/src/subdir2/program.c
@@ -0,0 +1,12 @@
+/* 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.
+ */
+
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+ printf("Hello from program.c\n");
+ return 0;
+}
diff --git a/test/win/gyptest-midl-excluded.py b/test/win/gyptest-midl-excluded.py
new file mode 100644
index 00000000..70059ab6
--- /dev/null
+++ b/test/win/gyptest-midl-excluded.py
@@ -0,0 +1,22 @@
+#!/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.
+
+"""
+Test that .idl files in actions and non-native rules are excluded.
+"""
+
+import TestGyp
+
+import sys
+
+if sys.platform == 'win32':
+ test = TestGyp.TestGyp(formats=['msvs', 'ninja'])
+
+ CHDIR = 'idl-excluded'
+ test.run_gyp('idl-excluded.gyp', chdir=CHDIR)
+ test.build('idl-excluded.gyp', test.ALL, chdir=CHDIR)
+
+ test.pass_test()
diff --git a/test/win/gyptest-midl-rules.py b/test/win/gyptest-midl-rules.py
index d615ba5c..591a5073 100644
--- a/test/win/gyptest-midl-rules.py
+++ b/test/win/gyptest-midl-rules.py
@@ -21,4 +21,8 @@ if sys.platform == 'win32':
test.set_configuration('Debug|%s' % platform)
test.build('basic-idl.gyp', test.ALL, chdir=CHDIR)
+ # Make sure ninja win_tool.py filters out noisy lines.
+ if test.format == 'ninja' and 'Processing' in test.stdout():
+ test.fail_test()
+
test.pass_test()
diff --git a/test/win/idl-excluded/bad.idl b/test/win/idl-excluded/bad.idl
new file mode 100644
index 00000000..38554e96
--- /dev/null
+++ b/test/win/idl-excluded/bad.idl
@@ -0,0 +1,6 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+This is a dummy .idl file that will trigger an error if it is not excluded from
+the build.
diff --git a/test/win/idl-excluded/copy-file.py b/test/win/idl-excluded/copy-file.py
new file mode 100644
index 00000000..5a5feae1
--- /dev/null
+++ b/test/win/idl-excluded/copy-file.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2009 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
+
+contents = open(sys.argv[1], 'r').read()
+open(sys.argv[2], 'wb').write(contents)
+
+sys.exit(0)
diff --git a/test/win/idl-excluded/idl-excluded.gyp b/test/win/idl-excluded/idl-excluded.gyp
new file mode 100644
index 00000000..972b7ded
--- /dev/null
+++ b/test/win/idl-excluded/idl-excluded.gyp
@@ -0,0 +1,58 @@
+# Copyright (c) 2014 The Chromium Authors. 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': 'exclude_with_action',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'actions': [{
+ 'action_name': 'copy_action',
+ 'inputs': [
+ 'copy-file.py',
+ 'bad.idl',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/bad.idl',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<@(_outputs)',
+ ],
+ }],
+ },
+ {
+ 'target_name': 'exclude_with_rule',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'bad.idl',
+ ],
+ 'rules': [{
+ 'rule_name': 'copy_rule',
+ 'extension': 'idl',
+ 'inputs': [
+ 'copy-file.py',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).idl',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ }],
+ },
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'sources': [
+ 'program.cc',
+ ],
+ 'dependencies': [
+ 'exclude_with_action',
+ 'exclude_with_rule',
+ ],
+ },
+ ],
+}
diff --git a/test/win/idl-excluded/program.cc b/test/win/idl-excluded/program.cc
new file mode 100644
index 00000000..9dc3c94f
--- /dev/null
+++ b/test/win/idl-excluded/program.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 main() {
+ return 0;
+}