Merge pull request #4655 from bdbaddog/fix_new_ninja_package
[scons.git] / SCons / Tool / MSCommon / vcTests.py
blobe1146e89be9603b106f2bda4ddd121ae2bae019c
1 # MIT License
3 # Copyright The SCons Foundation
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 import os
26 import os.path
27 import unittest
29 import SCons.Node.FS
30 import SCons.Warnings
31 import SCons.Tool.MSCommon.vc
32 from SCons.Tool import MSCommon
34 import TestCmd
36 original = os.getcwd()
38 test = TestCmd.TestCmd(workdir='')
40 os.chdir(test.workpath(''))
42 MSVCUnsupportedHostArch = SCons.Tool.MSCommon.vc.MSVCUnsupportedHostArch
43 MSVCUnsupportedTargetArch = SCons.Tool.MSCommon.vc.MSVCUnsupportedTargetArch
45 MS_TOOLS_VERSION = '1.1.1'
48 class VswhereTestCase(unittest.TestCase):
49 @staticmethod
50 def _createVSWhere(path) -> None:
51 os.makedirs(os.path.dirname(path), exist_ok=True)
52 with open(path, 'w') as f:
53 f.write("Created:%s" % f)
55 def testDefaults(self) -> None:
56 """
57 Verify that msvc_find_vswhere() find's files in the specified paths
58 """
59 # import pdb; pdb.set_trace()
60 test_all_dirs = []
62 base_dir = test.workpath('fake_vswhere')
64 vswhere_dirs = [os.path.splitdrive(p)[1] for p in SCons.Tool.MSCommon.vc._VSWHERE_EXEGROUP_MSVS]
65 test_vswhere_dirs = [os.path.join(base_dir,d[1:]) for d in vswhere_dirs]
66 SCons.Tool.MSCommon.vc._VSWHERE_EXEGROUP_MSVS = test_vswhere_dirs
67 test_all_dirs += test_vswhere_dirs
69 vswhere_dirs = [os.path.splitdrive(p)[1] for p in SCons.Tool.MSCommon.vc._VSWHERE_EXEGROUP_PKGMGR]
70 test_vswhere_dirs = [os.path.join(base_dir,d[1:]) for d in vswhere_dirs]
71 SCons.Tool.MSCommon.vc._VSWHERE_EXEGROUP_PKGMGR = test_vswhere_dirs
72 test_all_dirs += test_vswhere_dirs
74 for vsw in test_all_dirs:
75 SCons.Tool.MSCommon.vc._VSWhereExecutable.reset()
76 VswhereTestCase._createVSWhere(vsw)
77 find_path = SCons.Tool.MSCommon.vc.msvc_find_vswhere()
78 self.assertTrue(vsw == find_path, "Didn't find vswhere in %s found in %s" % (vsw, find_path))
79 os.remove(vsw)
81 # def specifiedVswherePathTest(self):
82 # "Verify that msvc.generate() respects VSWHERE Specified"
85 class MSVcTestCase(unittest.TestCase):
87 @staticmethod
88 def _createDummyFile(path, filename, add_bin: bool=True) -> None:
89 """
90 Creates a dummy cl.exe in the correct directory.
91 It will create all missing parent directories as well
93 Args:
94 path: Relative path to cl.exe for the version about to be tested.
95 """
97 # print("PATH:%s"%path)
99 path = path.replace('\\', os.sep)
100 if add_bin:
101 create_path = os.path.join(path,'bin')
102 else:
103 create_path = path
104 if create_path and not os.path.isdir(create_path):
105 os.makedirs(create_path)
107 create_this = os.path.join(create_path, filename)
109 # print("Creating: %s"%create_this)
110 with open(create_this,'w') as ct:
111 ct.write('created')
114 def runTest(self) -> None:
116 Check that all proper HOST_PLATFORM and TARGET_PLATFORM are handled.
117 Verify that improper HOST_PLATFORM and/or TARGET_PLATFORM are properly handled.
118 by SCons.Tool.MSCommon.vc._check_files_exist_in_vc_dir()
121 check = SCons.Tool.MSCommon.vc._check_files_exist_in_vc_dir
123 # Setup for 14.1 (VS2017) and later tests
125 # Create the VC minor/major version file
126 tools_version_file = SCons.Tool.MSCommon.vc._VC_TOOLS_VERSION_FILE
127 tools_dir = os.path.dirname(tools_version_file)
128 if not os.path.isdir(tools_dir):
129 os.makedirs(tools_dir)
130 try:
131 with open(tools_version_file, 'w') as tf:
132 tf.write(MS_TOOLS_VERSION)
133 except IOError as e:
134 print("Failed trying to write :%s :%s" % (tools_version_file, e))
136 # Test 14.3 (VS2022) and later
137 vc_ge2022_list = SCons.Tool.MSCommon.vc._GE2022_HOST_TARGET_CFG.all_pairs
138 for host, target in vc_ge2022_list:
139 batfile, clpathcomps = SCons.Tool.MSCommon.vc._GE2022_HOST_TARGET_BATCHFILE_CLPATHCOMPS[(host,target)]
140 # print("GE 14.3 Got: (%s, %s) -> (%s, %s)"%(host,target,batfile,clpathcomps))
142 env={'TARGET_ARCH':target, 'HOST_ARCH':host}
143 path = os.path.join('.', "Auxiliary", "Build", batfile)
144 MSVcTestCase._createDummyFile(path, batfile, add_bin=False)
145 path = os.path.join('.', 'Tools', 'MSVC', MS_TOOLS_VERSION, *clpathcomps)
146 MSVcTestCase._createDummyFile(path, 'cl.exe', add_bin=False)
147 result=check(env, '.', '14.3')
148 # print("for:(%s, %s) got :%s"%(host, target, result))
149 self.assertTrue(result, "Checking host: %s target: %s" % (host, target))
151 # Test 14.2 (VS2019) to 14.1 (VS2017) versions
152 vc_le2019_list = SCons.Tool.MSCommon.vc._LE2019_HOST_TARGET_CFG.all_pairs
153 for host, target in vc_le2019_list:
154 batfile, clpathcomps = SCons.Tool.MSCommon.vc._LE2019_HOST_TARGET_BATCHFILE_CLPATHCOMPS[(host,target)]
155 # print("LE 14.2 Got: (%s, %s) -> (%s, %s)"%(host,target,batfile,clpathcomps))
157 env={'TARGET_ARCH':target, 'HOST_ARCH':host}
158 path = os.path.join('.', 'Tools', 'MSVC', MS_TOOLS_VERSION, *clpathcomps)
159 MSVcTestCase._createDummyFile(path, 'cl.exe', add_bin=False)
160 result=check(env, '.', '14.1')
161 # print("for:(%s, %s) got :%s"%(host, target, result))
162 self.assertTrue(result, "Checking host: %s target: %s" % (host, target))
164 # Test 14.0 (VS2015) to 10.0 (VS2010) versions
165 vc_le2015_list = SCons.Tool.MSCommon.vc._LE2015_HOST_TARGET_CFG.all_pairs
166 for host, target in vc_le2015_list:
167 batarg, batfile, clpathcomps = SCons.Tool.MSCommon.vc._LE2015_HOST_TARGET_BATCHARG_BATCHFILE_CLPATHCOMPS[(host, target)]
168 # print("LE 14.0 Got: (%s, %s) -> (%s, %s, %s)"%(host,target,batarg,batfile,clpathcomps))
169 env={'TARGET_ARCH':target, 'HOST_ARCH':host}
170 MSVcTestCase._createDummyFile('.', 'vcvarsall.bat', add_bin=False)
171 path = os.path.join('.', *clpathcomps)
172 MSVcTestCase._createDummyFile(path, batfile, add_bin=False)
173 MSVcTestCase._createDummyFile(path, 'cl.exe', add_bin=False)
174 result=check(env, '.', '10.0')
175 # print("for:(%s, %s) got :%s"%(host, target, result))
176 self.assertTrue(result, "Checking host: %s target: %s" % (host, target))
178 # Test 9.0 (VC2008) to 8.0 (VS2005)
179 vc_le2008_list = SCons.Tool.MSCommon.vc._LE2008_HOST_TARGET_CFG.all_pairs
180 for host, target in vc_le2008_list:
181 batarg, batfile, clpathcomps = SCons.Tool.MSCommon.vc._LE2008_HOST_TARGET_BATCHARG_BATCHFILE_CLPATHCOMPS[(host, target)]
182 # print("LE 9.0 Got: (%s, %s) -> (%s, %s, %s)"%(host,target,batarg,batfile,clpathcomps))
183 env={'TARGET_ARCH':target, 'HOST_ARCH':host}
184 MSVcTestCase._createDummyFile('.', 'vcvarsall.bat', add_bin=False)
185 path = os.path.join('.', *clpathcomps)
186 MSVcTestCase._createDummyFile(path, batfile, add_bin=False)
187 MSVcTestCase._createDummyFile(path, 'cl.exe', add_bin=False)
188 # check will fail if '9.0' and VCForPython (layout different)
189 result=check(env, '.', '8.0')
190 # print("for:(%s, %s) got :%s"%(host, target, result))
191 self.assertTrue(result, "Checking host: %s target: %s" % (host, target))
193 # Test 7.1 (VS2003) and earlier
194 vc_le2003_list = SCons.Tool.MSCommon.vc._LE2003_HOST_TARGET_CFG.all_pairs
195 for host, target in vc_le2003_list:
196 # print("LE 7.1 Got: (%s, %s)"%(host,target))
197 env={'TARGET_ARCH':target, 'HOST_ARCH':host}
198 path = os.path.join('.')
199 MSVcTestCase._createDummyFile(path, 'cl.exe')
200 result=check(env, '.', '6.0')
201 # print("for:(%s, %s) got :%s"%(host, target, result))
202 self.assertTrue(result, "Checking host: %s target: %s" % (host, target))
204 # Now test bogus value for HOST_ARCH
205 env={'TARGET_ARCH':'x86', 'HOST_ARCH':'GARBAGE'}
206 try:
207 result=check(env, '.', '14.3')
208 # print("for:%s got :%s"%(env, result))
209 self.assertFalse(result, "Did not fail with bogus HOST_ARCH host: %s target: %s" % (env['HOST_ARCH'], env['TARGET_ARCH']))
210 except MSVCUnsupportedHostArch:
211 pass
212 else:
213 self.fail('Did not fail when HOST_ARCH specified as: %s' % env['HOST_ARCH'])
215 # Now test bogus value for TARGET_ARCH
216 env={'TARGET_ARCH':'GARBAGE', 'HOST_ARCH':'x86'}
217 try:
218 result=check(env, '.', '14.3')
219 # print("for:%s got :%s"%(env, result))
220 self.assertFalse(result, "Did not fail with bogus TARGET_ARCH host: %s target: %s" % (env['HOST_ARCH'], env['TARGET_ARCH']))
221 except MSVCUnsupportedTargetArch:
222 pass
223 else:
224 self.fail('Did not fail when TARGET_ARCH specified as: %s' % env['TARGET_ARCH'])
226 class Data:
228 DEFAULT_VERSION = MSCommon.vc.msvc_default_version()
230 if DEFAULT_VERSION:
231 HAVE_MSVC = True
232 DEFAULT_VERSION_DEF = MSCommon.msvc_version_components(DEFAULT_VERSION)
233 else:
234 HAVE_MSVC = False
235 DEFAULT_VERSION_DEF = None
237 INSTALLED_VCS = MSCommon.vc.get_installed_vcs()
238 INSTALLED_VCS_COMPONENTS = MSCommon.vc.get_installed_vcs_components()
239 INSTALLED_VCS_TOOLSETS_COMPONENTS = MSCommon.vc.get_installed_vcs_toolsets_components()
241 @classmethod
242 def query_version_list(cls, vcver):
243 # VS 2022 (14.3) can have either/both toolset versions 14.3X and 14.4X
244 if vcver == '14.3' or (vcver is None and cls.DEFAULT_VERSION == '14.3'):
245 vcver_list = ['14.4', '14.3']
246 else:
247 vcver_list = [vcver]
248 return vcver_list
250 @classmethod
251 def _msvc_toolset_notfound_list(cls, toolset_seen, toolset_list):
252 new_toolset_list = []
253 if not toolset_list:
254 return new_toolset_list
255 for toolset_version in toolset_list:
256 version = toolset_version
257 comps = version.split('.')
258 if len(comps) != 3:
259 continue
260 # full versions only
261 ival = int(comps[-1])
262 nloop = 0
263 while nloop < 10:
264 if ival == 0:
265 ival = 100000
266 ival -= 1
267 version = '{}.{}.{:05d}'.format(comps[0], comps[1], ival)
268 if version not in toolset_seen:
269 new_toolset_list.append(version)
270 break
271 nloop += 1
272 return new_toolset_list
274 _msvc_toolset_notfound_dict = None
276 @classmethod
277 def msvc_toolset_notfound_dict(cls):
278 if cls._msvc_toolset_notfound_dict is None:
279 toolset_seen = set()
280 toolset_dict = {}
281 for symbol in MSCommon.vc._VCVER:
282 toolset_list = MSCommon.vc.msvc_toolset_versions(msvc_version=symbol, full=True, sxs=False)
283 if not toolset_list:
284 continue
285 toolset_seen.update(toolset_list)
286 toolset_dict[symbol] = toolset_list
287 for key, val in toolset_dict.items():
288 toolset_dict[key] = cls._msvc_toolset_notfound_list(toolset_seen, val)
289 cls._msvc_toolset_notfound_dict = toolset_dict
290 return cls._msvc_toolset_notfound_dict
292 class Patch:
294 class MSCommon:
296 class vc:
298 class msvc_default_version:
300 msvc_default_version = MSCommon.vc.msvc_default_version
302 @classmethod
303 def msvc_default_version_none(cls):
304 return None
306 @classmethod
307 def enable_none(cls):
308 hook = cls.msvc_default_version_none
309 MSCommon.vc.msvc_default_version = hook
310 return hook
312 @classmethod
313 def restore(cls) -> None:
314 MSCommon.vc.msvc_default_version = cls.msvc_default_version
316 class MsvcSdkVersionsTests(unittest.TestCase):
317 """Test msvc_sdk_versions"""
319 def run_valid_default_msvc(self) -> None:
320 symbol = MSCommon.vc.msvc_default_version()
321 version_def = MSCommon.msvc_version_components(symbol)
322 for msvc_uwp_app in (True, False):
323 sdk_list = MSCommon.vc.msvc_sdk_versions(version=None, msvc_uwp_app=msvc_uwp_app)
324 if symbol and version_def.msvc_vernum >= 14.0:
325 self.assertTrue(sdk_list, "SDK list is empty for msvc version {}".format(repr(None)))
326 else:
327 self.assertFalse(sdk_list, "SDK list is not empty for msvc version {}".format(repr(None)))
329 def test_valid_default_msvc(self) -> None:
330 if Data.HAVE_MSVC:
331 Patch.MSCommon.vc.msvc_default_version.enable_none()
332 self.run_valid_default_msvc()
333 Patch.MSCommon.vc.msvc_default_version.restore()
334 self.run_valid_default_msvc()
336 def test_valid_vcver(self) -> None:
337 for symbol in MSCommon.vc._VCVER:
338 version_def = MSCommon.msvc_version_components(symbol)
339 for msvc_uwp_app in (True, False):
340 sdk_list = MSCommon.vc.msvc_sdk_versions(version=symbol, msvc_uwp_app=msvc_uwp_app)
341 if version_def.msvc_vernum < 14.0:
342 # version < VS2015
343 # does not accept sdk version argument
344 self.assertFalse(sdk_list, "SDK list is not empty for msvc version {}".format(repr(symbol)))
345 elif Data.HAVE_MSVC and Data.DEFAULT_VERSION_DEF.msvc_vernum >= 14.0:
346 # version >= VS2015 and default_version >= VS2015
347 # no guarantee test is valid: compatible sdks may not be installed as version gap grows
348 self.assertTrue(sdk_list, "SDK list is empty for msvc version {}".format(repr(symbol)))
349 else:
350 # version >= VS2015 and default_version < VS2015
351 # skip test: version is not installed; compatible windows sdks may not be installed
352 pass
354 def test_valid_vcver_toolsets(self) -> None:
355 for symbol in MSCommon.vc._VCVER:
356 toolset_list = MSCommon.vc.msvc_toolset_versions(msvc_version=symbol, full=True, sxs=True)
357 if toolset_list is None:
358 continue
359 for toolset in toolset_list:
360 extended_def = MSCommon.msvc_extended_version_components(toolset)
361 for msvc_uwp_app in (True, False):
362 sdk_list = MSCommon.vc.msvc_sdk_versions(
363 version=extended_def.msvc_toolset_version,
364 msvc_uwp_app=msvc_uwp_app
366 self.assertTrue(sdk_list, "SDK list is empty for msvc toolset version {}".format(repr(toolset)))
368 def test_invalid_vcver(self) -> None:
369 for symbol in ['6.0Exp', '14.3Exp', '99', '14.1Bug']:
370 for msvc_uwp_app in (True, False):
371 with self.assertRaises(MSCommon.vc.MSVCArgumentError):
372 _ = MSCommon.vc.msvc_sdk_versions(version=symbol, msvc_uwp_app=msvc_uwp_app)
374 def test_invalid_vcver_toolsets(self) -> None:
375 for symbol in ['14.31.123456', '14.31.1.1']:
376 for msvc_uwp_app in (True, False):
377 with self.assertRaises(MSCommon.vc.MSVCArgumentError):
378 _ = MSCommon.vc.msvc_sdk_versions(version=symbol, msvc_uwp_app=msvc_uwp_app)
380 class MsvcToolsetVersionsTests(unittest.TestCase):
381 """Test msvc_toolset_versions"""
383 def run_valid_default_msvc(self) -> None:
384 symbol = MSCommon.vc.msvc_default_version()
385 version_def = MSCommon.msvc_version_components(symbol)
386 toolset_none_list = MSCommon.vc.msvc_toolset_versions(msvc_version=None, full=False, sxs=False)
387 toolset_full_list = MSCommon.vc.msvc_toolset_versions(msvc_version=None, full=True, sxs=False)
388 toolset_sxs_list = MSCommon.vc.msvc_toolset_versions(msvc_version=None, full=False, sxs=True)
389 toolset_all_list = MSCommon.vc.msvc_toolset_versions(msvc_version=None, full=True, sxs=True)
390 if symbol and version_def in Data.INSTALLED_VCS_COMPONENTS and version_def.msvc_vernum >= 14.1:
391 # sxs list could be empty
392 self.assertTrue(toolset_full_list, "Toolset full list is empty for msvc version {}".format(repr(None)))
393 self.assertTrue(toolset_all_list, "Toolset all list is empty for msvc version {}".format(repr(None)))
394 else:
395 self.assertFalse(toolset_full_list, "Toolset full list is not empty for msvc version {}".format(repr(None)))
396 self.assertFalse(toolset_sxs_list, "Toolset sxs list is not empty for msvc version {}".format(repr(None)))
397 self.assertFalse(toolset_all_list, "Toolset all list is not empty for msvc version {}".format(repr(None)))
398 self.assertFalse(toolset_none_list, "Toolset none list is not empty for msvc version {}".format(repr(None)))
400 def test_valid_default_msvc(self) -> None:
401 if Data.HAVE_MSVC:
402 Patch.MSCommon.vc.msvc_default_version.enable_none()
403 self.run_valid_default_msvc()
404 Patch.MSCommon.vc.msvc_default_version.restore()
405 self.run_valid_default_msvc()
407 def test_valid_vcver(self) -> None:
408 for symbol in MSCommon.vc._VCVER:
409 version_def = MSCommon.msvc_version_components(symbol)
410 toolset_none_list = MSCommon.vc.msvc_toolset_versions(msvc_version=symbol, full=False, sxs=False)
411 toolset_full_list = MSCommon.vc.msvc_toolset_versions(msvc_version=symbol, full=True, sxs=False)
412 toolset_sxs_list = MSCommon.vc.msvc_toolset_versions(msvc_version=symbol, full=False, sxs=True)
413 toolset_all_list = MSCommon.vc.msvc_toolset_versions(msvc_version=symbol, full=True, sxs=True)
414 if version_def in Data.INSTALLED_VCS_COMPONENTS and version_def.msvc_vernum >= 14.1:
415 # sxs list could be empty
416 self.assertTrue(toolset_full_list, "Toolset full list is empty for msvc version {}".format(repr(symbol)))
417 self.assertTrue(toolset_all_list, "Toolset all list is empty for msvc version {}".format(repr(symbol)))
418 else:
419 self.assertFalse(toolset_full_list, "Toolset full list is not empty for msvc version {}".format(repr(symbol)))
420 self.assertFalse(toolset_sxs_list, "Toolset sxs list is not empty for msvc version {}".format(repr(symbol)))
421 self.assertFalse(toolset_all_list, "Toolset all list is not empty for msvc version {}".format(repr(symbol)))
422 self.assertFalse(toolset_none_list, "Toolset none list is not empty for msvc version {}".format(repr(symbol)))
424 def test_invalid_vcver(self) -> None:
425 for symbol in ['12.9', '6.0Exp', '14.3Exp', '99', '14.1Bug']:
426 with self.assertRaises(MSCommon.vc.MSVCArgumentError):
427 _ = MSCommon.vc.msvc_toolset_versions(msvc_version=symbol)
429 class MsvcToolsetVersionsSpectreTests(unittest.TestCase):
431 def run_valid_default_msvc(self) -> None:
432 symbol = MSCommon.vc.msvc_default_version()
433 version_def = MSCommon.msvc_version_components(symbol)
434 spectre_toolset_list = MSCommon.vc.msvc_toolset_versions_spectre(msvc_version=None)
435 if symbol and version_def in Data.INSTALLED_VCS_COMPONENTS and version_def.msvc_vernum >= 14.1:
436 # spectre toolset list can empty (may not be installed)
437 pass
438 else:
439 self.assertFalse(spectre_toolset_list, "Toolset spectre list is not empty for msvc version {}".format(repr(None)))
441 def test_valid_default_msvc(self) -> None:
442 if Data.HAVE_MSVC:
443 Patch.MSCommon.vc.msvc_default_version.enable_none()
444 self.run_valid_default_msvc()
445 Patch.MSCommon.vc.msvc_default_version.restore()
446 self.run_valid_default_msvc()
448 def test_valid_vcver(self) -> None:
449 for symbol in MSCommon.vc._VCVER:
450 version_def = MSCommon.msvc_version_components(symbol)
451 spectre_toolset_list = MSCommon.vc.msvc_toolset_versions_spectre(msvc_version=symbol)
452 if version_def in Data.INSTALLED_VCS_COMPONENTS and version_def.msvc_vernum >= 14.1:
453 # spectre toolset list can empty (may not be installed)
454 pass
455 else:
456 self.assertFalse(spectre_toolset_list, "Toolset spectre list is not empty for msvc version {}".format(repr(symbol)))
458 def test_invalid_vcver(self) -> None:
459 for symbol in ['12.9', '6.0Exp', '14.3Exp', '99', '14.1Bug']:
460 with self.assertRaises(MSCommon.vc.MSVCArgumentError):
461 _ = MSCommon.vc.msvc_toolset_versions_spectre(msvc_version=symbol)
463 class MsvcQueryVersionToolsetTests(unittest.TestCase):
464 """Test msvc_query_toolset_version"""
466 def run_valid_default_msvc(self, have_msvc) -> None:
467 for prefer_newest in (True, False):
468 if not have_msvc:
469 with self.assertRaises(MSCommon.vc.MSVCToolsetVersionNotFound):
470 msvc_version, msvc_toolset_version = MSCommon.vc.msvc_query_version_toolset(
471 version=None, prefer_newest=prefer_newest
473 continue
474 msvc_version = msvc_toolset_version = None
475 for vcver in Data.query_version_list(None):
476 try:
477 msvc_version, msvc_toolset_version = MSCommon.vc.msvc_query_version_toolset(
478 version=vcver, prefer_newest=prefer_newest
480 break
481 except MSCommon.vc.MSVCToolsetVersionNotFound:
482 pass
483 self.assertTrue(msvc_version, "unexpected msvc_version {} for for msvc version {}".format(
484 repr(msvc_version), repr(None)
486 version_def = MSCommon.msvc_version_components(msvc_version)
487 if version_def.msvc_vernum > 14.0:
488 # VS2017 and later for toolset version
489 self.assertTrue(msvc_toolset_version, "msvc_toolset_version is undefined for msvc version {}".format(
490 repr(None)
493 def test_valid_default_msvc(self) -> None:
494 if Data.HAVE_MSVC:
495 Patch.MSCommon.vc.msvc_default_version.enable_none()
496 self.run_valid_default_msvc(have_msvc=False)
497 Patch.MSCommon.vc.msvc_default_version.restore()
498 self.run_valid_default_msvc(have_msvc=Data.HAVE_MSVC)
500 def test_valid_vcver(self) -> None:
501 for symbol in MSCommon.vc._VCVER:
502 have_msvc = bool(symbol in Data.INSTALLED_VCS_TOOLSETS_COMPONENTS.toolset_vcs)
503 version_def = MSCommon.msvc_version_components(symbol)
504 for prefer_newest in (True, False):
505 if not have_msvc:
506 with self.assertRaises(MSCommon.vc.MSVCToolsetVersionNotFound):
507 msvc_version, msvc_toolset_version = MSCommon.vc.msvc_query_version_toolset(
508 version=symbol, prefer_newest=prefer_newest
510 continue
511 msvc_version = msvc_toolset_version = None
512 for vcver in Data.query_version_list(symbol):
513 try:
514 msvc_version, msvc_toolset_version = MSCommon.vc.msvc_query_version_toolset(
515 version=vcver, prefer_newest=prefer_newest
517 break
518 except:
519 pass
520 self.assertTrue(msvc_version, "msvc_version is undefined for msvc version {}".format(repr(symbol)))
521 if version_def.msvc_vernum > 14.0:
522 # VS2017 and later for toolset version
523 self.assertTrue(msvc_toolset_version, "msvc_toolset_version is undefined for msvc version {}".format(
524 repr(symbol)
527 def test_valid_vcver_toolsets(self) -> None:
528 for symbol in MSCommon.vc._VCVER:
529 toolset_list = MSCommon.vc.msvc_toolset_versions(msvc_version=symbol, full=True, sxs=True)
530 if toolset_list is None:
531 continue
532 for toolset in toolset_list:
533 extended_def = MSCommon.msvc_extended_version_components(toolset)
534 for prefer_newest in (True, False):
535 version = extended_def.msvc_toolset_version
536 msvc_version, msvc_toolset_version = MSCommon.vc.msvc_query_version_toolset(
537 version=version, prefer_newest=prefer_newest
539 self.assertTrue(msvc_version, "msvc_version is undefined for msvc toolset version {}".format(repr(toolset)))
540 if extended_def.msvc_vernum > 14.0:
541 # VS2017 and later for toolset version
542 self.assertTrue(msvc_toolset_version, "msvc_toolset_version is undefined for msvc toolset version {}".format(
543 repr(toolset)
546 def test_msvc_query_version_toolset_notfound(self) -> None:
547 toolset_notfound_dict = Data.msvc_toolset_notfound_dict()
548 for toolset_notfound_list in toolset_notfound_dict.values():
549 for toolset in toolset_notfound_list[:1]:
550 for prefer_newest in (True, False):
551 with self.assertRaises(MSCommon.vc.MSVCToolsetVersionNotFound):
552 _ = MSCommon.vc.msvc_query_version_toolset(version=toolset, prefer_newest=prefer_newest)
554 def test_invalid_vcver(self) -> None:
555 for symbol in ['12.9', '6.0Exp', '14.3Exp', '99', '14.1Bug']:
556 for prefer_newest in (True, False):
557 with self.assertRaises(MSCommon.vc.MSVCArgumentError):
558 _ = MSCommon.vc.msvc_query_version_toolset(version=symbol, prefer_newest=prefer_newest)
560 def test_invalid_vcver_toolsets(self) -> None:
561 for symbol in ['14.16.00000Exp', '14.00.00001', '14.31.123456', '14.31.1.1']:
562 for prefer_newest in (True, False):
563 with self.assertRaises(MSCommon.vc.MSVCArgumentError):
564 _ = MSCommon.vc.msvc_query_version_toolset(version=symbol, prefer_newest=prefer_newest)
567 if __name__ == "__main__":
568 unittest.main()