diff options
author | Android Chromium Automerger <chromium-automerger@android> | 2014-06-06 10:22:41 +0000 |
---|---|---|
committer | Android Chromium Automerger <chromium-automerger@android> | 2014-06-06 10:22:41 +0000 |
commit | 1ab1f9a545b0f568929f38e6952b39055276efef (patch) | |
tree | 8f35e94e2eef8136e4fc5ba567ddd737d7d26b68 | |
parent | 12fc9e9c1b483568b72ed83628097dcbe3aa6684 (diff) | |
parent | 0ff4e1aa19641cda58e3ed98399e0d96e6ccd7c2 (diff) | |
download | gyp-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
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; +} |