Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(297)

Side by Side Diff: test/lib/TestGyp.py

Issue 245923003: Fix msvs-ninja OutputDirectory path. (Closed) Base URL: http://gyp.googlecode.com/svn/trunk/
Patch Set: Can now run just msvs-ninja. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « test/ios/gyptest-xcode-ninja.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 Google Inc. All rights reserved. 1 # Copyright (c) 2012 Google Inc. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """ 5 """
6 TestGyp.py: a testing framework for GYP integration tests. 6 TestGyp.py: a testing framework for GYP integration tests.
7 """ 7 """
8 8
9 import collections 9 import collections
10 from contextlib import contextmanager 10 from contextlib import contextmanager
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 The default behavior is to test the 'gyp' or 'gyp.bat' file in the 71 The default behavior is to test the 'gyp' or 'gyp.bat' file in the
72 current directory. An alternative may be specified explicitly on 72 current directory. An alternative may be specified explicitly on
73 instantiation, or by setting the TESTGYP_GYP environment variable. 73 instantiation, or by setting the TESTGYP_GYP environment variable.
74 74
75 This class should be subclassed for each supported gyp generator 75 This class should be subclassed for each supported gyp generator
76 (format). Various abstract methods below define calling signatures 76 (format). Various abstract methods below define calling signatures
77 used by the test scripts to invoke builds on the generated build 77 used by the test scripts to invoke builds on the generated build
78 configuration and to run executables generated by those builds. 78 configuration and to run executables generated by those builds.
79 """ 79 """
80 80
81 formats = []
81 build_tool = None 82 build_tool = None
82 build_tool_list = [] 83 build_tool_list = []
83 84
84 _exe = TestCommon.exe_suffix 85 _exe = TestCommon.exe_suffix
85 _obj = TestCommon.obj_suffix 86 _obj = TestCommon.obj_suffix
86 shobj_ = TestCommon.shobj_prefix 87 shobj_ = TestCommon.shobj_prefix
87 _shobj = TestCommon.shobj_suffix 88 _shobj = TestCommon.shobj_suffix
88 lib_ = TestCommon.lib_prefix 89 lib_ = TestCommon.lib_prefix
89 _lib = TestCommon.lib_suffix 90 _lib = TestCommon.lib_suffix
90 dll_ = TestCommon.dll_prefix 91 dll_ = TestCommon.dll_prefix
(...skipping 15 matching lines...) Expand all
106 if not gyp: 107 if not gyp:
107 gyp = os.environ.get('TESTGYP_GYP') 108 gyp = os.environ.get('TESTGYP_GYP')
108 if not gyp: 109 if not gyp:
109 if sys.platform == 'win32': 110 if sys.platform == 'win32':
110 gyp = 'gyp.bat' 111 gyp = 'gyp.bat'
111 else: 112 else:
112 gyp = 'gyp' 113 gyp = 'gyp'
113 self.gyp = os.path.abspath(gyp) 114 self.gyp = os.path.abspath(gyp)
114 self.no_parallel = False 115 self.no_parallel = False
115 116
117 self.formats = [self.format]
118
116 self.initialize_build_tool() 119 self.initialize_build_tool()
117 120
118 kw.setdefault('match', TestCommon.match_exact) 121 kw.setdefault('match', TestCommon.match_exact)
119 122
120 # Put test output in out/testworkarea by default. 123 # Put test output in out/testworkarea by default.
121 # Use temporary names so there are no collisions. 124 # Use temporary names so there are no collisions.
122 workdir = os.path.join('out', kw.get('workdir', 'testworkarea')) 125 workdir = os.path.join('out', kw.get('workdir', 'testworkarea'))
123 # Create work area if it doesn't already exist. 126 # Create work area if it doesn't already exist.
124 if not os.path.isdir(workdir): 127 if not os.path.isdir(workdir):
125 os.makedirs(workdir) 128 os.makedirs(workdir)
126 129
127 kw['workdir'] = tempfile.mktemp(prefix='testgyp.', dir=workdir) 130 kw['workdir'] = tempfile.mktemp(prefix='testgyp.', dir=workdir)
128 131
129 formats = kw.pop('formats', []) 132 formats = kw.pop('formats', [])
130 133
131 super(TestGypBase, self).__init__(*args, **kw) 134 super(TestGypBase, self).__init__(*args, **kw)
132 135
136 realFormat = self.format.split('-')[-1]
scottmg 2014/05/30 16:41:37 realFormat -> real_format
bungeman-chromium 2014/05/30 22:18:09 Done.
133 excluded_formats = set([f for f in formats if f[0] == '!']) 137 excluded_formats = set([f for f in formats if f[0] == '!'])
134 included_formats = set(formats) - excluded_formats 138 included_formats = set(formats) - excluded_formats
135 if ('!'+self.format in excluded_formats or 139 if ('!'+realFormat in excluded_formats or
136 included_formats and self.format not in included_formats): 140 included_formats and realFormat not in included_formats):
137 msg = 'Invalid test for %r format; skipping test.\n' 141 msg = 'Invalid test for %r format; skipping test.\n'
138 self.skip_test(msg % self.format) 142 self.skip_test(msg % self.format)
139 143
140 self.copy_test_configuration(self.origin_cwd, self.workdir) 144 self.copy_test_configuration(self.origin_cwd, self.workdir)
141 self.set_configuration(None) 145 self.set_configuration(None)
142 146
143 # Set $HOME so that gyp doesn't read the user's actual 147 # Set $HOME so that gyp doesn't read the user's actual
144 # ~/.gyp/include.gypi file, which may contain variables 148 # ~/.gyp/include.gypi file, which may contain variables
145 # and other settings that would change the output. 149 # and other settings that would change the output.
146 os.environ['HOME'] = self.workpath() 150 os.environ['HOME'] = self.workpath()
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 Runs gyp against the specified gyp_file with the specified args. 269 Runs gyp against the specified gyp_file with the specified args.
266 """ 270 """
267 271
268 # When running gyp, and comparing its output we use a comparitor 272 # When running gyp, and comparing its output we use a comparitor
269 # that ignores the line numbers that gyp logs in its debug output. 273 # that ignores the line numbers that gyp logs in its debug output.
270 if kw.pop('ignore_line_numbers', False): 274 if kw.pop('ignore_line_numbers', False):
271 kw.setdefault('match', match_modulo_line_numbers) 275 kw.setdefault('match', match_modulo_line_numbers)
272 276
273 # TODO: --depth=. works around Chromium-specific tree climbing. 277 # TODO: --depth=. works around Chromium-specific tree climbing.
274 depth = kw.pop('depth', '.') 278 depth = kw.pop('depth', '.')
275 run_args = ['--depth='+depth, '--format='+self.format, gyp_file] 279 run_args = ['--depth='+depth]
280 run_args.extend(['--format='+f for f in self.formats]);
281 run_args.append(gyp_file)
276 if self.no_parallel: 282 if self.no_parallel:
277 run_args += ['--no-parallel'] 283 run_args += ['--no-parallel']
284 # TODO: if extra_args contains a '--build' flag
285 # we really want that to only apply to the last format (self.format).
278 run_args.extend(self.extra_args) 286 run_args.extend(self.extra_args)
279 run_args.extend(args) 287 run_args.extend(args)
280 return self.run(program=self.gyp, arguments=run_args, **kw) 288 return self.run(program=self.gyp, arguments=run_args, **kw)
281 289
282 def run(self, *args, **kw): 290 def run(self, *args, **kw):
283 """ 291 """
284 Executes a program by calling the superclass .run() method. 292 Executes a program by calling the superclass .run() method.
285 293
286 This exists to provide a common place to filter out keyword 294 This exists to provide a common place to filter out keyword
287 arguments implemented in this layer, without having to update 295 arguments implemented in this layer, without having to update
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after
995 chdir = kw.get('chdir') 1003 chdir = kw.get('chdir')
996 if chdir: 1004 if chdir:
997 result.append(chdir) 1005 result.append(chdir)
998 result.append(self.configuration_dirname()) 1006 result.append(self.configuration_dirname())
999 if type == self.STATIC_LIB: 1007 if type == self.STATIC_LIB:
1000 result.append('lib') 1008 result.append('lib')
1001 result.append(self.built_file_basename(name, type, **kw)) 1009 result.append(self.built_file_basename(name, type, **kw))
1002 return self.workpath(*result) 1010 return self.workpath(*result)
1003 1011
1004 1012
1013 def FindMSBuildInstallation():
scottmg 2014/05/30 16:41:37 This looks very similar to FindVisualStudioInstall
bungeman-chromium 2014/05/30 22:18:09 It is, but it needn't be. I think I shied away fro
1014 """Returns appropriate values for .build_tool and .uses_msbuild fields
1015 of TestGypBase for Visual Studio.
1016
1017 We use the value specified by GYP_MSVS_VERSION. If not specified, we
1018 search %PATH% and %PATHEXT% for a devenv.{exe,bat,...} executable.
1019 Failing that, we search for likely deployment paths.
1020 """
1021 possible_roots = ['%s:\\Program Files%s' % (chr(drive), suffix)
1022 for drive in range(ord('C'), ord('Z') + 1)
1023 for suffix in ['', ' (x86)']]
1024 possible_roots.extend(['%s:\\Windows' % (chr(drive),)
1025 for drive in range(ord('C'), ord('Z') + 1)])
1026 possible_paths = {
1027 '2013': r'MSBuild\12.0\Bin\MSBuild.exe', #Program Files
1028 '2012': r'Microsoft.NET\Framework\v4.0.30319\MSBuild.exe', #Windows
1029 '2010': r'Microsoft.NET\Framework\v4.0\MSBuild.exe',
1030 '2008': r'Microsoft.NET\Framework\v3.5\MSBuild.exe'}
1031 #The reccommended way to find this is
1032 #reg.exe query "HKLM\SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0" /v MSBuild ToolsPath
1033 #2013 : 12.0
1034 #2012 : 4.0 (really v4.0.30319 which comes with 4.5)
1035 #2010 : 4.0
1036 #2008 : 3.5
1037
1038 possible_roots = [ConvertToCygpath(r) for r in possible_roots]
1039
1040 msvs_version = 'auto'
1041 for flag in (f for f in sys.argv if f.startswith('msvs_version=')):
1042 msvs_version = flag.split('=')[-1]
1043 msvs_version = os.environ.get('GYP_MSVS_VERSION', msvs_version)
1044
1045 build_tool = None
1046 if msvs_version in possible_paths:
1047 # Check that the path to the specified GYP_MSVS_VERSION exists.
1048 path = possible_paths[msvs_version]
1049 for r in possible_roots:
1050 bt = os.path.join(r, path)
1051 if os.path.exists(bt):
1052 build_tool = bt
1053 return build_tool
1054 else:
1055 print ('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" '
1056 'but corresponding "%s" was not found.' % (msvs_version, path))
1057 if build_tool:
1058 # We found 'MSBuild' on the path, use that and try to guess the version.
1059 for version, path in possible_paths.iteritems():
1060 if build_tool.find(path) >= 0:
1061 return build_tool
1062 return build_tool
1063 # Neither GYP_MSVS_VERSION nor the path help us out. Iterate through
1064 # the choices looking for a match.
1065 for version in sorted(possible_paths, reverse=True):
1066 path = possible_paths[version]
1067 for r in possible_roots:
1068 bt = os.path.join(r, path)
1069 if os.path.exists(bt):
1070 build_tool = bt
1071 return build_tool
1072 print 'Error: could not find MSBuild'
1073 sys.exit(1)
1074
1075
1076 class TestGypMSVSNinja(TestGypNinja):
1077 """
1078 Subclass for testing the GYP Visual Studio Ninja generator.
1079 """
1080 format = 'msvs-ninja'
1081
1082 def initialize_build_tool(self):
1083 super(TestGypMSVSNinja, self).initialize_build_tool()
1084 self.msbuild_path = FindMSBuildInstallation()
1085 # When using '--build', make sure ninja is first in the format list.
1086 self.formats.insert(0, 'ninja')
1087
1088 def build(self, gyp_file, target=None, rebuild=False, clean=False, **kw):
1089 """
1090 Runs a Visual Studio build using the configuration generated
1091 from the specified gyp_file.
1092 """
1093 arguments = kw.get('arguments', [])[:]
1094 if target not in (None, self.ALL, self.DEFAULT):
1095 # MSBuild documentation claims that one can specify a sln but then build a
1096 # project target like 'msbuild a.sln /t:proj:target' but this format only
1097 # supports 'Clean', 'Rebuild', and 'Publish' (with none meaning Default).
1098 # This limitation is due to the .sln -> .sln.metaproj conversion.
1099 # The ':' is not special, 'proj:target' is a target in the metaproj.
1100 arguments.extend([target+'.vcxproj'])
1101 else:
1102 # Note: the Visual Studio generator doesn't add an explicit 'all' target.
1103 if 1:
1104 # This will build each project. This will work if projects are hermetic,
1105 # but may fail if they are not (a project may run more than once).
1106 # It would be nice to supply an all.metaproj for MSBuild.
1107 arguments.extend([gyp_file.replace('.gyp', '.sln')])
1108 else:
1109 # This is a cheat which just runs ninja's 'all' target directly.
1110 # However, this doesn't test what we want to test here,
1111 # which is that the thin msbuild projects call ninja correctly.
1112 return super(TestGypMSVSNinja, self).build(gyp_file, target=target, **kw)
1113
1114 if clean:
1115 build = 'Clean'
1116 elif rebuild:
1117 build = 'Rebuild'
1118 else:
1119 build = 'Build'
1120 arguments.extend(['/target:'+build])
1121 configuration = self.configuration_buildname()
1122 config = configuration.split('|')
1123 arguments.extend(['/property:Configuration='+config[0]])
1124 if len(config) > 1:
1125 arguments.extend(['/property:Platform='+config[1]])
1126 arguments.extend(['/property:BuildInParallel=false'])
1127 arguments.extend(['/verbosity:minimal'])
1128
1129 kw['arguments'] = arguments
1130 return self.run(program=self.msbuild_path, **kw)
1131
1132
1005 class TestGypXcode(TestGypBase): 1133 class TestGypXcode(TestGypBase):
1006 """ 1134 """
1007 Subclass for testing the GYP Xcode generator. 1135 Subclass for testing the GYP Xcode generator.
1008 """ 1136 """
1009 format = 'xcode' 1137 format = 'xcode'
1010 build_tool_list = ['xcodebuild'] 1138 build_tool_list = ['xcodebuild']
1011 1139
1012 phase_script_execution = ("\n" 1140 phase_script_execution = ("\n"
1013 "PhaseScriptExecution /\\S+/Script-[0-9A-F]+\\.sh\n" 1141 "PhaseScriptExecution /\\S+/Script-[0-9A-F]+\\.sh\n"
1014 " cd /\\S+\n" 1142 " cd /\\S+\n"
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1111 result.append(self.built_file_basename(name, type, **kw)) 1239 result.append(self.built_file_basename(name, type, **kw))
1112 return self.workpath(*result) 1240 return self.workpath(*result)
1113 1241
1114 1242
1115 format_class_list = [ 1243 format_class_list = [
1116 TestGypGypd, 1244 TestGypGypd,
1117 TestGypAndroid, 1245 TestGypAndroid,
1118 TestGypCMake, 1246 TestGypCMake,
1119 TestGypMake, 1247 TestGypMake,
1120 TestGypMSVS, 1248 TestGypMSVS,
1249 TestGypMSVSNinja,
1121 TestGypNinja, 1250 TestGypNinja,
1122 TestGypXcode, 1251 TestGypXcode,
1123 ] 1252 ]
1124 1253
1125 def TestGyp(*args, **kw): 1254 def TestGyp(*args, **kw):
1126 """ 1255 """
1127 Returns an appropriate TestGyp* instance for a specified GYP format. 1256 Returns an appropriate TestGyp* instance for a specified GYP format.
1128 """ 1257 """
1129 format = kw.pop('format', os.environ.get('TESTGYP_FORMAT')) 1258 format = kw.pop('format', os.environ.get('TESTGYP_FORMAT'))
1130 for format_class in format_class_list: 1259 for format_class in format_class_list:
1131 if format == format_class.format: 1260 if format == format_class.format:
1132 return format_class(*args, **kw) 1261 return format_class(*args, **kw)
1133 raise Exception, "unknown format %r" % format 1262 raise Exception, "unknown format %r" % format
OLDNEW
« no previous file with comments | « test/ios/gyptest-xcode-ninja.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698