summaryrefslogtreecommitdiffstats
path: root/SCons/Tool/MSCommon/MSVC/ScriptArguments.py
diff options
context:
space:
mode:
Diffstat (limited to 'SCons/Tool/MSCommon/MSVC/ScriptArguments.py')
-rw-r--r--SCons/Tool/MSCommon/MSVC/ScriptArguments.py733
1 files changed, 733 insertions, 0 deletions
diff --git a/SCons/Tool/MSCommon/MSVC/ScriptArguments.py b/SCons/Tool/MSCommon/MSVC/ScriptArguments.py
new file mode 100644
index 0000000..324f8be
--- /dev/null
+++ b/SCons/Tool/MSCommon/MSVC/ScriptArguments.py
@@ -0,0 +1,733 @@
+# 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.
+
+"""
+Batch file argument functions for Microsoft Visual C/C++.
+"""
+
+import os
+import re
+import enum
+
+from collections import (
+ namedtuple,
+)
+
+from ..common import (
+ debug,
+)
+
+from . import Dispatcher
+from . import Util
+from . import Config
+from . import WinSDK
+
+from .Exceptions import (
+ MSVCInternalError,
+ MSVCArgumentError,
+)
+
+Dispatcher.register_modulename(__name__)
+
+# TODO: verify SDK 10 version folder names 10.0.XXXXX.0 {1,3} last?
+re_sdk_version_100 = re.compile(r'^10[.][0-9][.][0-9]{5}[.][0-9]{1}$')
+re_sdk_version_81 = re.compile(r'^8[.]1$')
+
+re_sdk_dispatch_map = {
+ '10.0': re_sdk_version_100,
+ '8.1': re_sdk_version_81,
+}
+
+def _verify_re_sdk_dispatch_map():
+ debug('')
+ for sdk_version in Config.MSVC_SDK_VERSIONS:
+ if sdk_version in re_sdk_dispatch_map:
+ continue
+ err_msg = 'sdk version {} not in re_sdk_dispatch_map'.format(sdk_version)
+ raise MSVCInternalError(err_msg)
+ return None
+
+# capture msvc version
+re_toolset_version = re.compile(r'^(?P<version>[1-9][0-9]?[.][0-9])[0-9.]*$', re.IGNORECASE)
+
+re_toolset_full = re.compile(r'''^(?:
+ (?:[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
+)$''', re.VERBOSE)
+
+re_toolset_140 = re.compile(r'''^(?:
+ (?:14[.]0{1,2})| # 14.0 - 14.00
+ (?:14[.]0{2}[.]0{1,5}) # 14.00.0 - 14.00.00000
+)$''', re.VERBOSE)
+
+# valid SxS formats will be matched with re_toolset_full: match 3 '.' format
+re_toolset_sxs = re.compile(r'^[1-9][0-9][.][0-9]{2}[.][0-9]{2}[.][0-9]{1,2}$')
+
+# MSVC_SCRIPT_ARGS
+re_vcvars_uwp = re.compile(r'(?:(?<!\S)|^)(?P<uwp>(?:uwp|store))(?:(?!\S)|$)',re.IGNORECASE)
+re_vcvars_sdk = re.compile(r'(?:(?<!\S)|^)(?P<sdk>(?:[1-9][0-9]*[.]\S*))(?:(?!\S)|$)',re.IGNORECASE)
+re_vcvars_toolset = re.compile(r'(?:(?<!\S)|^)(?P<toolset_arg>(?:[-]{1,2}|[/])vcvars_ver[=](?P<toolset>\S*))(?:(?!\S)|$)', re.IGNORECASE)
+re_vcvars_spectre = re.compile(r'(?:(?<!\S)|^)(?P<spectre_arg>(?:[-]{1,2}|[/])vcvars_spectre_libs[=](?P<spectre>\S*))(?:(?!\S)|$)',re.IGNORECASE)
+
+# Force default sdk argument
+MSVC_FORCE_DEFAULT_SDK = False
+
+# Force default toolset argument
+MSVC_FORCE_DEFAULT_TOOLSET = False
+
+# MSVC batch file arguments:
+#
+# VS2022: UWP, SDK, TOOLSET, SPECTRE
+# VS2019: UWP, SDK, TOOLSET, SPECTRE
+# VS2017: UWP, SDK, TOOLSET, SPECTRE
+# VS2015: UWP, SDK
+#
+# MSVC_SCRIPT_ARGS: VS2015+
+#
+# MSVC_UWP_APP: VS2015+
+# MSVC_SDK_VERSION: VS2015+
+# MSVC_TOOLSET_VERSION: VS2017+
+# MSVC_SPECTRE_LIBS: VS2017+
+
+@enum.unique
+class SortOrder(enum.IntEnum):
+ ARCH = 0 # arch
+ UWP = 1 # MSVC_UWP_APP
+ SDK = 2 # MSVC_SDK_VERSION
+ TOOLSET = 3 # MSVC_TOOLSET_VERSION
+ SPECTRE = 4 # MSVC_SPECTRE_LIBS
+ USER = 5 # MSVC_SCRIPT_ARGS
+
+VS2019 = Config.MSVS_VERSION_INTERNAL['2019']
+VS2017 = Config.MSVS_VERSION_INTERNAL['2017']
+VS2015 = Config.MSVS_VERSION_INTERNAL['2015']
+
+MSVC_VERSION_ARGS_DEFINITION = namedtuple('MSVCVersionArgsDefinition', [
+ 'version', # fully qualified msvc version (e.g., '14.1Exp')
+ 'vs_def',
+])
+
+def _msvc_version(version):
+
+ verstr = Util.get_version_prefix(version)
+ vs_def = Config.MSVC_VERSION_INTERNAL[verstr]
+
+ version_args = MSVC_VERSION_ARGS_DEFINITION(
+ version = version,
+ vs_def = vs_def,
+ )
+
+ return version_args
+
+def _msvc_script_argument_uwp(env, msvc, arglist):
+
+ uwp_app = env['MSVC_UWP_APP']
+ debug('MSVC_VERSION=%s, MSVC_UWP_APP=%s', repr(msvc.version), repr(uwp_app))
+
+ if not uwp_app:
+ return None
+
+ if uwp_app not in Config.BOOLEAN_SYMBOLS[True]:
+ return None
+
+ if msvc.vs_def.vc_buildtools_def.vc_version_numeric < VS2015.vc_buildtools_def.vc_version_numeric:
+ debug(
+ 'invalid: msvc version constraint: %s < %s VS2015',
+ repr(msvc.vs_def.vc_buildtools_def.vc_version_numeric),
+ repr(VS2015.vc_buildtools_def.vc_version_numeric)
+ )
+ err_msg = "MSVC_UWP_APP ({}) constraint violation: MSVC_VERSION {} < {} VS2015".format(
+ repr(uwp_app), repr(msvc.version), repr(VS2015.vc_buildtools_def.vc_version)
+ )
+ raise MSVCArgumentError(err_msg)
+
+ # VS2017+ rewrites uwp => store for 14.0 toolset
+ uwp_arg = msvc.vs_def.vc_uwp
+
+ # store/uwp may not be fully installed
+ argpair = (SortOrder.UWP, uwp_arg)
+ arglist.append(argpair)
+
+ return uwp_arg
+
+def _user_script_argument_uwp(env, uwp, user_argstr):
+
+ matches = [m for m in re_vcvars_uwp.finditer(user_argstr)]
+ if not matches:
+ return None
+
+ if len(matches) > 1:
+ debug('multiple uwp declarations: MSVC_SCRIPT_ARGS=%s', repr(user_argstr))
+ err_msg = "multiple uwp declarations: MSVC_SCRIPT_ARGS={}".format(repr(user_argstr))
+ raise MSVCArgumentError(err_msg)
+
+ if not uwp:
+ return None
+
+ env_argstr = env.get('MSVC_UWP_APP','')
+ debug('multiple uwp declarations: MSVC_UWP_APP=%s, MSVC_SCRIPT_ARGS=%s', repr(env_argstr), repr(user_argstr))
+
+ err_msg = "multiple uwp declarations: MSVC_UWP_APP={} and MSVC_SCRIPT_ARGS={}".format(
+ repr(env_argstr), repr(user_argstr)
+ )
+
+ raise MSVCArgumentError(err_msg)
+
+def _msvc_script_argument_sdk_constraints(msvc, sdk_version):
+
+ if msvc.vs_def.vc_buildtools_def.vc_version_numeric < VS2015.vc_buildtools_def.vc_version_numeric:
+ debug(
+ 'invalid: msvc_version constraint: %s < %s VS2015',
+ repr(msvc.vs_def.vc_buildtools_def.vc_version_numeric),
+ repr(VS2015.vc_buildtools_def.vc_version_numeric)
+ )
+ err_msg = "MSVC_SDK_VERSION ({}) constraint violation: MSVC_VERSION {} < {} VS2015".format(
+ repr(sdk_version), repr(msvc.version), repr(VS2015.vc_buildtools_def.vc_version)
+ )
+ return err_msg
+
+ for msvc_sdk_version in msvc.vs_def.vc_sdk_versions:
+ re_sdk_version = re_sdk_dispatch_map[msvc_sdk_version]
+ if re_sdk_version.match(sdk_version):
+ debug('valid: sdk_version=%s', repr(sdk_version))
+ return None
+
+ debug('invalid: method exit: sdk_version=%s', repr(sdk_version))
+ err_msg = "MSVC_SDK_VERSION ({}) is not supported".format(repr(sdk_version))
+ return err_msg
+
+def _msvc_script_argument_sdk(env, msvc, platform_type, arglist):
+
+ sdk_version = env['MSVC_SDK_VERSION']
+ debug(
+ 'MSVC_VERSION=%s, MSVC_SDK_VERSION=%s, platform_type=%s',
+ repr(msvc.version), repr(sdk_version), repr(platform_type)
+ )
+
+ if not sdk_version:
+ return None
+
+ err_msg = _msvc_script_argument_sdk_constraints(msvc, sdk_version)
+ if err_msg:
+ raise MSVCArgumentError(err_msg)
+
+ sdk_list = WinSDK.get_sdk_version_list(msvc.vs_def.vc_sdk_versions, platform_type)
+
+ if sdk_version not in sdk_list:
+ err_msg = "MSVC_SDK_VERSION {} not found for platform type {}".format(
+ repr(sdk_version), repr(platform_type)
+ )
+ raise MSVCArgumentError(err_msg)
+
+ argpair = (SortOrder.SDK, sdk_version)
+ arglist.append(argpair)
+
+ return sdk_version
+
+def _msvc_script_default_sdk(env, msvc, platform_type, 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_type)
+ if not len(sdk_list):
+ return None
+
+ sdk_default = sdk_list[0]
+
+ debug(
+ 'MSVC_VERSION=%s, sdk_default=%s, platform_type=%s',
+ repr(msvc.version), repr(sdk_default), repr(platform_type)
+ )
+
+ argpair = (SortOrder.SDK, sdk_default)
+ arglist.append(argpair)
+
+ return sdk_default
+
+def _user_script_argument_sdk(env, sdk_version, user_argstr):
+
+ matches = [m for m in re_vcvars_sdk.finditer(user_argstr)]
+ if not matches:
+ return None
+
+ if len(matches) > 1:
+ debug('multiple sdk version declarations: MSVC_SCRIPT_ARGS=%s', repr(user_argstr))
+ err_msg = "multiple sdk version declarations: MSVC_SCRIPT_ARGS={}".format(repr(user_argstr))
+ raise MSVCArgumentError(err_msg)
+
+ if not sdk_version:
+ user_sdk = matches[0].group('sdk')
+ return user_sdk
+
+ env_argstr = env.get('MSVC_SDK_VERSION','')
+ debug('multiple sdk version declarations: MSVC_SDK_VERSION=%s, MSVC_SCRIPT_ARGS=%s', repr(env_argstr), repr(user_argstr))
+
+ err_msg = "multiple sdk version declarations: MSVC_SDK_VERSION={} and MSVC_SCRIPT_ARGS={}".format(
+ repr(env_argstr), repr(user_argstr)
+ )
+
+ raise MSVCArgumentError(err_msg)
+
+def _msvc_read_toolset_file(msvc, filename):
+ toolset_version = None
+ try:
+ with open(filename) as f:
+ toolset_version = f.readlines()[0].strip()
+ debug(
+ 'msvc_version=%s, filename=%s, toolset_version=%s',
+ repr(msvc.version), repr(filename), repr(toolset_version)
+ )
+ except OSError:
+ debug('OSError: msvc_version=%s, filename=%s', repr(msvc.version), repr(filename))
+ except IndexError:
+ debug('IndexError: msvc_version=%s, filename=%s', repr(msvc.version), repr(filename))
+ return toolset_version
+
+def _msvc_read_toolset_folders(msvc, vc_dir):
+
+ toolsets_sxs = {}
+ toolsets_full = []
+
+ build_dir = os.path.join(vc_dir, "Auxiliary", "Build")
+ sxs_toolsets = [f.name for f in os.scandir(build_dir) if f.is_dir()]
+ for sxs_toolset in sxs_toolsets:
+ filename = 'Microsoft.VCToolsVersion.{}.txt'.format(sxs_toolset)
+ filepath = os.path.join(build_dir, sxs_toolset, filename)
+ debug('sxs toolset: check file=%s', repr(filepath))
+ if os.path.exists(filepath):
+ toolset_version = _msvc_read_toolset_file(msvc, filepath)
+ if not toolset_version:
+ continue
+ toolsets_sxs[sxs_toolset] = toolset_version
+ debug(
+ 'sxs toolset: msvc_version=%s, sxs_version=%s, toolset_version=%s',
+ repr(msvc.version), repr(sxs_toolset), toolset_version
+ )
+
+ toolset_dir = os.path.join(vc_dir, "Tools", "MSVC")
+ toolsets = [f.name for f in os.scandir(toolset_dir) if f.is_dir()]
+ for toolset_version in toolsets:
+ binpath = os.path.join(toolset_dir, toolset_version, "bin")
+ debug('toolset: check binpath=%s', repr(binpath))
+ if os.path.exists(binpath):
+ toolsets_full.append(toolset_version)
+ debug(
+ 'toolset: msvc_version=%s, toolset_version=%s',
+ repr(msvc.version), repr(toolset_version)
+ )
+
+ toolsets_full.sort(reverse=True)
+ debug('msvc_version=%s, toolsets=%s', repr(msvc.version), repr(toolsets_full))
+
+ return toolsets_sxs, toolsets_full
+
+def _msvc_read_toolset_default(msvc, vc_dir):
+
+ build_dir = os.path.join(vc_dir, "Auxiliary", "Build")
+
+ # VS2019+
+ filename = "Microsoft.VCToolsVersion.{}.default.txt".format(msvc.vs_def.vc_buildtools_def.vc_buildtools)
+ filepath = os.path.join(build_dir, filename)
+
+ debug('default toolset: check file=%s', repr(filepath))
+ if os.path.exists(filepath):
+ toolset_buildtools = _msvc_read_toolset_file(msvc, filepath)
+ if toolset_buildtools:
+ return toolset_buildtools
+
+ # VS2017+
+ filename = "Microsoft.VCToolsVersion.default.txt"
+ filepath = os.path.join(build_dir, filename)
+
+ debug('default toolset: check file=%s', repr(filepath))
+ if os.path.exists(filepath):
+ toolset_default = _msvc_read_toolset_file(msvc, filepath)
+ if toolset_default:
+ return toolset_default
+
+ return None
+
+_toolset_version_cache = {}
+_toolset_default_cache = {}
+
+def _reset_toolset_cache():
+ debug('reset: toolset cache')
+ _toolset_version_cache = {}
+ _toolset_default_cache = {}
+
+def _msvc_version_toolsets(msvc, vc_dir):
+
+ if msvc.version in _toolset_version_cache:
+ toolsets_sxs, toolsets_full = _toolset_version_cache[msvc.version]
+ else:
+ toolsets_sxs, toolsets_full = _msvc_read_toolset_folders(msvc, vc_dir)
+ _toolset_version_cache[msvc.version] = toolsets_sxs, toolsets_full
+
+ return toolsets_sxs, toolsets_full
+
+def _msvc_default_toolset(msvc, vc_dir):
+
+ if msvc.version in _toolset_default_cache:
+ toolset_default = _toolset_default_cache[msvc.version]
+ else:
+ toolset_default = _msvc_read_toolset_default(msvc, vc_dir)
+ _toolset_default_cache[msvc.version] = toolset_default
+
+ return toolset_default
+
+def _msvc_version_toolset_vcvars(msvc, vc_dir, toolset_version):
+
+ if toolset_version == '14.0':
+ return toolset_version
+
+ toolsets_sxs, toolsets_full = _msvc_version_toolsets(msvc, vc_dir)
+
+ if msvc.vs_def.vc_buildtools_def.vc_version_numeric == VS2019.vc_buildtools_def.vc_version_numeric:
+ # necessary to detect toolset not found
+ if toolset_version == '14.28.16.8':
+ new_toolset_version = '14.28'
+ # VS2019\Common7\Tools\vsdevcmd\ext\vcvars.bat AzDO Bug#1293526
+ # special handling of the 16.8 SxS toolset, use VC\Auxiliary\Build\14.28 directory and SxS files
+ # if SxS version 14.28 not present/installed, fallback selection of toolset VC\Tools\MSVC\14.28.nnnnn.
+ debug(
+ 'rewrite toolset_version=%s => toolset_version=%s',
+ repr(toolset_version), repr(new_toolset_version)
+ )
+ toolset_version = new_toolset_version
+
+ if toolset_version in toolsets_sxs:
+ toolset_vcvars = toolsets_sxs[toolset_version]
+ return toolset_vcvars
+
+ for toolset_full in toolsets_full:
+ if toolset_full.startswith(toolset_version):
+ toolset_vcvars = toolset_full
+ return toolset_vcvars
+
+ return None
+
+def _msvc_script_argument_toolset_constraints(msvc, toolset_version):
+
+ if msvc.vs_def.vc_buildtools_def.vc_version_numeric < VS2017.vc_buildtools_def.vc_version_numeric:
+ debug(
+ 'invalid: msvc version constraint: %s < %s VS2017',
+ repr(msvc.vs_def.vc_buildtools_def.vc_version_numeric),
+ repr(VS2017.vc_buildtools_def.vc_version_numeric)
+ )
+ err_msg = "MSVC_TOOLSET_VERSION ({}) constraint violation: MSVC_VERSION {} < {} VS2017".format(
+ repr(toolset_version), repr(msvc.version), repr(VS2017.vc_buildtools_def.vc_version)
+ )
+ return err_msg
+
+ m = re_toolset_version.match(toolset_version)
+ if not m:
+ debug('invalid: re_toolset_version: toolset_version=%s', repr(toolset_version))
+ err_msg = 'MSVC_TOOLSET_VERSION {} format is not supported'.format(
+ repr(toolset_version)
+ )
+ return err_msg
+
+ toolset_ver = m.group('version')
+ toolset_vernum = float(toolset_ver)
+
+ if toolset_vernum < VS2015.vc_buildtools_def.vc_version_numeric:
+ debug(
+ 'invalid: toolset version constraint: %s < %s VS2015',
+ repr(toolset_vernum), repr(VS2015.vc_buildtools_def.vc_version_numeric)
+ )
+ err_msg = "MSVC_TOOLSET_VERSION ({}) constraint violation: toolset version {} < {} VS2015".format(
+ repr(toolset_version), repr(toolset_ver), repr(VS2015.vc_buildtools_def.vc_version)
+ )
+ return err_msg
+
+ if toolset_vernum > msvc.vs_def.vc_buildtools_def.vc_version_numeric:
+ debug(
+ 'invalid: toolset version constraint: toolset %s > %s msvc',
+ repr(toolset_vernum), repr(msvc.vs_def.vc_buildtools_def.vc_version_numeric)
+ )
+ err_msg = "MSVC_TOOLSET_VERSION ({}) constraint violation: toolset version {} > {} MSVC_VERSION".format(
+ repr(toolset_version), repr(toolset_ver), repr(msvc.version)
+ )
+ return err_msg
+
+ if toolset_vernum == VS2015.vc_buildtools_def.vc_version_numeric:
+ # tooset = 14.0
+ if re_toolset_full.match(toolset_version):
+ if not re_toolset_140.match(toolset_version):
+ debug(
+ 'invalid: toolset version 14.0 constraint: %s != 14.0',
+ repr(toolset_version)
+ )
+ err_msg = "MSVC_TOOLSET_VERSION ({}) constraint violation: toolset version {} != '14.0'".format(
+ repr(toolset_version), repr(toolset_version)
+ )
+ return err_msg
+ return None
+
+ if re_toolset_full.match(toolset_version):
+ debug('valid: re_toolset_full: toolset_version=%s', repr(toolset_version))
+ return None
+
+ if re_toolset_sxs.match(toolset_version):
+ debug('valid: re_toolset_sxs: toolset_version=%s', repr(toolset_version))
+ return None
+
+ debug('invalid: method exit: toolset_version=%s', repr(toolset_version))
+ err_msg = "MSVC_TOOLSET_VERSION ({}) format is not supported".format(repr(toolset_version))
+ return err_msg
+
+def _msvc_script_argument_toolset(env, msvc, vc_dir, arglist):
+
+ toolset_version = env['MSVC_TOOLSET_VERSION']
+ debug('MSVC_VERSION=%s, MSVC_TOOLSET_VERSION=%s', repr(msvc.version), repr(toolset_version))
+
+ if not toolset_version:
+ return None
+
+ err_msg = _msvc_script_argument_toolset_constraints(msvc, toolset_version)
+ if err_msg:
+ raise MSVCArgumentError(err_msg)
+
+ if toolset_version.startswith('14.0') and len(toolset_version) > len('14.0'):
+ new_toolset_version = '14.0'
+ debug(
+ 'rewrite toolset_version=%s => toolset_version=%s',
+ repr(toolset_version), repr(new_toolset_version)
+ )
+ toolset_version = new_toolset_version
+
+ toolset_vcvars = _msvc_version_toolset_vcvars(msvc, vc_dir, toolset_version)
+ debug(
+ 'toolset: toolset_version=%s, toolset_vcvars=%s',
+ repr(toolset_version), repr(toolset_vcvars)
+ )
+
+ if not toolset_vcvars:
+ err_msg = "MSVC_TOOLSET_VERSION {} not found for MSVC_VERSION {}".format(
+ repr(toolset_version), repr(msvc.version)
+ )
+ raise MSVCArgumentError(err_msg)
+
+ argpair = (SortOrder.TOOLSET, '-vcvars_ver={}'.format(toolset_vcvars))
+ arglist.append(argpair)
+
+ return toolset_vcvars
+
+def _msvc_script_default_toolset(env, msvc, vc_dir, arglist):
+
+ if msvc.vs_def.vc_buildtools_def.vc_version_numeric < VS2017.vc_buildtools_def.vc_version_numeric:
+ return None
+
+ toolset_default = _msvc_default_toolset(msvc, vc_dir)
+ if not toolset_default:
+ return None
+
+ debug('MSVC_VERSION=%s, toolset_default=%s', repr(msvc.version), repr(toolset_default))
+
+ argpair = (SortOrder.TOOLSET, '-vcvars_ver={}'.format(toolset_default))
+ arglist.append(argpair)
+
+ return toolset_default
+
+def _user_script_argument_toolset(env, toolset_version, user_argstr):
+
+ matches = [m for m in re_vcvars_toolset.finditer(user_argstr)]
+ if not matches:
+ return None
+
+ if len(matches) > 1:
+ debug('multiple toolset version declarations: MSVC_SCRIPT_ARGS=%s', repr(user_argstr))
+ err_msg = "multiple toolset version declarations: MSVC_SCRIPT_ARGS={}".format(repr(user_argstr))
+ raise MSVCArgumentError(err_msg)
+
+ if not toolset_version:
+ user_toolset = matches[0].group('toolset')
+ return user_toolset
+
+ env_argstr = env.get('MSVC_TOOLSET_VERSION','')
+ debug('multiple toolset version declarations: MSVC_TOOLSET_VERSION=%s, MSVC_SCRIPT_ARGS=%s', repr(env_argstr), repr(user_argstr))
+
+ err_msg = "multiple toolset version declarations: MSVC_TOOLSET_VERSION={} and MSVC_SCRIPT_ARGS={}".format(
+ repr(env_argstr), repr(user_argstr)
+ )
+
+ raise MSVCArgumentError(err_msg)
+
+def _msvc_script_argument_spectre(env, msvc, arglist):
+
+ spectre_libs = env['MSVC_SPECTRE_LIBS']
+ debug('MSVC_VERSION=%s, MSVC_SPECTRE_LIBS=%s', repr(msvc.version), repr(spectre_libs))
+
+ if not spectre_libs:
+ return None
+
+ if spectre_libs not in (True, '1'):
+ return None
+
+ if msvc.vs_def.vc_buildtools_def.vc_version_numeric < VS2017.vc_buildtools_def.vc_version_numeric:
+ debug(
+ 'invalid: msvc version constraint: %s < %s VS2017',
+ repr(msvc.vs_def.vc_buildtools_def.vc_version_numeric),
+ repr(VS2017.vc_buildtools_def.vc_version_numeric)
+ )
+ err_msg = "MSVC_SPECTRE_LIBS ({}) constraint violation: MSVC_VERSION {} < {} VS2017".format(
+ repr(spectre_libs), repr(msvc.version), repr(VS2017.vc_buildtools_def.vc_version)
+ )
+ raise MSVCArgumentError(err_msg)
+
+ spectre_arg = 'spectre'
+
+ # spectre libs may not be installed
+ argpair = (SortOrder.SPECTRE, '-vcvars_spectre_libs={}'.format(spectre_arg))
+ arglist.append(argpair)
+
+ return spectre_arg
+
+def _msvc_script_argument_user(env, msvc, arglist):
+
+ # subst None -> empty string
+ script_args = env.subst('$MSVC_SCRIPT_ARGS')
+ debug('MSVC_VERSION=%s, MSVC_SCRIPT_ARGS=%s', repr(msvc.version), repr(script_args))
+
+ if not script_args:
+ return None
+
+ if msvc.vs_def.vc_buildtools_def.vc_version_numeric < VS2015.vc_buildtools_def.vc_version_numeric:
+ debug(
+ 'invalid: msvc version constraint: %s < %s VS2015',
+ repr(msvc.vs_def.vc_buildtools_def.vc_version_numeric),
+ repr(VS2015.vc_buildtools_def.vc_version_numeric)
+ )
+ err_msg = "MSVC_SCRIPT_ARGS ({}) constraint violation: MSVC_VERSION {} < {} VS2015".format(
+ repr(script_args), repr(msvc.version), repr(VS2015.vc_buildtools_def.vc_version)
+ )
+ raise MSVCArgumentError(err_msg)
+
+ # user arguments are not validated
+ argpair = (SortOrder.USER, script_args)
+ arglist.append(argpair)
+
+ return script_args
+
+def _user_script_argument_spectre(env, spectre, user_argstr):
+
+ matches = [m for m in re_vcvars_spectre.finditer(user_argstr)]
+ if not matches:
+ return None
+
+ if len(matches) > 1:
+ debug('multiple spectre declarations: MSVC_SCRIPT_ARGS=%s', repr(user_argstr))
+ err_msg = "multiple spectre declarations: MSVC_SCRIPT_ARGS={}".format(repr(user_argstr))
+ raise MSVCArgumentError(err_msg)
+
+ if not spectre:
+ return None
+
+ env_argstr = env.get('MSVC_SPECTRE_LIBS','')
+ debug('multiple spectre declarations: MSVC_SPECTRE_LIBS=%s, MSVC_SCRIPT_ARGS=%s', repr(env_argstr), repr(user_argstr))
+
+ err_msg = "multiple spectre declarations: MSVC_SPECTRE_LIBS={} and MSVC_SCRIPT_ARGS={}".format(
+ repr(env_argstr), repr(user_argstr)
+ )
+
+ raise MSVCArgumentError(err_msg)
+
+def msvc_script_arguments(env, version, vc_dir, arg):
+
+ arglist = []
+
+ msvc = _msvc_version(version)
+
+ if arg:
+ argpair = (SortOrder.ARCH, arg)
+ arglist.append(argpair)
+
+ if 'MSVC_SCRIPT_ARGS' in env:
+ user_argstr = _msvc_script_argument_user(env, msvc, arglist)
+ else:
+ user_argstr = None
+
+ if 'MSVC_UWP_APP' in env:
+ uwp = _msvc_script_argument_uwp(env, msvc, arglist)
+ else:
+ uwp = None
+
+ if user_argstr:
+ _user_script_argument_uwp(env, uwp, user_argstr)
+
+ platform_type = 'uwp' if uwp else 'desktop'
+
+ if 'MSVC_SDK_VERSION' in env:
+ sdk_version = _msvc_script_argument_sdk(env, msvc, platform_type, arglist)
+ else:
+ sdk_version = None
+
+ if user_argstr:
+ user_sdk = _user_script_argument_sdk(env, sdk_version, user_argstr)
+ else:
+ user_sdk = None
+
+ if MSVC_FORCE_DEFAULT_SDK:
+ if not sdk_version and not user_sdk:
+ sdk_version = _msvc_script_default_sdk(env, msvc, platform_type, arglist)
+
+ if 'MSVC_TOOLSET_VERSION' in env:
+ toolset_version = _msvc_script_argument_toolset(env, msvc, vc_dir, arglist)
+ else:
+ toolset_version = None
+
+ if user_argstr:
+ user_toolset = _user_script_argument_toolset(env, toolset_version, user_argstr)
+ else:
+ user_toolset = None
+
+ if MSVC_FORCE_DEFAULT_TOOLSET:
+ if not toolset_version and not user_toolset:
+ toolset_version = _msvc_script_default_toolset(env, msvc, vc_dir, arglist)
+
+ if 'MSVC_SPECTRE_LIBS' in env:
+ spectre = _msvc_script_argument_spectre(env, msvc, arglist)
+ else:
+ spectre = None
+
+ if user_argstr:
+ _user_script_argument_spectre(env, spectre, user_argstr)
+
+ if arglist:
+ arglist.sort()
+ argstr = ' '.join([argpair[-1] for argpair in arglist]).strip()
+ else:
+ argstr = ''
+
+ debug('arguments: %s', repr(argstr))
+ return argstr
+
+def reset():
+ debug('')
+ _reset_toolset_cache()
+
+def verify():
+ debug('')
+ _verify_re_sdk_dispatch_map()
+