Merge pull request #4657 from mwichmann/feature/vars-defaulted
[scons.git] / SCons / Tool / MSCommon / MSVC / Config.py
blobd0ccb6d0bae341461eae1c872cfdc4dcaf0d9457
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.
24 """
25 Constants and initialized data structures for Microsoft Visual C/C++.
26 """
28 from collections import (
29 namedtuple,
32 from .Exceptions import (
33 MSVCInternalError,
36 from . import Dispatcher
37 Dispatcher.register_modulename(__name__)
40 UNDEFINED = object()
42 BOOLEAN_SYMBOLS = {}
43 BOOLEAN_EXTERNAL = {}
45 for bool_val, symbol_list, symbol_case_list in [
46 (False, (False, 0, '0', None, ''), ('False', 'No', 'F', 'N')),
47 (True, (True, 1, '1'), ('True', 'Yes', 'T', 'Y')),
49 BOOLEAN_SYMBOLS[bool_val] = list(symbol_list)
50 for symbol in symbol_case_list:
51 BOOLEAN_SYMBOLS[bool_val].extend([symbol, symbol.lower(), symbol.upper()])
53 for symbol in BOOLEAN_SYMBOLS[bool_val]:
54 BOOLEAN_EXTERNAL[symbol] = bool_val
56 MSVC_PLATFORM_DEFINITION = namedtuple('MSVCPlatform', [
57 'vc_platform',
58 'is_uwp',
61 MSVC_PLATFORM_DEFINITION_LIST = []
63 MSVC_PLATFORM_INTERNAL = {}
64 MSVC_PLATFORM_EXTERNAL = {}
66 for vc_platform, is_uwp in [
67 ('Desktop', False),
68 ('UWP', True),
71 vc_platform_def = MSVC_PLATFORM_DEFINITION(
72 vc_platform = vc_platform,
73 is_uwp = is_uwp,
76 MSVC_PLATFORM_DEFINITION_LIST.append(vc_platform_def)
78 MSVC_PLATFORM_INTERNAL[vc_platform] = vc_platform_def
80 for symbol in [vc_platform, vc_platform.lower(), vc_platform.upper()]:
81 MSVC_PLATFORM_EXTERNAL[symbol] = vc_platform_def
83 MSVC_RUNTIME_DEFINITION = namedtuple('MSVCRuntime', [
84 'vc_runtime',
85 'vc_runtime_numeric',
86 'vc_runtime_alias_list',
87 'vc_runtime_vsdef_list',
90 MSVC_RUNTIME_DEFINITION_LIST = []
92 MSVC_RUNTIME_INTERNAL = {}
93 MSVC_RUNTIME_EXTERNAL = {}
95 for vc_runtime, vc_runtime_numeric, vc_runtime_alias_list in [
96 ('140', 140, ['ucrt']),
97 ('120', 120, ['msvcr120']),
98 ('110', 110, ['msvcr110']),
99 ('100', 100, ['msvcr100']),
100 ('90', 90, ['msvcr90']),
101 ('80', 80, ['msvcr80']),
102 ('71', 71, ['msvcr71']),
103 ('70', 70, ['msvcr70']),
104 ('60', 60, ['msvcrt']),
106 vc_runtime_def = MSVC_RUNTIME_DEFINITION(
107 vc_runtime = vc_runtime,
108 vc_runtime_numeric = vc_runtime_numeric,
109 vc_runtime_alias_list = vc_runtime_alias_list,
110 vc_runtime_vsdef_list = [],
113 MSVC_RUNTIME_DEFINITION_LIST.append(vc_runtime_def)
115 MSVC_RUNTIME_INTERNAL[vc_runtime] = vc_runtime_def
116 MSVC_RUNTIME_EXTERNAL[vc_runtime] = vc_runtime_def
118 for vc_runtime_alias in vc_runtime_alias_list:
119 MSVC_RUNTIME_EXTERNAL[vc_runtime_alias] = vc_runtime_def
121 MSVC_BUILDSERIES_DEFINITION = namedtuple('MSVCBuildSeries', [
122 'vc_buildseries',
123 'vc_buildseries_numeric',
124 'vc_version',
125 'vc_version_numeric',
126 'cl_version',
127 'cl_version_numeric',
130 MSVC_BUILDSERIES_DEFINITION_LIST = []
132 MSVC_BUILDSERIES_INTERNAL = {}
133 MSVC_BUILDSERIES_EXTERNAL = {}
135 VC_BUILDTOOLS_MAP = {}
137 VC_VERSION_MAP = {}
138 CL_VERSION_MAP = {}
140 for (vc_buildseries, vc_version, cl_version) in [
141 ('144', '14.4', '19.4'),
142 ('143', '14.3', '19.3'),
143 ('142', '14.2', '19.2'),
144 ('141', '14.1', '19.1'),
145 ('140', '14.0', '19.0'),
146 ('120', '12.0', '18.0'),
147 ('110', '11.0', '17.0'),
148 ('100', '10.0', '16.0'),
149 ('90', '9.0', '15.0'),
150 ('80', '8.0', '14.0'),
151 ('71', '7.1', '13.1'),
152 ('70', '7.0', '13.0'),
153 ('60', '6.0', '12.0'),
156 vc_buildseries_def = MSVC_BUILDSERIES_DEFINITION(
157 vc_buildseries=vc_buildseries,
158 vc_buildseries_numeric=int(vc_buildseries),
159 vc_version=vc_version,
160 vc_version_numeric=float(vc_version),
161 cl_version=cl_version,
162 cl_version_numeric=float(cl_version),
165 MSVC_BUILDSERIES_DEFINITION_LIST.append(vc_buildseries_def)
167 MSVC_BUILDSERIES_INTERNAL[vc_buildseries] = vc_buildseries_def
168 MSVC_BUILDSERIES_EXTERNAL[vc_buildseries] = vc_buildseries_def
169 MSVC_BUILDSERIES_EXTERNAL[vc_version] = vc_buildseries_def
171 VC_VERSION_MAP[vc_version] = vc_buildseries_def
172 CL_VERSION_MAP[cl_version] = vc_buildseries_def
174 MSVC_BUILDTOOLS_DEFINITION = namedtuple('MSVCBuildtools', [
175 'vc_buildtools',
176 'vc_buildtools_numeric',
177 'vc_buildseries_list',
178 'vc_runtime_def',
179 'vc_istoolset',
180 'msvc_version',
181 'msvc_version_numeric',
184 MSVC_BUILDTOOLS_DEFINITION_LIST = []
186 MSVC_BUILDTOOLS_INTERNAL = {}
187 MSVC_BUILDTOOLS_EXTERNAL = {}
189 MSVC_VERSION_NEWEST = None
190 MSVC_VERSION_NEWEST_NUMERIC = 0.0
192 for vc_buildtools, vc_buildseries_list, vc_runtime, vc_istoolset in [
193 ('v143', ['144', '143'], '140', True),
194 ('v142', ['142'], '140', True),
195 ('v141', ['141'], '140', True),
196 ('v140', ['140'], '140', True),
197 ('v120', ['120'], '120', False),
198 ('v110', ['110'], '110', False),
199 ('v100', ['100'], '100', False),
200 ('v90', ['90'], '90', False),
201 ('v80', ['80'], '80', False),
202 ('v71', ['71'], '71', False),
203 ('v70', ['70'], '70', False),
204 ('v60', ['60'], '60', False),
207 vc_runtime_def = MSVC_RUNTIME_INTERNAL[vc_runtime]
209 vc_buildseries_list = tuple(
210 MSVC_BUILDSERIES_INTERNAL[vc_buildseries]
211 for vc_buildseries in vc_buildseries_list
214 vc_buildtools_numstr = vc_buildtools[1:]
216 msvc_version = vc_buildtools_numstr[:-1] + '.' + vc_buildtools_numstr[-1]
217 msvc_version_numeric = float(msvc_version)
219 vc_buildtools_def = MSVC_BUILDTOOLS_DEFINITION(
220 vc_buildtools = vc_buildtools,
221 vc_buildtools_numeric = int(vc_buildtools[1:]),
222 vc_buildseries_list = vc_buildseries_list,
223 vc_runtime_def = vc_runtime_def,
224 vc_istoolset = vc_istoolset,
225 msvc_version = msvc_version,
226 msvc_version_numeric = msvc_version_numeric,
229 MSVC_BUILDTOOLS_DEFINITION_LIST.append(vc_buildtools_def)
231 MSVC_BUILDTOOLS_INTERNAL[vc_buildtools] = vc_buildtools_def
232 MSVC_BUILDTOOLS_EXTERNAL[vc_buildtools] = vc_buildtools_def
233 MSVC_BUILDTOOLS_EXTERNAL[msvc_version] = vc_buildtools_def
235 for vc_buildseries_def in vc_buildseries_list:
236 VC_BUILDTOOLS_MAP[vc_buildseries_def.vc_buildseries] = vc_buildtools_def
238 if vc_buildtools_def.msvc_version_numeric > MSVC_VERSION_NEWEST_NUMERIC:
239 MSVC_VERSION_NEWEST_NUMERIC = vc_buildtools_def.msvc_version_numeric
240 MSVC_VERSION_NEWEST = vc_buildtools_def.msvc_version
242 MSVS_VERSION_INTERNAL = {}
243 MSVS_VERSION_EXTERNAL = {}
245 MSVC_VERSION_INTERNAL = {}
246 MSVC_VERSION_EXTERNAL = {}
247 MSVC_VERSION_SUFFIX = {}
249 MSVS_VERSION_MAJOR_MAP = {}
251 MSVC_SDK_VERSIONS = set()
253 VISUALSTUDIO_DEFINITION = namedtuple('VisualStudioDefinition', [
254 'vs_product',
255 'vs_product_alias_list',
256 'vs_version',
257 'vs_version_major',
258 'vs_envvar',
259 'vs_express',
260 'vs_lookup',
261 'vc_sdk_versions',
262 'vc_ucrt_versions',
263 'vc_uwp',
264 'vc_buildtools_def',
265 'vc_buildtools_all',
268 VISUALSTUDIO_DEFINITION_LIST = []
270 VS_PRODUCT_ALIAS = {
271 '1998': ['6']
274 # vs_envvar: VisualStudioVersion defined in environment for MSVS 2012 and later
275 # MSVS 2010 and earlier cl_version -> vs_def is a 1:1 mapping
276 # SDK attached to product or buildtools?
277 for vs_product, vs_version, vs_envvar, vs_express, vs_lookup, vc_sdk, vc_ucrt, vc_uwp, vc_buildtools_all in [
278 ('2022', '17.0', True, False, 'vswhere' , ['10.0', '8.1'], ['10'], 'uwp', ['v143', 'v142', 'v141', 'v140']),
279 ('2019', '16.0', True, False, 'vswhere' , ['10.0', '8.1'], ['10'], 'uwp', ['v142', 'v141', 'v140']),
280 ('2017', '15.0', True, True, 'vswhere' , ['10.0', '8.1'], ['10'], 'uwp', ['v141', 'v140']),
281 ('2015', '14.0', True, True, 'registry', ['10.0', '8.1'], ['10'], 'store', ['v140']),
282 ('2013', '12.0', True, True, 'registry', None, None, None, ['v120']),
283 ('2012', '11.0', True, True, 'registry', None, None, None, ['v110']),
284 ('2010', '10.0', False, True, 'registry', None, None, None, ['v100']),
285 ('2008', '9.0', False, True, 'registry', None, None, None, ['v90']),
286 ('2005', '8.0', False, True, 'registry', None, None, None, ['v80']),
287 ('2003', '7.1', False, False, 'registry', None, None, None, ['v71']),
288 ('2002', '7.0', False, False, 'registry', None, None, None, ['v70']),
289 ('1998', '6.0', False, False, 'registry', None, None, None, ['v60']),
292 vs_version_major = vs_version.split('.')[0]
294 vc_buildtools_def = MSVC_BUILDTOOLS_INTERNAL[vc_buildtools_all[0]]
296 vs_def = VISUALSTUDIO_DEFINITION(
297 vs_product = vs_product,
298 vs_product_alias_list = [],
299 vs_version = vs_version,
300 vs_version_major = vs_version_major,
301 vs_envvar = vs_envvar,
302 vs_express = vs_express,
303 vs_lookup = vs_lookup,
304 vc_sdk_versions = vc_sdk,
305 vc_ucrt_versions = vc_ucrt,
306 vc_uwp = vc_uwp,
307 vc_buildtools_def = vc_buildtools_def,
308 vc_buildtools_all = vc_buildtools_all,
311 VISUALSTUDIO_DEFINITION_LIST.append(vs_def)
313 vc_buildtools_def.vc_runtime_def.vc_runtime_vsdef_list.append(vs_def)
315 msvc_version = vc_buildtools_def.msvc_version
317 MSVS_VERSION_INTERNAL[vs_product] = vs_def
318 MSVS_VERSION_EXTERNAL[vs_product] = vs_def
319 MSVS_VERSION_EXTERNAL[vs_version] = vs_def
321 MSVC_VERSION_INTERNAL[msvc_version] = vs_def
322 MSVC_VERSION_EXTERNAL[vs_product] = vs_def
323 MSVC_VERSION_EXTERNAL[msvc_version] = vs_def
324 MSVC_VERSION_EXTERNAL[vc_buildtools_def.vc_buildtools] = vs_def
326 if vs_product in VS_PRODUCT_ALIAS:
327 for vs_product_alias in VS_PRODUCT_ALIAS[vs_product]:
328 vs_def.vs_product_alias_list.append(vs_product_alias)
329 MSVS_VERSION_EXTERNAL[vs_product_alias] = vs_def
330 MSVC_VERSION_EXTERNAL[vs_product_alias] = vs_def
332 MSVC_VERSION_SUFFIX[msvc_version] = vs_def
333 if vs_express:
334 MSVC_VERSION_SUFFIX[msvc_version + 'Exp'] = vs_def
336 MSVS_VERSION_MAJOR_MAP[vs_version_major] = vs_def
338 if vc_sdk:
339 MSVC_SDK_VERSIONS.update(vc_sdk)
341 # EXPERIMENTAL: msvc version/toolset search lists
343 # VS2017 example:
345 # defaults['14.1'] = ['14.1', '14.1Exp']
346 # defaults['14.1Exp'] = ['14.1Exp']
348 # search['14.1'] = ['14.3', '14.2', '14.1', '14.1Exp']
349 # search['14.1Exp'] = ['14.1Exp']
351 MSVC_VERSION_TOOLSET_DEFAULTS_MAP = {}
352 MSVC_VERSION_TOOLSET_SEARCH_MAP = {}
354 # Pass 1: Build defaults lists and setup express versions
355 for vs_def in VISUALSTUDIO_DEFINITION_LIST:
356 if not vs_def.vc_buildtools_def.vc_istoolset:
357 continue
358 version_key = vs_def.vc_buildtools_def.msvc_version
359 MSVC_VERSION_TOOLSET_DEFAULTS_MAP[version_key] = [version_key]
360 MSVC_VERSION_TOOLSET_SEARCH_MAP[version_key] = []
361 if vs_def.vs_express:
362 express_key = version_key + 'Exp'
363 MSVC_VERSION_TOOLSET_DEFAULTS_MAP[version_key].append(express_key)
364 MSVC_VERSION_TOOLSET_DEFAULTS_MAP[express_key] = [express_key]
365 MSVC_VERSION_TOOLSET_SEARCH_MAP[express_key] = [express_key]
367 # Pass 2: Extend search lists (decreasing version order)
368 for vs_def in VISUALSTUDIO_DEFINITION_LIST:
369 if not vs_def.vc_buildtools_def.vc_istoolset:
370 continue
371 version_key = vs_def.vc_buildtools_def.msvc_version
372 for vc_buildtools in vs_def.vc_buildtools_all:
373 toolset_buildtools_def = MSVC_BUILDTOOLS_INTERNAL[vc_buildtools]
374 toolset_vs_def = MSVC_VERSION_INTERNAL[toolset_buildtools_def.msvc_version]
375 buildtools_key = toolset_buildtools_def.msvc_version
376 MSVC_VERSION_TOOLSET_SEARCH_MAP[buildtools_key].extend(MSVC_VERSION_TOOLSET_DEFAULTS_MAP[version_key])
378 # convert string version set to string version list ranked in descending order
379 MSVC_SDK_VERSIONS = [str(f) for f in sorted([float(s) for s in MSVC_SDK_VERSIONS], reverse=True)]
382 def verify():
383 from . import Util
384 from .. import vc
385 for msvc_version in vc._VCVER:
386 if msvc_version not in MSVC_VERSION_SUFFIX:
387 err_msg = f'msvc_version {msvc_version!r} not in MSVC_VERSION_SUFFIX'
388 raise MSVCInternalError(err_msg)
389 vc_version = Util.get_msvc_version_prefix(msvc_version)
390 if vc_version not in MSVC_VERSION_INTERNAL:
391 err_msg = f'vc_version {vc_version!r} not in MSVC_VERSION_INTERNAL'
392 raise MSVCInternalError(err_msg)