summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoseph Brill <48932340+jcbrill@users.noreply.github.com>2022-07-09 18:49:53 (GMT)
committerJoseph Brill <48932340+jcbrill@users.noreply.github.com>2022-07-09 18:49:53 (GMT)
commit04a5dea1a00abd7ffdc4c274f000273ce6ff37db (patch)
treede73f1079176391dae6b9084d19effa9b7657dd8
parent23f63fc766f9e157bfe8642b8559983dde684dd3 (diff)
downloadSCons-04a5dea1a00abd7ffdc4c274f000273ce6ff37db.zip
SCons-04a5dea1a00abd7ffdc4c274f000273ce6ff37db.tar.gz
SCons-04a5dea1a00abd7ffdc4c274f000273ce6ff37db.tar.bz2
Rework version convenience functions. Add additional tests.
-rw-r--r--SCons/Tool/MSCommon/MSVC/Config.py35
-rw-r--r--SCons/Tool/MSCommon/MSVC/ScriptArguments.py6
-rw-r--r--SCons/Tool/MSCommon/MSVC/Util.py126
-rw-r--r--SCons/Tool/MSCommon/MSVC/WinSDK.py5
-rw-r--r--SCons/Tool/MSCommon/MSVC/__init__.py2
-rw-r--r--SCons/Tool/MSCommon/__init__.py3
-rw-r--r--SCons/Tool/MSCommon/vc.py51
-rw-r--r--test/MSVC/MSVC_SDK_VERSION.py8
-rw-r--r--test/MSVC/MSVC_TOOLSET_VERSION.py25
-rw-r--r--test/MSVC/msvc_cache_force_defaults.py81
-rw-r--r--test/MSVC/msvc_sdk_versions.py90
-rw-r--r--test/MSVC/msvc_version_components.py61
-rw-r--r--test/MSVC/no_msvc.py10
-rw-r--r--test/fixture/no_msvc/no_msvcs_sconstruct_msvc_sdk_versions.py15
-rw-r--r--test/fixture/no_msvc/no_msvcs_sconstruct_msvc_toolset_versions.py15
15 files changed, 437 insertions, 96 deletions
diff --git a/SCons/Tool/MSCommon/MSVC/Config.py b/SCons/Tool/MSCommon/MSVC/Config.py
index 60e2910..3bb7d07 100644
--- a/SCons/Tool/MSCommon/MSVC/Config.py
+++ b/SCons/Tool/MSCommon/MSVC/Config.py
@@ -179,6 +179,7 @@ MSVS_VERSION_EXTERNAL = {}
MSVC_VERSION_INTERNAL = {}
MSVC_VERSION_EXTERNAL = {}
+MSVC_VERSION_SUFFIX = {}
MSVS_VERSION_MAJOR_MAP = {}
@@ -248,13 +249,15 @@ for vs_product, vs_version, vs_envvar, vs_express, vs_lookup, vc_sdk, vc_ucrt, v
vc_buildtools_def.vc_runtime_def.vc_runtime_vsdef_list.append(vs_def)
+ vc_version = vc_buildtools_def.vc_version
+
MSVS_VERSION_INTERNAL[vs_product] = vs_def
MSVS_VERSION_EXTERNAL[vs_product] = vs_def
MSVS_VERSION_EXTERNAL[vs_version] = vs_def
- MSVC_VERSION_INTERNAL[vc_buildtools_def.vc_version] = vs_def
+ MSVC_VERSION_INTERNAL[vc_version] = vs_def
MSVC_VERSION_EXTERNAL[vs_product] = vs_def
- MSVC_VERSION_EXTERNAL[vc_buildtools_def.vc_version] = vs_def
+ MSVC_VERSION_EXTERNAL[vc_version] = vs_def
MSVC_VERSION_EXTERNAL[vc_buildtools_def.vc_buildtools] = vs_def
if vs_product in VS_PRODUCT_ALIAS:
@@ -263,14 +266,16 @@ for vs_product, vs_version, vs_envvar, vs_express, vs_lookup, vc_sdk, vc_ucrt, v
MSVS_VERSION_EXTERNAL[vs_product_alias] = vs_def
MSVC_VERSION_EXTERNAL[vs_product_alias] = vs_def
+ MSVC_VERSION_SUFFIX[vc_version] = vs_def
+ if vs_express:
+ MSVC_VERSION_SUFFIX[vc_version + 'Exp'] = vs_def
+
MSVS_VERSION_MAJOR_MAP[vs_version_major] = vs_def
CL_VERSION_MAP[vc_buildtools_def.cl_version] = vs_def
- if not vc_sdk:
- continue
-
- MSVC_SDK_VERSIONS.update(vc_sdk)
+ if vc_sdk:
+ MSVC_SDK_VERSIONS.update(vc_sdk)
# EXPERIMENTAL: msvc version/toolset search lists
#
@@ -312,21 +317,15 @@ for vs_def in VISUALSTUDIO_DEFINITION_LIST:
# convert string version set to string version list ranked in descending order
MSVC_SDK_VERSIONS = [str(f) for f in sorted([float(s) for s in MSVC_SDK_VERSIONS], reverse=True)]
-MSVS_VERSION_LEGACY = {}
-MSVC_VERSION_LEGACY = {}
-
-for vdict in (MSVS_VERSION_EXTERNAL, MSVC_VERSION_INTERNAL):
- for key, vs_def in vdict.items():
- if key not in MSVS_VERSION_LEGACY:
- MSVS_VERSION_LEGACY[key] = vs_def
- MSVC_VERSION_LEGACY[key] = vs_def
def verify():
from .. import vc
for msvc_version in vc._VCVER:
+ if not msvc_version in MSVC_VERSION_SUFFIX:
+ err_msg = 'msvc_version {} not in MSVC_VERSION_SUFFIX'.format(repr(msvc_version))
+ raise MSVCInternalError(err_msg)
vc_version = Util.get_msvc_version_prefix(msvc_version)
- if vc_version in MSVC_VERSION_INTERNAL:
- continue
- err_msg = 'vc_version {} not in MSVC_VERSION_INTERNAL'.format(repr(vc_version))
- raise MSVCInternalError(err_msg)
+ if vc_version not in MSVC_VERSION_INTERNAL:
+ err_msg = 'vc_version {} not in MSVC_VERSION_INTERNAL'.format(repr(vc_version))
+ raise MSVCInternalError(err_msg)
diff --git a/SCons/Tool/MSCommon/MSVC/ScriptArguments.py b/SCons/Tool/MSCommon/MSVC/ScriptArguments.py
index d07b78f..fab948e 100644
--- a/SCons/Tool/MSCommon/MSVC/ScriptArguments.py
+++ b/SCons/Tool/MSCommon/MSVC/ScriptArguments.py
@@ -77,6 +77,8 @@ def _verify_re_sdk_dispatch_map():
raise MSVCInternalError(err_msg)
return None
+# toolset regexes need to accept same formats as extended version regexes in ./Util.py
+
# capture msvc version
re_toolset_version = re.compile(r'^(?P<version>[1-9][0-9]?[.][0-9])[0-9.]*$', re.IGNORECASE)
@@ -323,7 +325,7 @@ def _msvc_script_argument_sdk(env, msvc, toolset, platform_def, arglist):
if err_msg:
raise MSVCArgumentError(err_msg)
- sdk_list = WinSDK.get_sdk_version_list(msvc.vs_def.vc_sdk_versions, platform_def)
+ sdk_list = WinSDK.get_sdk_version_list(msvc.vs_def, platform_def)
if sdk_version not in sdk_list:
err_msg = "MSVC_SDK_VERSION {} not found for platform type {}".format(
@@ -345,7 +347,7 @@ def _msvc_script_default_sdk(env, msvc, platform_def, arglist):
if msvc.vs_def.vc_buildtools_def.vc_version_numeric < VS2015.vc_buildtools_def.vc_version_numeric:
return None
- sdk_list = WinSDK.get_sdk_version_list(msvc.vs_def.vc_sdk_versions, platform_def)
+ sdk_list = WinSDK.get_sdk_version_list(msvc.vs_def, platform_def)
if not len(sdk_list):
return None
diff --git a/SCons/Tool/MSCommon/MSVC/Util.py b/SCons/Tool/MSCommon/MSVC/Util.py
index f7e9091..e5e719c 100644
--- a/SCons/Tool/MSCommon/MSVC/Util.py
+++ b/SCons/Tool/MSCommon/MSVC/Util.py
@@ -32,6 +32,8 @@ from collections import (
namedtuple,
)
+from . import Config
+
def listdir_dirs(p):
"""
Return a list of tuples for each subdirectory of the given directory path.
@@ -113,47 +115,9 @@ def get_msvc_version_prefix(version):
rval = ''
return rval
-_VERSION_ELEMENTS_DEFINITION = namedtuple('VersionElements', [
- 'vc_version_numstr', # msvc version numeric string ('14.1')
- 'vc_toolset_numstr', # toolset version numeric string ('14.16.27023')
- 'vc_version_suffix', # component type ('Exp')
- 'msvc_version', # msvc version ('14.1Exp')
-])
-
-re_version_elements = re.compile(r'^(?P<version>(?P<msvc_version>[1-9][0-9]?[.][0-9])[0-9.]*)(?P<suffix>[A-Z]+)*$', re.IGNORECASE)
-
-def get_version_elements(version):
- """
- Get the version elements from an msvc version or toolset version.
-
- Args:
- version: str
- version specification
-
- Returns:
- None or VersionElements namedtuple:
- """
-
- m = re_version_elements.match(version)
- if not m:
- return None
-
- vc_version_numstr = m.group('msvc_version')
- vc_toolset_numstr = m.group('version')
- vc_version_suffix = m.group('suffix') if m.group('suffix') else ''
-
- version_elements_def = _VERSION_ELEMENTS_DEFINITION(
- vc_version_numstr = vc_version_numstr,
- vc_toolset_numstr = vc_toolset_numstr,
- vc_version_suffix = vc_version_suffix,
- msvc_version = vc_version_numstr + vc_version_suffix,
- )
-
- return version_elements_def
-
-# test suite convenience function
+# convenience functions
-_MSVC_VERSION_COMPONENTS = namedtuple('MSVCVersionComponents', [
+_MSVC_VERSION_COMPONENTS_DEFINITION = namedtuple('MSVCVersionComponentsDefinition', [
'msvc_version', # msvc version (e.g., '14.1Exp')
'msvc_verstr', # msvc version numeric string (e.g., '14.1')
'msvc_suffix', # msvc version component type (e.g., 'Exp')
@@ -164,9 +128,9 @@ _MSVC_VERSION_COMPONENTS = namedtuple('MSVCVersionComponents', [
re_msvc_version = re.compile(r'^(?P<msvc_version>[1-9][0-9]?[.][0-9])(?P<suffix>[A-Z]+)*$', re.IGNORECASE)
-def get_msvc_version_components(vcver):
+def msvc_version_components(vcver):
"""
- Get a tuple of msvc version components.
+ Decompose an msvc version into components.
Tuple fields:
msvc_version: msvc version (e.g., '14.1Exp')
@@ -188,6 +152,10 @@ def get_msvc_version_components(vcver):
if not m:
return None
+ vs_def = Config.MSVC_VERSION_SUFFIX.get(vcver)
+ if not vs_def:
+ return None
+
msvc_version = vcver
msvc_verstr = m.group('msvc_version')
msvc_suffix = m.group('suffix') if m.group('suffix') else ''
@@ -195,14 +163,82 @@ def get_msvc_version_components(vcver):
msvc_major, msvc_minor = [int(x) for x in msvc_verstr.split('.')]
- msvc_version_components_def = _MSVC_VERSION_COMPONENTS(
- msvc_vernum = msvc_vernum,
+ msvc_version_components_def = _MSVC_VERSION_COMPONENTS_DEFINITION(
+ msvc_version = msvc_version,
msvc_verstr = msvc_verstr,
msvc_suffix = msvc_suffix,
- msvc_version = msvc_version,
+ msvc_vernum = msvc_vernum,
msvc_major = msvc_major,
msvc_minor = msvc_minor,
)
return msvc_version_components_def
+_MSVC_EXTENDED_VERSION_COMPONENTS_DEFINITION = namedtuple('MSVCExtendedVersionComponentsDefinition', [
+ 'msvc_version', # msvc version (e.g., '14.1Exp')
+ 'msvc_verstr', # msvc version numeric string (e.g., '14.1')
+ 'msvc_suffix', # msvc version component type (e.g., 'Exp')
+ 'msvc_vernum', # msvc version floating point number (e.g, 14.1)
+ 'msvc_major', # msvc major version integer number (e.g., 14)
+ 'msvc_minor', # msvc minor version integer number (e.g., 1)
+ 'msvc_toolset_version', # msvc toolset version
+ 'version', # msvc version or msvc toolset version
+])
+
+# regex needs to accept same formats as toolset regexes in ./ScriptArguments.py
+
+re_extended_version = re.compile(r'''^
+ (?P<version>(?:
+ ([1-9][0-9]?[.][0-9]{1,2})| # XX.Y - XX.YY
+ ([1-9][0-9][.][0-9]{2}[.][0-9]{1,5})| # XX.YY.Z - XX.YY.ZZZZZ
+ ([1-9][0-9][.][0-9]{2}[.][0-9]{2}[.][0-9]{1,2}) # XX.YY.AA.B - XX.YY.AA.BB
+ ))
+ (?P<suffix>[A-Z]+)*
+$''', re.IGNORECASE | re.VERBOSE)
+
+def msvc_extended_version_components(version):
+ """
+ Decompose an msvc version or msvc toolset version into components.
+
+ Args:
+ version: str
+ version specification
+
+ Returns:
+ None or MSVCExtendedVersionComponents namedtuple:
+ """
+
+ m = re_extended_version.match(version)
+ if not m:
+ return None
+
+ msvc_toolset_version = m.group('version')
+
+ msvc_verstr = get_msvc_version_prefix(msvc_toolset_version)
+ if not msvc_verstr:
+ return None
+
+ msvc_suffix = m.group('suffix') if m.group('suffix') else ''
+ msvc_version = msvc_verstr + msvc_suffix
+
+ vs_def = Config.MSVC_VERSION_SUFFIX.get(msvc_version)
+ if not vs_def:
+ return None
+
+ msvc_vernum = float(msvc_verstr)
+
+ msvc_major, msvc_minor = [int(x) for x in msvc_verstr.split('.')]
+
+ msvc_extended_version_components_def = _MSVC_EXTENDED_VERSION_COMPONENTS_DEFINITION(
+ msvc_version = msvc_version,
+ msvc_verstr = msvc_verstr,
+ msvc_suffix = msvc_suffix,
+ msvc_vernum = msvc_vernum,
+ msvc_major = msvc_major,
+ msvc_minor = msvc_minor,
+ msvc_toolset_version = msvc_toolset_version,
+ version = version,
+ )
+
+ return msvc_extended_version_components_def
+
diff --git a/SCons/Tool/MSCommon/MSVC/WinSDK.py b/SCons/Tool/MSCommon/MSVC/WinSDK.py
index b17f850..f1fb961 100644
--- a/SCons/Tool/MSCommon/MSVC/WinSDK.py
+++ b/SCons/Tool/MSCommon/MSVC/WinSDK.py
@@ -225,7 +225,8 @@ def get_msvc_platform(is_uwp=False):
platform_def = _UWP if is_uwp else _DESKTOP
return platform_def
-def get_sdk_version_list(version_list, platform_def):
+def get_sdk_version_list(vs_def, platform_def):
+ version_list = vs_def.vc_sdk_versions if vs_def.vc_sdk_versions is not None else []
sdk_map = _sdk_map(version_list)
sdk_list = sdk_map.get(platform_def.vc_platform, [])
return sdk_list
@@ -243,7 +244,7 @@ def get_msvc_sdk_version_list(msvc_version, msvc_uwp_app=False):
is_uwp = True if msvc_uwp_app in Config.BOOLEAN_SYMBOLS[True] else False
platform_def = get_msvc_platform(is_uwp)
- sdk_list = get_sdk_version_list(vs_def.vc_sdk_versions, platform_def)
+ sdk_list = get_sdk_version_list(vs_def, platform_def)
sdk_versions.extend(sdk_list)
debug('sdk_versions=%s', repr(sdk_versions))
diff --git a/SCons/Tool/MSCommon/MSVC/__init__.py b/SCons/Tool/MSCommon/MSVC/__init__.py
index 04a6948..849c82d 100644
--- a/SCons/Tool/MSCommon/MSVC/__init__.py
+++ b/SCons/Tool/MSCommon/MSVC/__init__.py
@@ -36,9 +36,9 @@ Currently:
"""
from . import Exceptions # noqa: F401
-from . import Util # noqa: F401
from . import Config # noqa: F401
+from . import Util # noqa: F401
from . import Registry # noqa: F401
from . import SetupEnvDefault # noqa: F401
from . import Policy # noqa: F401
diff --git a/SCons/Tool/MSCommon/__init__.py b/SCons/Tool/MSCommon/__init__.py
index 0640bce..ff2e42a 100644
--- a/SCons/Tool/MSCommon/__init__.py
+++ b/SCons/Tool/MSCommon/__init__.py
@@ -71,6 +71,9 @@ from .vc import MSVCUnsupportedTargetArch # noqa: F401
from .vc import MSVCScriptNotFound # noqa: F401
from .vc import MSVCUseSettingsError # noqa: F401
+from .MSVC.Util import msvc_version_components # noqa: F401
+from .MSVC.Util import msvc_extended_version_components # noqa: F401
+
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
diff --git a/SCons/Tool/MSCommon/vc.py b/SCons/Tool/MSCommon/vc.py
index 7fed093..a254dc4 100644
--- a/SCons/Tool/MSCommon/vc.py
+++ b/SCons/Tool/MSCommon/vc.py
@@ -970,7 +970,8 @@ def reset_installed_vcs():
__INSTALLED_VCS_RUN = None
MSVC._reset()
-def get_default_installed_msvc(env=None):
+def msvc_get_default_version(env=None):
+ """Get default msvc version."""
vcs = get_installed_vcs(env)
msvc_version = vcs[0] if vcs else None
debug('msvc_version=%s', repr(msvc_version))
@@ -979,7 +980,7 @@ def get_default_installed_msvc(env=None):
def get_installed_vcs_components(env=None):
"""Test suite convenience function: return list of installed msvc version component tuples"""
vcs = get_installed_vcs(env)
- msvc_version_component_defs = [MSVC.Util.get_msvc_version_components(vcver) for vcver in vcs]
+ msvc_version_component_defs = [MSVC.Util.msvc_version_components(vcver) for vcver in vcs]
return msvc_version_component_defs
# Running these batch files isn't cheap: most of the time spent in
@@ -1088,7 +1089,7 @@ def get_default_version(env):
return msvs_version
if not msvc_version:
- msvc_version = get_default_installed_msvc(env)
+ msvc_version = msvc_get_default_version(env)
if not msvc_version:
#SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, msg)
debug('No installed VCs')
@@ -1340,19 +1341,24 @@ def msvc_setup_env_tool(env=None, version=None, tool=None):
rval = True
return rval
-def msvc_sdk_versions(msvc_version=None, msvc_uwp_app=False):
- debug('msvc_version=%s, msvc_uwp_app=%s', repr(msvc_version), repr(msvc_uwp_app))
+def msvc_sdk_versions(version=None, msvc_uwp_app=False):
+ debug('version=%s, msvc_uwp_app=%s', repr(version), repr(msvc_uwp_app))
rval = []
- if not msvc_version:
- msvc_version = get_default_installed_msvc()
+ if not version:
+ version = msvc_get_default_version()
- if not msvc_version:
+ if not version:
debug('no msvc versions detected')
return rval
- rval = MSVC.WinSDK.get_msvc_sdk_version_list(msvc_version, msvc_uwp_app)
+ version_def = MSVC.Util.msvc_extended_version_components(version)
+ if not version_def:
+ msg = 'Unsupported version {}'.format(repr(version))
+ raise MSVCArgumentError(msg)
+
+ rval = MSVC.WinSDK.get_msvc_sdk_version_list(version, msvc_uwp_app)
return rval
def msvc_toolset_versions(msvc_version=None, full=True, sxs=False):
@@ -1362,7 +1368,7 @@ def msvc_toolset_versions(msvc_version=None, full=True, sxs=False):
rval = []
if not msvc_version:
- msvc_version = get_default_installed_msvc()
+ msvc_version = msvc_get_default_version()
if not msvc_version:
debug('no msvc versions detected')
@@ -1438,36 +1444,33 @@ def msvc_query_version_toolset(version=None, prefer_newest=True):
)
return msvc_version, msvc_toolset_version
- version_elements_def = MSVC.Util.get_version_elements(version)
- if not version_elements_def:
- msg = 'Unsupported version format {}'.format(repr(version))
- raise MSVCArgumentError(msg)
+ version_def = MSVC.Util.msvc_extended_version_components(version)
- if version_elements_def.msvc_version not in _VCVER:
+ if not version_def:
msg = 'Unsupported msvc version {}'.format(repr(version))
raise MSVCArgumentError(msg)
- if version_elements_def.vc_version_suffix:
- if version_elements_def.vc_version_numstr != version_elements_def.vc_toolset_numstr:
+ if version_def.msvc_suffix:
+ if version_def.msvc_verstr != version_def.msvc_toolset_version:
# toolset version with component suffix
msg = 'Unsupported toolset version {}'.format(repr(version))
raise MSVCArgumentError(msg)
- if float(version_elements_def.vc_version_numstr) > 14.0:
+ if version_def.msvc_vernum > 14.0:
# VS2017 and later
force_toolset_msvc_version = False
else:
# VS2015 and earlier
force_toolset_msvc_version = True
- extended_version = version_elements_def.vc_version_numstr + '0.00000'
- if not extended_version.startswith(version_elements_def.vc_toolset_numstr):
+ extended_version = version_def.msvc_verstr + '0.00000'
+ if not extended_version.startswith(version_def.msvc_toolset_version):
# toolset not equivalent to msvc version
msg = 'Unsupported toolset version {} (expected {})'.format(
repr(version), repr(extended_version)
)
raise MSVCArgumentError(msg)
- msvc_version = version_elements_def.msvc_version
+ msvc_version = version_def.msvc_version
if msvc_version not in MSVC.Config.MSVC_VERSION_TOOLSET_SEARCH_MAP:
# VS2013 and earlier
@@ -1478,9 +1481,9 @@ def msvc_query_version_toolset(version=None, prefer_newest=True):
return msvc_version, msvc_toolset_version
if force_toolset_msvc_version:
- query_msvc_toolset_version = version_elements_def.vc_version_numstr
+ query_msvc_toolset_version = version_def.msvc_verstr
else:
- query_msvc_toolset_version = version_elements_def.vc_toolset_numstr
+ query_msvc_toolset_version = version_def.msvc_toolset_version
if prefer_newest:
query_version_list = MSVC.Config.MSVC_VERSION_TOOLSET_SEARCH_MAP[msvc_version]
@@ -1528,7 +1531,7 @@ def msvc_query_version_toolset(version=None, prefer_newest=True):
repr(msvc_version), repr(msvc_toolset_version)
)
- if version_elements_def.vc_version_numstr == msvc_toolset_version:
+ if version_def.msvc_verstr == msvc_toolset_version:
msg = 'MSVC version {} was not found'.format(repr(version))
MSVC.Policy.msvc_notfound_handler(None, msg)
return msvc_version, msvc_toolset_version
diff --git a/test/MSVC/MSVC_SDK_VERSION.py b/test/MSVC/MSVC_SDK_VERSION.py
index 2ebd046..627c867 100644
--- a/test/MSVC/MSVC_SDK_VERSION.py
+++ b/test/MSVC/MSVC_SDK_VERSION.py
@@ -44,8 +44,8 @@ default_version = installed_versions[0]
GE_VS2015_versions = [v for v in installed_versions if v.msvc_vernum >= 14.0]
LT_VS2015_versions = [v for v in installed_versions if v.msvc_vernum < 14.0]
-default_sdk_versions_uwp = msvc_sdk_versions(msvc_version=None, msvc_uwp_app=True)
-default_sdk_versions_def = msvc_sdk_versions(msvc_version=None, msvc_uwp_app=False)
+default_sdk_versions_uwp = msvc_sdk_versions(version=None, msvc_uwp_app=True)
+default_sdk_versions_def = msvc_sdk_versions(version=None, msvc_uwp_app=False)
have_140 = any([v.msvc_verstr == '14.0' for v in GE_VS2015_versions])
@@ -72,8 +72,8 @@ if GE_VS2015_versions:
for supported in GE_VS2015_versions:
- sdk_versions_uwp = msvc_sdk_versions(msvc_version=supported.msvc_version, msvc_uwp_app=True)
- sdk_versions_def = msvc_sdk_versions(msvc_version=supported.msvc_version, msvc_uwp_app=False)
+ sdk_versions_uwp = msvc_sdk_versions(version=supported.msvc_version, msvc_uwp_app=True)
+ sdk_versions_def = msvc_sdk_versions(version=supported.msvc_version, msvc_uwp_app=False)
# find sdk version for each major SDK
sdk_versions = version_major_list(sdk_versions_def)
diff --git a/test/MSVC/MSVC_TOOLSET_VERSION.py b/test/MSVC/MSVC_TOOLSET_VERSION.py
index ce6e251..aa4213f 100644
--- a/test/MSVC/MSVC_TOOLSET_VERSION.py
+++ b/test/MSVC/MSVC_TOOLSET_VERSION.py
@@ -34,6 +34,7 @@ test.skip_if_not_msvc()
import textwrap
from SCons.Tool.MSCommon.vc import get_installed_vcs_components
+from SCons.Tool.MSCommon import msvc_toolset_versions
installed_versions = get_installed_vcs_components()
@@ -48,6 +49,30 @@ if GE_VS2017_versions:
for supported in GE_VS2017_versions:
+ toolset_full_versions = msvc_toolset_versions(supported.msvc_version, full=True, sxs=False)
+ toolset_full_version = toolset_full_versions[0] if toolset_full_versions else None
+
+ toolset_sxs_versions = msvc_toolset_versions(supported.msvc_version, full=False, sxs=True)
+ toolset_sxs_version = toolset_sxs_versions[0] if toolset_sxs_versions else None
+
+ if toolset_full_version:
+ test.write('SConstruct', textwrap.dedent(
+ """
+ DefaultEnvironment(tools=[])
+ env = Environment(MSVC_VERSION={}, MSVC_TOOLSET_VERSION={}, tools=['msvc'])
+ """.format(repr(supported.msvc_version), repr(toolset_full_version))
+ ))
+ test.run(arguments='-Q -s', stdout='')
+
+ if toolset_sxs_version:
+ test.write('SConstruct', textwrap.dedent(
+ """
+ DefaultEnvironment(tools=[])
+ env = Environment(MSVC_VERSION={}, MSVC_TOOLSET_VERSION={}, tools=['msvc'])
+ """.format(repr(supported.msvc_version), repr(toolset_sxs_version))
+ ))
+ test.run(arguments='-Q -s', stdout='')
+
# msvc_version as toolset version
test.write('SConstruct', textwrap.dedent(
"""
diff --git a/test/MSVC/msvc_cache_force_defaults.py b/test/MSVC/msvc_cache_force_defaults.py
new file mode 100644
index 0000000..a964405
--- /dev/null
+++ b/test/MSVC/msvc_cache_force_defaults.py
@@ -0,0 +1,81 @@
+# MIT License
+#
+# Copyright The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+"""
+Test SCONS_CACHE_MSVC_FORCE_DEFAULTS system environment variable.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.skip_if_not_msvc()
+
+import textwrap
+
+from SCons.Tool.MSCommon.vc import get_installed_vcs_components
+
+installed_versions = get_installed_vcs_components()
+
+default_version = installed_versions[0]
+
+if default_version.msvc_vernum >= 14.0:
+ # VS2015 and later
+
+ # force SDK version and toolset version as msvc batch file arguments
+ test.write('SConstruct', textwrap.dedent(
+ """
+ import os
+ import json
+
+ cache_file = 'MSCACHE.json'
+
+ os.environ['SCONS_CACHE_MSVC_CONFIG']=cache_file
+ os.environ['SCONS_CACHE_MSVC_FORCE_DEFAULTS']='1'
+
+ DefaultEnvironment(tools=[])
+ env = Environment(tools=['msvc'])
+
+ envcache_keys = []
+ with open(cache_file, 'r') as file:
+ envcache_list = json.load(file)
+ envcache_keys = [tuple(d['key']) for d in envcache_list]
+
+ if envcache_keys:
+ # key = (script, arguments)
+ print("SCRIPT_ARGS: {}".format(envcache_keys[0][-1]))
+ """
+ ))
+ test.run(arguments = "-Q -s", status=0, stdout=None)
+
+ cache_arg = test.stdout().strip()
+
+ if default_version.msvc_verstr == '14.0':
+ # VS2015: target_arch msvc_sdk_version
+ expect = r'^SCRIPT_ARGS: .* [0-9.]+$'
+ else:
+ # VS2017+ msvc_sdk_version msvc_toolset_version
+ expect = r'^SCRIPT_ARGS: [0-9.]+ -vcvars_ver=[0-9.]+$'
+
+ test.must_contain_all(cache_arg, expect, find=TestSCons.match_re)
+
diff --git a/test/MSVC/msvc_sdk_versions.py b/test/MSVC/msvc_sdk_versions.py
new file mode 100644
index 0000000..a99c1fe
--- /dev/null
+++ b/test/MSVC/msvc_sdk_versions.py
@@ -0,0 +1,90 @@
+# MIT License
+#
+# Copyright The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+"""
+Test the msvc_sdk_versions method.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.skip_if_not_msvc()
+
+import unittest
+
+from SCons.Tool.MSCommon.vc import _VCVER
+from SCons.Tool.MSCommon.vc import msvc_get_default_version
+from SCons.Tool.MSCommon import msvc_version_components
+from SCons.Tool.MSCommon import msvc_extended_version_components
+from SCons.Tool.MSCommon import msvc_sdk_versions
+from SCons.Tool.MSCommon import msvc_toolset_versions
+from SCons.Tool.MSCommon import MSVCArgumentError
+
+class MsvcSdkVersionsTests(unittest.TestCase):
+
+ def test_valid_default_msvc(self):
+ symbol = msvc_get_default_version()
+ version_def = msvc_version_components(symbol)
+ for msvc_uwp_app in (True, False):
+ sdk_list = msvc_sdk_versions(version=None, msvc_uwp_app=msvc_uwp_app)
+ if version_def.msvc_vernum >= 14.0:
+ self.assertTrue(sdk_list, "SDK list is empty for msvc version {}".format(repr(symbol)))
+ else:
+ self.assertFalse(sdk_list, "SDK list is not empty for msvc version {}".format(repr(symbol)))
+
+ def test_valid_vcver(self):
+ for symbol in _VCVER:
+ version_def = msvc_version_components(symbol)
+ for msvc_uwp_app in (True, False):
+ sdk_list = msvc_sdk_versions(version=symbol, msvc_uwp_app=msvc_uwp_app)
+ if version_def.msvc_vernum >= 14.0:
+ self.assertTrue(sdk_list, "SDK list is empty for msvc version {}".format(repr(symbol)))
+ else:
+ self.assertFalse(sdk_list, "SDK list is not empty for msvc version {}".format(repr(symbol)))
+
+ def test_valid_vcver_toolsets(self):
+ for symbol in _VCVER:
+ toolset_list = msvc_toolset_versions(msvc_version=symbol, full=True, sxs=True)
+ if toolset_list is None:
+ continue
+ for toolset in toolset_list:
+ extended_def = msvc_extended_version_components(toolset)
+ for msvc_uwp_app in (True, False):
+ sdk_list = msvc_sdk_versions(version=extended_def.msvc_toolset_version, msvc_uwp_app=msvc_uwp_app)
+ self.assertTrue(sdk_list, "SDK list is empty for msvc toolset version {}".format(repr(toolset)))
+
+ def test_invalid_vcver(self):
+ for symbol in ['6.0Exp', '14.3Exp', '99', '14.1Bug']:
+ for msvc_uwp_app in (True, False):
+ with self.assertRaises(MSVCArgumentError):
+ sdk_list = msvc_sdk_versions(version=symbol, msvc_uwp_app=msvc_uwp_app)
+
+ def test_invalid_vcver_toolsets(self):
+ for symbol in ['14.31.123456', '14.31.1.1']:
+ for msvc_uwp_app in (True, False):
+ with self.assertRaises(MSVCArgumentError):
+ sdk_list = msvc_sdk_versions(version=symbol, msvc_uwp_app=msvc_uwp_app)
+
+unittest.main()
+
diff --git a/test/MSVC/msvc_version_components.py b/test/MSVC/msvc_version_components.py
new file mode 100644
index 0000000..d55de88
--- /dev/null
+++ b/test/MSVC/msvc_version_components.py
@@ -0,0 +1,61 @@
+# MIT License
+#
+# Copyright The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+"""
+Test msvc_version_components and msvc_extended_version_components functions.
+"""
+
+import unittest
+
+from SCons.Tool.MSCommon.vc import _VCVER
+from SCons.Tool.MSCommon import msvc_version_components
+from SCons.Tool.MSCommon import msvc_extended_version_components
+
+class MsvcVersionComponentsTests(unittest.TestCase):
+
+ def test_valid_msvc_versions(self):
+ for symbol in _VCVER:
+ version_def = msvc_version_components(symbol)
+ self.assertNotEqual(version_def, None, "Components tuple is None for {}".format(symbol))
+
+ def test_invalid_msvc_versions(self):
+ for symbol in ['14', '14Bug', '14.31', '14.31Bug']:
+ version_def = msvc_version_components(symbol)
+ self.assertEqual(version_def, None, "Components tuple is not None for {}".format(symbol))
+
+ def test_valid_msvc_extended_versions(self):
+ for symbol in _VCVER:
+ extended_def = msvc_extended_version_components(symbol)
+ self.assertNotEqual(extended_def, None, "Components tuple is None for {}".format(symbol))
+ for symbol in ['14.31', '14.31.1', '14.31.12', '14.31.123', '14.31.1234', '14.31.12345', '14.31.17.2']:
+ extended_def = msvc_extended_version_components(symbol)
+ self.assertNotEqual(extended_def, None, "Components tuple is None for {}".format(symbol))
+
+ def test_invalid_extended_msvc_versions(self):
+ for symbol in ['14', '14.3Bug', '14.31Bug', '14.31.123456', '14.3.17', '14.3.1.1']:
+ extended_def = msvc_extended_version_components(symbol)
+ self.assertEqual(extended_def, None, "Components tuple is not None for {}".format(symbol))
+
+if __name__ == "__main__":
+ unittest.main()
+
diff --git a/test/MSVC/no_msvc.py b/test/MSVC/no_msvc.py
index 4ab7dd8..1a522c6 100644
--- a/test/MSVC/no_msvc.py
+++ b/test/MSVC/no_msvc.py
@@ -67,5 +67,15 @@ def exists(env):
test.file_fixture('no_msvc/no_msvcs_sconstruct_tools.py', 'SConstruct')
test.run(arguments='-Q -s')
+# test no msvc's and msvc_sdk_version() call
+test.file_fixture('no_msvc/no_msvcs_sconstruct_msvc_sdk_versions.py', 'SConstruct')
+test.run(arguments='-Q -s')
+test.must_contain_all(test.stdout(), 'sdk_version_list=[]')
+
+# test no msvc's and msvc_sdk_version() call
+test.file_fixture('no_msvc/no_msvcs_sconstruct_msvc_toolset_versions.py', 'SConstruct')
+test.run(arguments='-Q -s')
+test.must_contain_all(test.stdout(), 'toolset_version_list=[]')
+
test.pass_test()
diff --git a/test/fixture/no_msvc/no_msvcs_sconstruct_msvc_sdk_versions.py b/test/fixture/no_msvc/no_msvcs_sconstruct_msvc_sdk_versions.py
new file mode 100644
index 0000000..62e77ab
--- /dev/null
+++ b/test/fixture/no_msvc/no_msvcs_sconstruct_msvc_sdk_versions.py
@@ -0,0 +1,15 @@
+import SCons
+import SCons.Tool.MSCommon
+
+def DummyVsWhere(msvc_version, env):
+ # not testing versions with vswhere, so return none
+ return None
+
+for key in SCons.Tool.MSCommon.vc._VCVER_TO_PRODUCT_DIR:
+ SCons.Tool.MSCommon.vc._VCVER_TO_PRODUCT_DIR[key]=[(SCons.Util.HKEY_LOCAL_MACHINE, r'')]
+
+SCons.Tool.MSCommon.vc.find_vc_pdir_vswhere = DummyVsWhere
+
+sdk_version_list = SCons.Tool.MSCommon.msvc_sdk_versions()
+
+print('sdk_version_list='+repr(sdk_version_list)) \ No newline at end of file
diff --git a/test/fixture/no_msvc/no_msvcs_sconstruct_msvc_toolset_versions.py b/test/fixture/no_msvc/no_msvcs_sconstruct_msvc_toolset_versions.py
new file mode 100644
index 0000000..3aec559
--- /dev/null
+++ b/test/fixture/no_msvc/no_msvcs_sconstruct_msvc_toolset_versions.py
@@ -0,0 +1,15 @@
+import SCons
+import SCons.Tool.MSCommon
+
+def DummyVsWhere(msvc_version, env):
+ # not testing versions with vswhere, so return none
+ return None
+
+for key in SCons.Tool.MSCommon.vc._VCVER_TO_PRODUCT_DIR:
+ SCons.Tool.MSCommon.vc._VCVER_TO_PRODUCT_DIR[key]=[(SCons.Util.HKEY_LOCAL_MACHINE, r'')]
+
+SCons.Tool.MSCommon.vc.find_vc_pdir_vswhere = DummyVsWhere
+
+toolset_version_list = SCons.Tool.MSCommon.msvc_toolset_versions()
+
+print('toolset_version_list='+repr(toolset_version_list)) \ No newline at end of file