Index: test/lib/TestGyp.py |
=================================================================== |
--- test/lib/TestGyp.py (revision 1925) |
+++ test/lib/TestGyp.py (working copy) |
@@ -78,6 +78,7 @@ |
configuration and to run executables generated by those builds. |
""" |
+ formats = [] |
build_tool = None |
build_tool_list = [] |
@@ -113,6 +114,8 @@ |
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 @@ |
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 @@ |
# 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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
TestGypCMake, |
TestGypMake, |
TestGypMSVS, |
+ TestGypMSVSNinja, |
TestGypNinja, |
TestGypXcode, |
] |