diff options
author | Joseph Brill <48932340+jcbrill@users.noreply.github.com> | 2022-07-09 18:49:53 (GMT) |
---|---|---|
committer | Joseph Brill <48932340+jcbrill@users.noreply.github.com> | 2022-07-09 18:49:53 (GMT) |
commit | 04a5dea1a00abd7ffdc4c274f000273ce6ff37db (patch) | |
tree | de73f1079176391dae6b9084d19effa9b7657dd8 | |
parent | 23f63fc766f9e157bfe8642b8559983dde684dd3 (diff) | |
download | SCons-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.py | 35 | ||||
-rw-r--r-- | SCons/Tool/MSCommon/MSVC/ScriptArguments.py | 6 | ||||
-rw-r--r-- | SCons/Tool/MSCommon/MSVC/Util.py | 126 | ||||
-rw-r--r-- | SCons/Tool/MSCommon/MSVC/WinSDK.py | 5 | ||||
-rw-r--r-- | SCons/Tool/MSCommon/MSVC/__init__.py | 2 | ||||
-rw-r--r-- | SCons/Tool/MSCommon/__init__.py | 3 | ||||
-rw-r--r-- | SCons/Tool/MSCommon/vc.py | 51 | ||||
-rw-r--r-- | test/MSVC/MSVC_SDK_VERSION.py | 8 | ||||
-rw-r--r-- | test/MSVC/MSVC_TOOLSET_VERSION.py | 25 | ||||
-rw-r--r-- | test/MSVC/msvc_cache_force_defaults.py | 81 | ||||
-rw-r--r-- | test/MSVC/msvc_sdk_versions.py | 90 | ||||
-rw-r--r-- | test/MSVC/msvc_version_components.py | 61 | ||||
-rw-r--r-- | test/MSVC/no_msvc.py | 10 | ||||
-rw-r--r-- | test/fixture/no_msvc/no_msvcs_sconstruct_msvc_sdk_versions.py | 15 | ||||
-rw-r--r-- | test/fixture/no_msvc/no_msvcs_sconstruct_msvc_toolset_versions.py | 15 |
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 |