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 Helper functions for Microsoft Visual C/C++.
31 from collections
import (
41 Return a list of tuples for each subdirectory of the given directory path.
42 Each tuple is comprised of the subdirectory name and the qualified subdirectory path.
49 list[tuple[str,str]]: a list of tuples
53 if p
and os
.path
.exists(p
) and os
.path
.isdir(p
):
54 for dir_name
in os
.listdir(p
):
55 dir_path
= os
.path
.join(p
, dir_name
)
56 if os
.path
.isdir(dir_path
):
57 dirs
.append((dir_name
, dir_path
))
62 Normalize a system path
69 str: normalized system path
73 p
= os
.path
.normpath(p
)
74 p
= os
.path
.realpath(p
)
75 p
= os
.path
.normcase(p
)
78 # msvc version and msvc toolset version regexes
80 re_version_prefix
= re
.compile('^(?P<version>[0-9]+(?:[.][0-9]+)*)(?![.]).*$')
82 re_msvc_version_prefix
= re
.compile(r
'^(?P<version>[1-9][0-9]?[.][0-9]).*$')
84 re_msvc_version
= re
.compile(r
'^(?P<msvc_version>[1-9][0-9]?[.][0-9])(?P<suffix>[A-Z]+)*$', re
.IGNORECASE
)
86 re_extended_version
= re
.compile(r
'''^
88 ([1-9][0-9]?[.][0-9]{1,2})| # XX.Y - XX.YY
89 ([1-9][0-9][.][0-9]{2}[.][0-9]{1,5})| # XX.YY.Z - XX.YY.ZZZZZ
90 ([1-9][0-9][.][0-9]{2}[.][0-9]{2}[.][0-9]{1,2}) # XX.YY.AA.B - XX.YY.AA.BB
93 $''', re
.IGNORECASE | re
.VERBOSE
)
95 re_toolset_full
= re
.compile(r
'''^(?:
96 (?:[1-9][0-9][.][0-9]{1,2})| # XX.Y - XX.YY
97 (?:[1-9][0-9][.][0-9]{2}[.][0-9]{1,5}) # XX.YY.Z - XX.YY.ZZZZZ
100 re_toolset_140
= re
.compile(r
'''^(?:
101 (?:14[.]0{1,2})| # 14.0 - 14.00
102 (?:14[.]0{2}[.]0{1,5}) # 14.00.0 - 14.00.00000
105 re_toolset_sxs
= re
.compile(
106 r
'^[1-9][0-9][.][0-9]{2}[.][0-9]{2}[.][0-9]{1,2}$' # MM.mm.VV.vv format
109 # msvc sdk version regexes
111 re_msvc_sdk_version
= re
.compile(r
'''^
113 ([1-9][0-9]?[.][0-9])| # XX.Y
114 ([1-9][0-9][.][0-9]{1}[.][0-9]{5}[.][0-9]{1,2}) # XX.Y.ZZZZZ.A - XX.Y.ZZZZZ.AA
116 $''', re
.IGNORECASE | re
.VERBOSE
)
118 # version prefix utilities
120 def get_version_prefix(version
):
122 Get the version number prefix from a string.
126 version specification
129 str: the version number prefix
134 m
= re_version_prefix
.match(version
)
136 rval
= m
.group('version')
139 def get_msvc_version_prefix(version
):
141 Get the msvc version number prefix from a string.
145 version specification
148 str: the msvc version number prefix
153 m
= re_msvc_version_prefix
.match(version
)
155 rval
= m
.group('version')
158 # toolset version query utilities
160 def is_toolset_full(toolset_version
) -> bool:
163 if re_toolset_full
.match(toolset_version
):
167 def is_toolset_140(toolset_version
) -> bool:
170 if re_toolset_140
.match(toolset_version
):
174 def is_toolset_sxs(toolset_version
) -> bool:
177 if re_toolset_sxs
.match(toolset_version
):
181 # msvc version and msvc toolset version decomposition utilties
183 _MSVC_VERSION_COMPONENTS_DEFINITION
= namedtuple('MSVCVersionComponentsDefinition', [
184 'msvc_version', # msvc version (e.g., '14.1Exp')
185 'msvc_verstr', # msvc version numeric string (e.g., '14.1')
186 'msvc_suffix', # msvc version component type (e.g., 'Exp')
187 'msvc_vernum', # msvc version floating point number (e.g, 14.1)
188 'msvc_major', # msvc major version integer number (e.g., 14)
189 'msvc_minor', # msvc minor version integer number (e.g., 1)
190 'msvc_comps', # msvc version components tuple (e.g., ('14', '1'))
193 def msvc_version_components(vcver
):
195 Decompose an msvc version into components.
198 msvc_version: msvc version (e.g., '14.1Exp')
199 msvc_verstr: msvc version numeric string (e.g., '14.1')
200 msvc_suffix: msvc version component type (e.g., 'Exp')
201 msvc_vernum: msvc version floating point number (e.g., 14.1)
202 msvc_major: msvc major version integer number (e.g., 14)
203 msvc_minor: msvc minor version integer number (e.g., 1)
204 msvc_comps: msvc version components tuple (e.g., ('14', '1'))
208 msvc version specification
211 None or MSVCVersionComponents namedtuple:
217 m
= re_msvc_version
.match(vcver
)
221 vs_def
= Config
.MSVC_VERSION_SUFFIX
.get(vcver
)
226 msvc_verstr
= m
.group('msvc_version')
227 msvc_suffix
= m
.group('suffix') if m
.group('suffix') else ''
228 msvc_vernum
= float(msvc_verstr
)
230 msvc_comps
= tuple(msvc_verstr
.split('.'))
231 msvc_major
, msvc_minor
= [int(x
) for x
in msvc_comps
]
233 msvc_version_components_def
= _MSVC_VERSION_COMPONENTS_DEFINITION(
234 msvc_version
= msvc_version
,
235 msvc_verstr
= msvc_verstr
,
236 msvc_suffix
= msvc_suffix
,
237 msvc_vernum
= msvc_vernum
,
238 msvc_major
= msvc_major
,
239 msvc_minor
= msvc_minor
,
240 msvc_comps
= msvc_comps
,
243 return msvc_version_components_def
245 _MSVC_EXTENDED_VERSION_COMPONENTS_DEFINITION
= namedtuple('MSVCExtendedVersionComponentsDefinition', [
246 'msvc_version', # msvc version (e.g., '14.1Exp')
247 'msvc_verstr', # msvc version numeric string (e.g., '14.1')
248 'msvc_suffix', # msvc version component type (e.g., 'Exp')
249 'msvc_vernum', # msvc version floating point number (e.g, 14.1)
250 'msvc_major', # msvc major version integer number (e.g., 14)
251 'msvc_minor', # msvc minor version integer number (e.g., 1)
252 'msvc_comps', # msvc version components tuple (e.g., ('14', '1'))
253 'msvc_toolset_version', # msvc toolset version
254 'msvc_toolset_comps', # msvc toolset version components
255 'version', # msvc version or msvc toolset version
258 def msvc_extended_version_components(version
):
260 Decompose an msvc version or msvc toolset version into components.
264 version specification
267 None or MSVCExtendedVersionComponents namedtuple:
273 m
= re_extended_version
.match(version
)
277 msvc_toolset_version
= m
.group('version')
278 msvc_toolset_comps
= tuple(msvc_toolset_version
.split('.'))
280 msvc_verstr
= get_msvc_version_prefix(msvc_toolset_version
)
284 msvc_suffix
= m
.group('suffix') if m
.group('suffix') else ''
285 msvc_version
= msvc_verstr
+ msvc_suffix
287 vs_def
= Config
.MSVC_VERSION_SUFFIX
.get(msvc_version
)
291 msvc_vernum
= float(msvc_verstr
)
293 msvc_comps
= tuple(msvc_verstr
.split('.'))
294 msvc_major
, msvc_minor
= [int(x
) for x
in msvc_comps
]
296 msvc_extended_version_components_def
= _MSVC_EXTENDED_VERSION_COMPONENTS_DEFINITION(
297 msvc_version
= msvc_version
,
298 msvc_verstr
= msvc_verstr
,
299 msvc_suffix
= msvc_suffix
,
300 msvc_vernum
= msvc_vernum
,
301 msvc_major
= msvc_major
,
302 msvc_minor
= msvc_minor
,
303 msvc_comps
= msvc_comps
,
304 msvc_toolset_version
= msvc_toolset_version
,
305 msvc_toolset_comps
= msvc_toolset_comps
,
309 return msvc_extended_version_components_def
311 # msvc sdk version decomposition utilties
313 _MSVC_SDK_VERSION_COMPONENTS_DEFINITION
= namedtuple('MSVCSDKVersionComponentsDefinition', [
314 'sdk_version', # sdk version (e.g., '10.0.20348.0')
315 'sdk_verstr', # sdk version numeric string (e.g., '10.0')
316 'sdk_vernum', # sdk version floating point number (e.g, 10.0)
317 'sdk_major', # sdk major version integer number (e.g., 10)
318 'sdk_minor', # sdk minor version integer number (e.g., 0)
319 'sdk_comps', # sdk version components tuple (e.g., ('10', '0', '20348', '0'))
322 def msvc_sdk_version_components(version
):
324 Decompose an msvc sdk version into components.
327 sdk_version: sdk version (e.g., '10.0.20348.0')
328 sdk_verstr: sdk version numeric string (e.g., '10.0')
329 sdk_vernum: sdk version floating point number (e.g., 10.0)
330 sdk_major: sdk major version integer number (e.g., 10)
331 sdk_minor: sdk minor version integer number (e.g., 0)
332 sdk_comps: sdk version components tuple (e.g., ('10', '0', '20348', '0'))
336 sdk version specification
339 None or MSVCSDKVersionComponents namedtuple:
345 m
= re_msvc_sdk_version
.match(version
)
349 sdk_version
= version
350 sdk_comps
= tuple(sdk_version
.split('.'))
351 sdk_verstr
= '.'.join(sdk_comps
[:2])
352 sdk_vernum
= float(sdk_verstr
)
354 sdk_major
, sdk_minor
= [int(x
) for x
in sdk_comps
[:2]]
356 msvc_sdk_version_components_def
= _MSVC_SDK_VERSION_COMPONENTS_DEFINITION(
357 sdk_version
= sdk_version
,
358 sdk_verstr
= sdk_verstr
,
359 sdk_vernum
= sdk_vernum
,
360 sdk_major
= sdk_major
,
361 sdk_minor
= sdk_minor
,
362 sdk_comps
= sdk_comps
,
365 return msvc_sdk_version_components_def