From 7082c53ff6bc7454e4cd306123b2de8516a56c2d Mon Sep 17 00:00:00 2001 From: Joseph Brill <48932340+jcbrill@users.noreply.github.com> Date: Tue, 14 Mar 2023 10:25:52 -0400 Subject: Fix #4312 and Windows on ARM64 support. Changes for #4312: * The installed VCS list is cached but has an indirect dependency on the value of the environment's TARGET_ARCH during construction. For the initial construction, force the env['TARGET_ARCH'] to be undefined and then restore the value after construction. * Protect against an empty regular expression list when iteratively removing default tool sequences. Changes for ARM64 host support: * Add configuration data structures to support ARM64 hosts and ARM64 native tools for VS2022. Update the tests for the renamed data structures. * Evaluate the PROCESSOR_ARCHITECTURE value from the windows registry before evaluating the os environment values for host architecture determination on Windows. * Set VSCMD_SKIP_SENDTELEMETRY=1 for arm32 process on arm64 host if not already defined to prevent powershell dll not found error. * The os environment variable value for PROCESSOR_ARCHITECTURE is AMD64 for Windows ARM64 hosts when using a python built for AMD64. Related MSVC changes for #4312 and ARM64 hosts: * Check that cl.exe exists in find_batch_file for VS6 to VS2015. Move the sdk batch file query code to its own function. Query for the sdk batch file only when all of the vc script host/target combinations have been exhausted and a valid script has not been found. * Hoist the query for the vc product directory outside the current vc script host/target loop. Catch the internal exceptions as before. * Clear the sdk batch file path for VCForPython as the sdk batch files do not appear to be updated during installation and do not point to the VCForPython installation location. * Move the sdk batch file determination to its own function. Defer evaluation of candidate sdk batch files until after all host/target combinations of the vc scripts have been evaluated. * Always check that cl.exe is found in vc script environment path. Miscellaneous: * Reorder and group exception definitions in Tool\MSCommon\vc.py by external exceptions and internal exceptions. * Adjust debug messages. * Convert the floating point msvc version to an integer version number for product range comparisons (e.g., 14.3 is 143). Adjust the comparison ranges accordingly. --- SCons/Platform/win32.py | 20 +- SCons/Tool/MSCommon/MSVC/SetupEnvDefault.py | 29 +- SCons/Tool/MSCommon/common.py | 36 ++- SCons/Tool/MSCommon/vc.py | 429 ++++++++++++++++++++++------ SCons/Tool/MSCommon/vcTests.py | 48 +++- 5 files changed, 440 insertions(+), 122 deletions(-) diff --git a/SCons/Platform/win32.py b/SCons/Platform/win32.py index 990794f..e815913 100644 --- a/SCons/Platform/win32.py +++ b/SCons/Platform/win32.py @@ -299,6 +299,11 @@ SupportedArchitectureList = [ ), ArchDefinition( + 'arm64', + ['ARM64', 'aarch64', 'AARCH64', 'AArch64'], + ), + + ArchDefinition( 'ia64', ['IA64'], ), @@ -315,10 +320,21 @@ def get_architecture(arch=None): """Returns the definition for the specified architecture string. If no string is specified, the system default is returned (as defined - by the PROCESSOR_ARCHITEW6432 or PROCESSOR_ARCHITECTURE environment - variables). + by the registry PROCESSOR_ARCHITECTURE value, PROCESSOR_ARCHITEW6432 + environment variable, PROCESSOR_ARCHITECTURE environment variable, or + the platform machine). """ if arch is None: + if SCons.Util.can_read_reg: + try: + k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, + 'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment') + val, tok = SCons.Util.RegQueryValueEx(k, 'PROCESSOR_ARCHITECTURE') + except SCons.Util.RegError: + val = '' + if val and val in SupportedArchitectureMap: + arch = val + if arch is None: arch = os.environ.get('PROCESSOR_ARCHITEW6432') if not arch: arch = os.environ.get('PROCESSOR_ARCHITECTURE') diff --git a/SCons/Tool/MSCommon/MSVC/SetupEnvDefault.py b/SCons/Tool/MSCommon/MSVC/SetupEnvDefault.py index e1c05bc..7d0f0e4 100644 --- a/SCons/Tool/MSCommon/MSVC/SetupEnvDefault.py +++ b/SCons/Tool/MSCommon/MSVC/SetupEnvDefault.py @@ -188,19 +188,22 @@ def register_iserror(env, tool, msvc_exists_func): debug('msvc default:check tools:nchar=%d, tools=%s', tools_nchar, tools) # iteratively remove default tool sequences (longest to shortest) - re_nchar_min, re_tools_min = _Data.default_tools_re_list[-1] - if tools_nchar >= re_nchar_min and re_tools_min.search(tools): - # minimum characters satisfied and minimum pattern exists - for re_nchar, re_default_tool in _Data.default_tools_re_list: - if tools_nchar < re_nchar: - # not enough characters for pattern - continue - tools = re_default_tool.sub('', tools).strip(_Data.separator) - tools_nchar = len(tools) - debug('msvc default:check tools:nchar=%d, tools=%s', tools_nchar, tools) - if tools_nchar < re_nchar_min or not re_tools_min.search(tools): - # less than minimum characters or minimum pattern does not exist - break + if not _Data.default_tools_re_list: + debug('default_tools_re_list=%s', _Data.default_tools_re_list) + else: + re_nchar_min, re_tools_min = _Data.default_tools_re_list[-1] + if tools_nchar >= re_nchar_min and re_tools_min.search(tools): + # minimum characters satisfied and minimum pattern exists + for re_nchar, re_default_tool in _Data.default_tools_re_list: + if tools_nchar < re_nchar: + # not enough characters for pattern + continue + tools = re_default_tool.sub('', tools).strip(_Data.separator) + tools_nchar = len(tools) + debug('msvc default:check tools:nchar=%d, tools=%s', tools_nchar, tools) + if tools_nchar < re_nchar_min or not re_tools_min.search(tools): + # less than minimum characters or minimum pattern does not exist + break # construct non-default list(s) tools set tools_set = {msvc_tool for msvc_tool in tools.split(_Data.separator) if msvc_tool} diff --git a/SCons/Tool/MSCommon/common.py b/SCons/Tool/MSCommon/common.py index ad4c827..df8e6c8 100644 --- a/SCons/Tool/MSCommon/common.py +++ b/SCons/Tool/MSCommon/common.py @@ -209,6 +209,17 @@ def has_reg(value): # Functions for fetching environment variable settings from batch files. +def _force_vscmd_skip_sendtelemetry(env): + + if 'VSCMD_SKIP_SENDTELEMETRY' in env['ENV']: + return False + + env['ENV']['VSCMD_SKIP_SENDTELEMETRY'] = '1' + debug("force env['ENV']['VSCMD_SKIP_SENDTELEMETRY']=%s", env['ENV']['VSCMD_SKIP_SENDTELEMETRY']) + + return True + + def normalize_env(env, keys, force=False): """Given a dictionary representing a shell environment, add the variables from os.environ needed for the processing of .bat files; the keys are @@ -257,7 +268,7 @@ def normalize_env(env, keys, force=False): return normenv -def get_output(vcbat, args=None, env=None): +def get_output(vcbat, args=None, env=None, skip_sendtelemetry=False): """Parse the output of given bat file, with given args.""" if env is None: @@ -296,20 +307,23 @@ def get_output(vcbat, args=None, env=None): ] env['ENV'] = normalize_env(env['ENV'], vs_vc_vars, force=False) + if skip_sendtelemetry: + _force_vscmd_skip_sendtelemetry(env) + if args: debug("Calling '%s %s'", vcbat, args) - popen = SCons.Action._subproc(env, - '"%s" %s & set' % (vcbat, args), - stdin='devnull', - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + cmd_str = '"%s" %s & set' % (vcbat, args) else: debug("Calling '%s'", vcbat) - popen = SCons.Action._subproc(env, - '"%s" & set' % vcbat, - stdin='devnull', - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + cmd_str = '"%s" & set' % vcbat + + popen = SCons.Action._subproc( + env, + cmd_str, + stdin='devnull', + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) # Use the .stdout and .stderr attributes directly because the # .communicate() method uses the threading module on Windows diff --git a/SCons/Tool/MSCommon/vc.py b/SCons/Tool/MSCommon/vc.py index 7871940..64b4cde 100644 --- a/SCons/Tool/MSCommon/vc.py +++ b/SCons/Tool/MSCommon/vc.py @@ -43,6 +43,7 @@ import SCons.compat import subprocess import os import platform +import sysconfig from pathlib import Path from string import digits as string_digits from subprocess import PIPE @@ -69,8 +70,7 @@ from .MSVC.Exceptions import ( MSVCToolsetVersionNotFound, ) -class UnsupportedVersion(VisualCException): - pass +# external exceptions class MSVCUnsupportedHostArch(VisualCException): pass @@ -78,21 +78,35 @@ class MSVCUnsupportedHostArch(VisualCException): class MSVCUnsupportedTargetArch(VisualCException): pass -class MissingConfiguration(VisualCException): +class MSVCScriptNotFound(MSVCUserError): pass -class NoVersionFound(VisualCException): +class MSVCUseSettingsError(MSVCUserError): pass -class BatchFileExecutionError(VisualCException): +# internal exceptions + +class UnsupportedVersion(VisualCException): pass -class MSVCScriptNotFound(MSVCUserError): +class MissingConfiguration(VisualCException): pass -class MSVCUseSettingsError(MSVCUserError): +class BatchFileExecutionError(VisualCException): pass +# undefined object for dict.get() in case key exists and value is None +UNDEFINED = object() + +# powershell error sending telemetry for arm32 process on arm64 host (VS2019+): +# True: force VSCMD_SKIP_SENDTELEMETRY=1 (if necessary) +# False: do nothing +_ARM32_ON_ARM64_SKIP_SENDTELEMETRY = True + +# MSVC 9.0 preferred query order: +# True: VCForPython, VisualStudio +# FAlse: VisualStudio, VCForPython +_VC90_Prefer_VCForPython = True # Dict to 'canonalize' the arch _ARCH_TO_CANONICAL = { @@ -282,7 +296,9 @@ def _host_target_config_factory(*, label, host_all_hosts, host_all_targets, host # The cl path fragment under the toolset version folder is the second value of # the stored tuple. -_GE2017_HOST_TARGET_BATCHFILE_CLPATHCOMPS = { +# 14.3 (VS2022) and later + +_GE2022_HOST_TARGET_BATCHFILE_CLPATHCOMPS = { ('amd64', 'amd64') : ('vcvars64.bat', ('bin', 'Hostx64', 'x64')), ('amd64', 'x86') : ('vcvarsamd64_x86.bat', ('bin', 'Hostx64', 'x86')), @@ -294,11 +310,66 @@ _GE2017_HOST_TARGET_BATCHFILE_CLPATHCOMPS = { ('x86', 'arm') : ('vcvarsx86_arm.bat', ('bin', 'Hostx86', 'arm')), ('x86', 'arm64') : ('vcvarsx86_arm64.bat', ('bin', 'Hostx86', 'arm64')), + ('arm64', 'amd64') : ('vcvarsarm64_amd64.bat', ('bin', 'Hostarm64', 'arm64_amd64')), + ('arm64', 'x86') : ('vcvarsarm64_x86.bat', ('bin', 'Hostarm64', 'arm64_x86')), + ('arm64', 'arm') : ('vcvarsarm64_arm.bat', ('bin', 'Hostarm64', 'arm64_arm')), + ('arm64', 'arm64') : ('vcvarsarm64.bat', ('bin', 'Hostarm64', 'arm64')), + } -_GE2017_HOST_TARGET_CFG = _host_target_config_factory( +_GE2022_HOST_TARGET_CFG = _host_target_config_factory( - label = 'GE2017', + label = 'GE2022', + + host_all_hosts = OrderedDict([ + ('amd64', ['amd64', 'x86']), + ('x86', ['x86']), + ('arm64', ['arm64', 'amd64', 'x86']), + ('arm', ['x86']), + ]), + + host_all_targets = { + 'amd64': ['amd64', 'x86', 'arm64', 'arm'], + 'x86': ['x86', 'amd64', 'arm', 'arm64'], + 'arm64': ['arm64', 'amd64', 'arm', 'x86'], + 'arm': [], + }, + + host_def_targets = { + 'amd64': ['amd64', 'x86'], + 'x86': ['x86'], + 'arm64': ['arm64', 'amd64', 'arm', 'x86'], + 'arm': ['arm'], + }, + +) + +# debug("_GE2022_HOST_TARGET_CFG: %s", _GE2022_HOST_TARGET_CFG) + +# 14.2 (VS2019) to 14.1 (VS2017) + +_LE2019_HOST_TARGET_BATCHFILE_CLPATHCOMPS = { + + ('amd64', 'amd64') : ('vcvars64.bat', ('bin', 'Hostx64', 'x64')), + ('amd64', 'x86') : ('vcvarsamd64_x86.bat', ('bin', 'Hostx64', 'x86')), + ('amd64', 'arm') : ('vcvarsamd64_arm.bat', ('bin', 'Hostx64', 'arm')), + ('amd64', 'arm64') : ('vcvarsamd64_arm64.bat', ('bin', 'Hostx64', 'arm64')), + + ('x86', 'amd64') : ('vcvarsx86_amd64.bat', ('bin', 'Hostx86', 'x64')), + ('x86', 'x86') : ('vcvars32.bat', ('bin', 'Hostx86', 'x86')), + ('x86', 'arm') : ('vcvarsx86_arm.bat', ('bin', 'Hostx86', 'arm')), + ('x86', 'arm64') : ('vcvarsx86_arm64.bat', ('bin', 'Hostx86', 'arm64')), + + ('arm64', 'amd64') : ('vcvars64.bat', ('bin', 'Hostx64', 'x64')), + ('arm64', 'x86') : ('vcvarsamd64_x86.bat', ('bin', 'Hostx64', 'x86')), + ('arm64', 'arm') : ('vcvarsamd64_arm.bat', ('bin', 'Hostx64', 'arm')), + ('arm64', 'arm64') : ('vcvarsamd64_arm64.bat', ('bin', 'Hostx64', 'arm64')), + +} + +_LE2019_HOST_TARGET_CFG = _host_target_config_factory( + + label = 'LE2019', host_all_hosts = OrderedDict([ ('amd64', ['amd64', 'x86']), @@ -310,20 +381,20 @@ _GE2017_HOST_TARGET_CFG = _host_target_config_factory( host_all_targets = { 'amd64': ['amd64', 'x86', 'arm64', 'arm'], 'x86': ['x86', 'amd64', 'arm', 'arm64'], - 'arm64': [], + 'arm64': ['arm64', 'amd64', 'arm', 'x86'], 'arm': [], }, host_def_targets = { 'amd64': ['amd64', 'x86'], 'x86': ['x86'], - 'arm64': ['arm64', 'arm'], + 'arm64': ['arm64', 'amd64', 'arm', 'x86'], 'arm': ['arm'], }, ) -# debug("_GE2017_HOST_TARGET_CFG: %s", _GE2017_HOST_TARGET_CFG) +# debug("_LE2019_HOST_TARGET_CFG: %s", _LE2019_HOST_TARGET_CFG) # 14.0 (VS2015) to 8.0 (VS2005) @@ -345,6 +416,10 @@ _LE2015_HOST_TARGET_BATCHARG_CLPATHCOMPS = { ('x86', 'arm') : ('x86_arm', ('bin', 'x86_arm')), ('x86', 'ia64') : ('x86_ia64', ('bin', 'x86_ia64')), + ('arm64', 'amd64') : ('amd64', ('bin', 'amd64')), + ('arm64', 'x86') : ('amd64_x86', ('bin', 'amd64_x86')), + ('arm64', 'arm') : ('amd64_arm', ('bin', 'amd64_arm')), + ('arm', 'arm') : ('arm', ('bin', 'arm')), ('ia64', 'ia64') : ('ia64', ('bin', 'ia64')), @@ -357,6 +432,7 @@ _LE2015_HOST_TARGET_CFG = _host_target_config_factory( host_all_hosts = OrderedDict([ ('amd64', ['amd64', 'x86']), ('x86', ['x86']), + ('arm64', ['amd64', 'x86']), ('arm', ['arm']), ('ia64', ['ia64']), ]), @@ -364,6 +440,7 @@ _LE2015_HOST_TARGET_CFG = _host_target_config_factory( host_all_targets = { 'amd64': ['amd64', 'x86', 'arm'], 'x86': ['x86', 'amd64', 'arm', 'ia64'], + 'arm64': ['amd64', 'x86', 'arm'], 'arm': ['arm'], 'ia64': ['ia64'], }, @@ -371,6 +448,7 @@ _LE2015_HOST_TARGET_CFG = _host_target_config_factory( host_def_targets = { 'amd64': ['amd64', 'x86'], 'x86': ['x86'], + 'arm64': ['amd64', 'arm', 'x86'], 'arm': ['arm'], 'ia64': ['ia64'], }, @@ -391,16 +469,19 @@ _LE2003_HOST_TARGET_CFG = _host_target_config_factory( host_all_hosts = OrderedDict([ ('amd64', ['x86']), ('x86', ['x86']), + ('arm64', ['x86']), ]), host_all_targets = { 'amd64': ['x86'], 'x86': ['x86'], + 'arm64': ['x86'], }, host_def_targets = { 'amd64': ['x86'], 'x86': ['x86'], + 'arm64': ['x86'], }, ) @@ -444,28 +525,54 @@ def get_host_platform(host_platform): return host +_native_host_architecture = None + +def get_native_host_architecture(): + """Return the native host architecture.""" + global _native_host_architecture + + if _native_host_architecture is None: + + try: + arch = common.read_reg( + r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE' + ) + except OSError: + arch = None + + if not arch: + arch = platform.machine() + + _native_host_architecture = arch + + return _native_host_architecture + _native_host_platform = None def get_native_host_platform(): global _native_host_platform if _native_host_platform is None: - - _native_host_platform = get_host_platform(platform.machine()) + arch = get_native_host_architecture() + _native_host_platform = get_host_platform(arch) return _native_host_platform def get_host_target(env, msvc_version, all_host_targets=False): vernum = float(get_msvc_version_numeric(msvc_version)) - - if vernum > 14: - # 14.1 (VS2017) and later - host_target_cfg = _GE2017_HOST_TARGET_CFG - elif 14 >= vernum >= 8: + vernum_int = int(vernum * 10) + + if vernum_int >= 143: + # 14.3 (VS2022) and later + host_target_cfg = _GE2022_HOST_TARGET_CFG + elif 143 > vernum_int >= 141: + # 14.2 (VS2019) to 14.1 (VS2017) + host_target_cfg = _LE2019_HOST_TARGET_CFG + elif 141 > vernum_int >= 80: # 14.0 (VS2015) to 8.0 (VS2005) host_target_cfg = _LE2015_HOST_TARGET_CFG - else: + else: # 80 > vernum_int # 7.1 (VS2003) and earlier host_target_cfg = _LE2003_HOST_TARGET_CFG @@ -520,6 +627,53 @@ def get_host_target(env, msvc_version, all_host_targets=False): return host_platform, target_platform, host_target_list +_arm32_process_arm64_host = None + +def is_arm32_process_arm64_host(): + global _arm32_process_arm64_host + + if _arm32_process_arm64_host is None: + + host = get_native_host_architecture() + host = _ARCH_TO_CANONICAL.get(host.lower(),'') + host_isarm64 = host == 'arm64' + + process = sysconfig.get_platform() + process_isarm32 = process == 'win-arm32' + + _arm32_process_arm64_host = host_isarm64 and process_isarm32 + + return _arm32_process_arm64_host + +_check_skip_sendtelemetry = None + +def _skip_sendtelemetry(env): + global _check_skip_sendtelemetry + + if _check_skip_sendtelemetry is None: + + if _ARM32_ON_ARM64_SKIP_SENDTELEMETRY and is_arm32_process_arm64_host(): + _check_skip_sendtelemetry = True + else: + _check_skip_sendtelemetry = False + + if not _check_skip_sendtelemetry: + return False + + msvc_version = env.get('MSVC_VERSION') if env else None + if not msvc_version: + msvc_version = msvc_default_version(env) + + if not msvc_version: + return False + + vernum = float(get_msvc_version_numeric(msvc_version)) + if vernum < 14.2: # VS2019 + return False + + # arm32 process, arm64 host, VS2019+ + return True + # If you update this, update SupportedVSList in Tool/MSCommon/vs.py, and the # MSVC_VERSION documentation in Tool/msvc.xml. _VCVER = [ @@ -589,6 +743,9 @@ _VCVER_TO_PRODUCT_DIR = { '9.0': [ (SCons.Util.HKEY_CURRENT_USER, r'Microsoft\DevDiv\VCForPython\9.0\installdir',), (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\9.0\Setup\VC\ProductDir',), + ] if _VC90_Prefer_VCForPython else [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\9.0\Setup\VC\ProductDir',), + (SCons.Util.HKEY_CURRENT_USER, r'Microsoft\DevDiv\VCForPython\9.0\installdir',), ], '9.0Exp': [ (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\9.0\Setup\VC\ProductDir'), @@ -763,7 +920,7 @@ def find_vc_pdir(env, msvc_version): raise MissingConfiguration("registry dir {} not found on the filesystem".format(comps)) return None -def find_batch_file(env, msvc_version, host_arch, target_arch): +def find_batch_file(msvc_version, host_arch, target_arch, pdir): """ Find the location of the batch script which should set up the compiler for any TARGET_ARCH whose compilers were installed by Visual Studio/VCExpress @@ -772,52 +929,73 @@ def find_batch_file(env, msvc_version, host_arch, target_arch): scripts named with a host_target pair that calls vcvarsall.bat properly, so use that and return an empty argument. """ - pdir = find_vc_pdir(env, msvc_version) - if pdir is None: - raise NoVersionFound("No version of Visual Studio found") - debug('looking in %s', pdir) # filter out e.g. "Exp" from the version name - msvc_ver_numeric = get_msvc_version_numeric(msvc_version) - vernum = float(msvc_ver_numeric) + vernum = float(get_msvc_version_numeric(msvc_version)) + vernum_int = int(vernum * 10) + + sdk_pdir = pdir arg = '' vcdir = None + clexe = None - if vernum > 14: - # 14.1 (VS2017) and later + if vernum_int >= 143: + # 14.3 (VS2022) and later + batfiledir = os.path.join(pdir, "Auxiliary", "Build") + batfile, _ = _GE2022_HOST_TARGET_BATCHFILE_CLPATHCOMPS[(host_arch, target_arch)] + batfilename = os.path.join(batfiledir, batfile) + vcdir = pdir + elif 143 > vernum_int >= 141: + # 14.2 (VS2019) to 14.1 (VS2017) batfiledir = os.path.join(pdir, "Auxiliary", "Build") - batfile, _ = _GE2017_HOST_TARGET_BATCHFILE_CLPATHCOMPS[(host_arch, target_arch)] + batfile, _ = _LE2019_HOST_TARGET_BATCHFILE_CLPATHCOMPS[(host_arch, target_arch)] batfilename = os.path.join(batfiledir, batfile) vcdir = pdir - elif 14 >= vernum >= 8: + elif 141 > vernum_int >= 80: # 14.0 (VS2015) to 8.0 (VS2005) - arg, _ = _LE2015_HOST_TARGET_BATCHARG_CLPATHCOMPS[(host_arch, target_arch)] + arg, cl_path_comps = _LE2015_HOST_TARGET_BATCHARG_CLPATHCOMPS[(host_arch, target_arch)] batfilename = os.path.join(pdir, "vcvarsall.bat") if msvc_version == '9.0' and not os.path.exists(batfilename): # Visual C++ for Python batch file is in installdir (root) not productdir (vc) batfilename = os.path.normpath(os.path.join(pdir, os.pardir, "vcvarsall.bat")) - else: + # Visual C++ for Python sdk batch files do not point to the VCForPython installation + sdk_pdir = None + clexe = os.path.join(pdir, *cl_path_comps, _CL_EXE_NAME) + else: # 80 > vernum_int # 7.1 (VS2003) and earlier pdir = os.path.join(pdir, "Bin") batfilename = os.path.join(pdir, "vcvars32.bat") + clexe = os.path.join(pdir, _CL_EXE_NAME) if not os.path.exists(batfilename): - debug("Not found: %s", batfilename) + debug("batch file not found: %s", batfilename) batfilename = None + if clexe and not os.path.exists(clexe): + debug("cl.exe not found: %s", clexe) + batfilename = None + + return batfilename, arg, vcdir, sdk_pdir + +def find_batch_file_sdk(host_arch, target_arch, sdk_pdir): + """ + Find the location of the sdk batch script which should set up the compiler + for any TARGET_ARCH whose compilers were installed by Visual Studio/VCExpress + """ + installed_sdks = get_installed_sdks() for _sdk in installed_sdks: sdk_bat_file = _sdk.get_sdk_vc_script(host_arch, target_arch) if not sdk_bat_file: - debug("batch file not found:%s", _sdk) + debug("sdk batch file not found:%s", _sdk) else: - sdk_bat_file_path = os.path.join(pdir, sdk_bat_file) + sdk_bat_file_path = os.path.join(sdk_pdir, sdk_bat_file) if os.path.exists(sdk_bat_file_path): debug('sdk_bat_file_path:%s', sdk_bat_file_path) - return batfilename, arg, vcdir, sdk_bat_file_path + return sdk_bat_file_path - return batfilename, arg, vcdir, None + return None __INSTALLED_VCS_RUN = None _VC_TOOLS_VERSION_FILE_PATH = ['Auxiliary', 'Build', 'Microsoft.VCToolsVersion.default.txt'] @@ -852,9 +1030,10 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): host_platform, target_platform, host_target_list = platforms vernum = float(get_msvc_version_numeric(msvc_version)) + vernum_int = int(vernum * 10) # make sure the cl.exe exists meaning the tool is installed - if vernum > 14: + if vernum_int >= 141: # 14.1 (VS2017) and later # 2017 and newer allowed multiple versions of the VC toolset to be # installed at the same time. This changes the layout. @@ -871,11 +1050,18 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): debug('failed to find MSVC version in %s', default_toolset_file) return False + if vernum_int >= 143: + # 14.3 (VS2022) and later + host_target_batchfile_clpathcomps = _GE2022_HOST_TARGET_BATCHFILE_CLPATHCOMPS + else: + # 14.2 (VS2019) to 14.1 (VS2017) + host_target_batchfile_clpathcomps = _LE2019_HOST_TARGET_BATCHFILE_CLPATHCOMPS + for host_platform, target_platform in host_target_list: debug('host platform %s, target platform %s for version %s', host_platform, target_platform, msvc_version) - batchfile_clpathcomps = _GE2017_HOST_TARGET_BATCHFILE_CLPATHCOMPS.get((host_platform, target_platform), None) + batchfile_clpathcomps = host_target_batchfile_clpathcomps.get((host_platform, target_platform), None) if batchfile_clpathcomps is None: debug('unsupported host/target platform combo: (%s,%s)', host_platform, target_platform) continue @@ -888,7 +1074,7 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): debug('found %s!', _CL_EXE_NAME) return True - elif 14 >= vernum >= 8: + elif 141 > vernum_int >= 80: # 14.0 (VS2015) to 8.0 (VS2005) for host_platform, target_platform in host_target_list: @@ -908,7 +1094,7 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): debug('found %s', _CL_EXE_NAME) return True - elif 8 > vernum >= 6: + elif 80 > vernum_int >= 60: # 7.1 (VS2003) to 6.0 (VS6) # quick check for vc_dir/bin and vc_dir/ before walk @@ -928,7 +1114,7 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): return False else: - # version not support return false + # version not supported return false debug('unsupported MSVC version: %s', str(vernum)) return False @@ -939,6 +1125,13 @@ def get_installed_vcs(env=None): if __INSTALLED_VCS_RUN is not None: return __INSTALLED_VCS_RUN + save_target_arch = env.get('TARGET_ARCH', UNDEFINED) if env else None + force_target = env and save_target_arch and save_target_arch != UNDEFINED + + if force_target: + del env['TARGET_ARCH'] + debug("delete env['TARGET_ARCH']") + installed_versions = [] for ver in _VCVER: @@ -960,7 +1153,12 @@ def get_installed_vcs(env=None): except VisualCException as e: debug('did not find VC %s: caught exception %s', ver, str(e)) + if force_target: + env['TARGET_ARCH'] = save_target_arch + debug("restore env['TARGET_ARCH']=%s", save_target_arch) + __INSTALLED_VCS_RUN = installed_versions + debug("__INSTALLED_VCS_RUN=%s", __INSTALLED_VCS_RUN) return __INSTALLED_VCS_RUN def reset_installed_vcs(): @@ -982,6 +1180,19 @@ def get_installed_vcs_components(env=None): msvc_version_component_defs = [MSVC.Util.msvc_version_components(vcver) for vcver in vcs] return msvc_version_component_defs +def _check_cl_exists_in_script_env(data): + """Find cl.exe in the script environment path.""" + cl_path = None + if data and 'PATH' in data: + for p in data['PATH']: + cl_exe = os.path.join(p, _CL_EXE_NAME) + if os.path.exists(cl_exe): + cl_path = cl_exe + break + have_cl = True if cl_path else False + debug('have_cl: %s, cl_path: %s', have_cl, cl_path) + return have_cl, cl_path + # Running these batch files isn't cheap: most of the time spent in # msvs.generate() is due to vcvars*.bat. In a build that uses "tools='msvs'" # in multiple environments, for example: @@ -1027,7 +1238,8 @@ def script_env(env, script, args=None): cache_data = None if cache_data is None: - stdout = common.get_output(script, args) + skip_sendtelemetry = _skip_sendtelemetry(env) + stdout = common.get_output(script, args, skip_sendtelemetry=skip_sendtelemetry) cache_data = common.parse_output(stdout) # debug(stdout) @@ -1044,12 +1256,7 @@ def script_env(env, script, args=None): if script_errlog: script_errmsg = '\n'.join(script_errlog) - have_cl = False - if cache_data and 'PATH' in cache_data: - for p in cache_data['PATH']: - if os.path.exists(os.path.join(p, _CL_EXE_NAME)): - have_cl = True - break + have_cl, _ = _check_cl_exists_in_script_env(cache_data) debug( 'script=%s args=%s have_cl=%s, errors=%s', @@ -1130,6 +1337,18 @@ def msvc_find_valid_batch_script(env, version): get it right. """ + # Find the product directory + pdir = None + try: + pdir = find_vc_pdir(env, version) + except UnsupportedVersion: + # Unsupported msvc version (raise MSVCArgumentError?) + pass + except MissingConfiguration: + # Found version, directory missing + pass + debug('product directory: version=%s, pdir=%s', version, pdir) + # Find the host, target, and all candidate (host, target) platform combinations: platforms = get_host_target(env, version) debug("host_platform %s, target_platform %s host_target_list %s", *platforms) @@ -1137,48 +1356,81 @@ def msvc_find_valid_batch_script(env, version): d = None version_installed = False - for host_arch, target_arch, in host_target_list: - # Set to current arch. - env['TARGET_ARCH'] = target_arch - arg = '' - # Try to locate a batch file for this host/target platform combo - try: - (vc_script, arg, vc_dir, sdk_script) = find_batch_file(env, version, host_arch, target_arch) - debug('vc_script:%s vc_script_arg:%s sdk_script:%s', vc_script, arg, sdk_script) - version_installed = True - except VisualCException as e: - msg = str(e) - debug('Caught exception while looking for batch file (%s)', msg) - version_installed = False - continue + if pdir: + + # Query all candidate sdk (host, target, sdk_pdir) after vc_script pass if necessary + sdk_queries = [] + + for host_arch, target_arch, in host_target_list: + # Set to current arch. + env['TARGET_ARCH'] = target_arch + arg = '' + + # Try to locate a batch file for this host/target platform combo + try: + (vc_script, arg, vc_dir, sdk_pdir) = find_batch_file(version, host_arch, target_arch, pdir) + debug('vc_script:%s vc_script_arg:%s', vc_script, arg) + version_installed = True + except VisualCException as e: + msg = str(e) + debug('Caught exception while looking for batch file (%s)', msg) + version_installed = False + continue + + # Save (host, target, sdk_pdir) platform combo for sdk queries + if sdk_pdir: + sdk_query = (host_arch, target_arch, sdk_pdir) + if sdk_query not in sdk_queries: + debug('save sdk_query host=%s, target=%s, sdk_pdir=%s', host_arch, target_arch, sdk_pdir) + sdk_queries.append(sdk_query) + + if not vc_script: + continue - # Try to use the located batch file for this host/target platform combo - debug('use_script 2 %s, args:%s', repr(vc_script), arg) - found = None - if vc_script: + # Try to use the located batch file for this host/target platform combo arg = MSVC.ScriptArguments.msvc_script_arguments(env, version, vc_dir, arg) + debug('trying vc_script:%s, vc_script_args:%s', repr(vc_script), arg) try: d = script_env(env, vc_script, args=arg) - found = vc_script except BatchFileExecutionError as e: - debug('use_script 3: failed running VC script %s: %s: Error:%s', repr(vc_script), arg, e) - vc_script=None + debug('failed vc_script:%s, vc_script_args:%s, error:%s', repr(vc_script), arg, e) + vc_script = None continue - if not vc_script and sdk_script: - debug('use_script 4: trying sdk script: %s', sdk_script) - try: - d = script_env(env, sdk_script) - found = sdk_script - except BatchFileExecutionError as e: - debug('use_script 5: failed running SDK script %s: Error:%s', repr(sdk_script), e) + + have_cl, _ = _check_cl_exists_in_script_env(d) + if not have_cl: + debug('skip cl.exe not found vc_script:%s, vc_script_args:%s', repr(vc_script), arg) continue - elif not vc_script and not sdk_script: - debug('use_script 6: Neither VC script nor SDK script found') - continue - debug("Found a working script/target: %s/%s", repr(found), arg) - break # We've found a working target_platform, so stop looking + debug("Found a working script/target: %s/%s", repr(vc_script), arg) + break # We've found a working target_platform, so stop looking + + if not d: + for host_arch, target_arch, sdk_pdir in sdk_queries: + # Set to current arch. + env['TARGET_ARCH'] = target_arch + + sdk_script = find_batch_file_sdk(host_arch, target_arch, sdk_pdir) + if not sdk_script: + continue + + # Try to use the sdk batch file for this (host, target, sdk_pdir) combo + debug('trying sdk_script:%s', repr(sdk_script)) + try: + d = script_env(env, sdk_script) + version_installed = True + except BatchFileExecutionError as e: + debug('failed sdk_script:%s, error=%s', repr(sdk_script), e) + continue + + have_cl, _ = _check_cl_exists_in_script_env(d) + if not have_cl: + debug('skip cl.exe not found sdk_script:%s', repr(sdk_script)) + continue + + debug("Found a working script/target: %s", repr(sdk_script)) + break # We've found a working script, so stop looking # If we cannot find a viable installed compiler, reset the TARGET_ARCH # To it's initial value @@ -1206,8 +1458,6 @@ def msvc_find_valid_batch_script(env, version): return d -_UNDEFINED = object() - def get_use_script_use_settings(env): # use_script use_settings return values action @@ -1217,9 +1467,9 @@ def get_use_script_use_settings(env): # None (documentation) or evaluates False (code): bypass detection # need to distinguish between undefined and None - use_script = env.get('MSVC_USE_SCRIPT', _UNDEFINED) + use_script = env.get('MSVC_USE_SCRIPT', UNDEFINED) - if use_script != _UNDEFINED: + if use_script != UNDEFINED: # use_script defined, use_settings ignored (not type checked) return use_script, None @@ -1293,8 +1543,7 @@ def msvc_exists(env=None, version=None): rval = len(vcs) > 0 else: rval = version in vcs - if not rval: - debug('version=%s, return=%s', repr(version), rval) + debug('version=%s, return=%s', repr(version), rval) return rval def msvc_setup_env_user(env=None): diff --git a/SCons/Tool/MSCommon/vcTests.py b/SCons/Tool/MSCommon/vcTests.py index 3e37def..a8b139a 100644 --- a/SCons/Tool/MSCommon/vcTests.py +++ b/SCons/Tool/MSCommon/vcTests.py @@ -132,12 +132,48 @@ class MSVcTestCase(unittest.TestCase): print("Failed trying to write :%s :%s" % (tools_version_file, e)) - # Now walk all the valid combinations of host/target for 14.1 (VS2017) and later - vc_ge2017_list = SCons.Tool.MSCommon.vc._GE2017_HOST_TARGET_CFG.all_pairs + # Test 14.3 (VS2022) and later + vc_ge2022_list = SCons.Tool.MSCommon.vc._GE2022_HOST_TARGET_CFG.all_pairs - for host, target in vc_ge2017_list: - batfile, clpathcomps = SCons.Tool.MSCommon.vc._GE2017_HOST_TARGET_BATCHFILE_CLPATHCOMPS[(host,target)] - # print("GT 14 Got: (%s, %s) -> (%s, %s)"%(host,target,batfile,clpathcomps)) + for host, target in vc_ge2022_list: + batfile, clpathcomps = SCons.Tool.MSCommon.vc._GE2022_HOST_TARGET_BATCHFILE_CLPATHCOMPS[(host,target)] + # print("GE 14.3 Got: (%s, %s) -> (%s, %s)"%(host,target,batfile,clpathcomps)) + + env={'TARGET_ARCH':target, 'HOST_ARCH':host} + path = os.path.join('.', 'Tools', 'MSVC', MS_TOOLS_VERSION, *clpathcomps) + MSVcTestCase._createDummyCl(path, add_bin=False) + result=check(env, '.', '14.3') + # print("for:(%s, %s) got :%s"%(host, target, result)) + self.assertTrue(result, "Checking host: %s target: %s" % (host, target)) + + # Now test bogus value for HOST_ARCH + env={'TARGET_ARCH':'x86', 'HOST_ARCH':'GARBAGE'} + try: + result=check(env, '.', '14.3') + # print("for:%s got :%s"%(env, result)) + self.assertFalse(result, "Did not fail with bogus HOST_ARCH host: %s target: %s" % (env['HOST_ARCH'], env['TARGET_ARCH'])) + except MSVCUnsupportedHostArch: + pass + else: + self.fail('Did not fail when HOST_ARCH specified as: %s' % env['HOST_ARCH']) + + # Now test bogus value for TARGET_ARCH + env={'TARGET_ARCH':'GARBAGE', 'HOST_ARCH':'x86'} + try: + result=check(env, '.', '14.3') + # print("for:%s got :%s"%(env, result)) + self.assertFalse(result, "Did not fail with bogus TARGET_ARCH host: %s target: %s" % (env['HOST_ARCH'], env['TARGET_ARCH'])) + except MSVCUnsupportedTargetArch: + pass + else: + self.fail('Did not fail when TARGET_ARCH specified as: %s' % env['TARGET_ARCH']) + + # Test 14.2 (VS2019) to 14.1 (VS2017) versions + vc_le2019_list = SCons.Tool.MSCommon.vc._LE2019_HOST_TARGET_CFG.all_pairs + + for host, target in vc_le2019_list: + batfile, clpathcomps = SCons.Tool.MSCommon.vc._LE2019_HOST_TARGET_BATCHFILE_CLPATHCOMPS[(host,target)] + # print("LE 14.2 Got: (%s, %s) -> (%s, %s)"%(host,target,batfile,clpathcomps)) env={'TARGET_ARCH':target, 'HOST_ARCH':host} path = os.path.join('.', 'Tools', 'MSVC', MS_TOOLS_VERSION, *clpathcomps) @@ -173,7 +209,7 @@ class MSVcTestCase(unittest.TestCase): for host, target in vc_le2015_list: batarg, clpathcomps = SCons.Tool.MSCommon.vc._LE2015_HOST_TARGET_BATCHARG_CLPATHCOMPS[(host, target)] - # print("LE 14 Got: (%s, %s) -> (%s, %s)"%(host,target,batarg,clpathcomps)) + # print("LE 14.0 Got: (%s, %s) -> (%s, %s)"%(host,target,batarg,clpathcomps)) env={'TARGET_ARCH':target, 'HOST_ARCH':host} path = os.path.join('.', *clpathcomps) MSVcTestCase._createDummyCl(path, add_bin=False) -- cgit v0.12 From d352fa50095102ab1f81adb720e905967fd38b3d Mon Sep 17 00:00:00 2001 From: Joseph Brill <48932340+jcbrill@users.noreply.github.com> Date: Wed, 15 Mar 2023 09:19:19 -0400 Subject: Refactor MSCommon/common.py logging filter class due to SConfTests module reset when debug logging is enabled. --- SCons/Tool/MSCommon/common.py | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/SCons/Tool/MSCommon/common.py b/SCons/Tool/MSCommon/common.py index df8e6c8..dca43bf 100644 --- a/SCons/Tool/MSCommon/common.py +++ b/SCons/Tool/MSCommon/common.py @@ -46,30 +46,31 @@ LOGFILE = os.environ.get('SCONS_MSCOMMON_DEBUG') if LOGFILE: import logging - modulelist = ( - # root module and parent/root module - 'MSCommon', 'Tool', - # python library and below: correct iff scons does not have a lib folder - 'lib', - # scons modules - 'SCons', 'test', 'scons' - ) + class _Debug_Filter(logging.Filter): + # custom filter for module relative filename - def get_relative_filename(filename, module_list): - if not filename: + modulelist = ( + # root module and parent/root module + 'MSCommon', 'Tool', + # python library and below: correct iff scons does not have a lib folder + 'lib', + # scons modules + 'SCons', 'test', 'scons' + ) + + def get_relative_filename(self, filename, module_list): + if not filename: + return filename + for module in module_list: + try: + ind = filename.rindex(module) + return filename[ind:] + except ValueError: + pass return filename - for module in module_list: - try: - ind = filename.rindex(module) - return filename[ind:] - except ValueError: - pass - return filename - class _Debug_Filter(logging.Filter): - # custom filter for module relative filename def filter(self, record): - relfilename = get_relative_filename(record.pathname, modulelist) + relfilename = self.get_relative_filename(record.pathname, self.modulelist) relfilename = relfilename.replace('\\', '/') record.relfilename = relfilename return True -- cgit v0.12 From 4eca02072d7a39ef158d4d6aca1ec8845965568f Mon Sep 17 00:00:00 2001 From: Joseph Brill <48932340+jcbrill@users.noreply.github.com> Date: Sat, 18 Mar 2023 10:48:48 -0400 Subject: Update CHANGES.txt [skip ci] --- CHANGES.txt | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 8bb3c21..82e6d0a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -9,6 +9,31 @@ NOTE: 4.3.0 now requires Python 3.6.0 and above. Python 3.5.x is no longer suppo RELEASE VERSION/DATE TO BE FILLED IN LATER + From Joseph Brill: + - Fix issue #4312: the cached installed msvc list had an indirect dependency + on the target architecture in the environment dictionary. The first call + to construct the installed msvc list now forces the target architecture to be + undefined, constructs the installed msvc list, and then restores the original + target architecture. + Note: an indirect dependency on the VSWHERE construction variable in the + environment remains. + - Fix issue #4312: explicitly guard against an empty regular expression list + when msvc is not installed. + - When trying to find a valid msvc batch file, check that the compiler executable + (cl.exe) exists for VS6 to VS2015 to avoid executing the msvc batch file. Always + check that the compiler executable is found on the msvc script environment path + after running the msvc batch file. Only use the sdk batch files when all of the + msvc script host/target combinations have been exhausted and a valid script was + not found. + - Add ARM64 host configurations for windows and msvc. + Note: VS2013 and earlier has not been tested on ARM64. + - If necessary, automatically define VSCMD_SKIP_SENDTELEMETRY for VS2019 and later + on ARM64 hosts when using an arm32 build of python to prevent a powershell dll + not found error pop-up window. + - Fix an issue where test SConfTests.py would fail when mscommon debugging + was enabled. The mscommon debug filter class registered with the logging + module was refactored. + From Michał Górny: - Remove the redundant `wheel` dependency from `pyproject.toml`, as it is added automatically by the setuptools PEP517 backend. -- cgit v0.12 From 26dbadd82605e797b1151e04ba945b176ab1dfab Mon Sep 17 00:00:00 2001 From: Joseph Brill <48932340+jcbrill@users.noreply.github.com> Date: Sun, 19 Mar 2023 09:32:08 -0400 Subject: Add arm64 to the MSVS supported architectures list for VS2017 and later to be consistent with the current documentation of MSVS_ARCH. Update the documentation for HOST_ARCH. --- CHANGES.txt | 2 ++ SCons/Platform/Platform.xml | 4 ++-- SCons/Tool/MSCommon/vs.py | 8 ++++---- doc/generated/variables.gen | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 82e6d0a..614aebe 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -33,6 +33,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Fix an issue where test SConfTests.py would fail when mscommon debugging was enabled. The mscommon debug filter class registered with the logging module was refactored. + - Add arm64 to the MSVS supported architectures list for VS2017 and later to be + consistent with the current documentation of MSVS_ARCH. From Michał Górny: - Remove the redundant `wheel` dependency from `pyproject.toml`, diff --git a/SCons/Platform/Platform.xml b/SCons/Platform/Platform.xml index 08199f4..c449fa5 100644 --- a/SCons/Platform/Platform.xml +++ b/SCons/Platform/Platform.xml @@ -173,8 +173,8 @@ else: Valid host arch values are x86 and arm for 32-bit hosts and - amd64 and x86_64 - for 64-bit hosts. + amd64, arm64, + and x86_64 for 64-bit hosts. Should be considered immutable. diff --git a/SCons/Tool/MSCommon/vs.py b/SCons/Tool/MSCommon/vs.py index 08c3cf5..07fcdc4 100644 --- a/SCons/Tool/MSCommon/vs.py +++ b/SCons/Tool/MSCommon/vs.py @@ -207,7 +207,7 @@ SupportedVSList = [ executable_path=r'Common7\IDE\devenv.com', # should be a fallback, prefer use vswhere installationPath batch_file_path=r'Common7\Tools\VsDevCmd.bat', - supported_arch=['x86', 'amd64', "arm"], + supported_arch=['x86', 'amd64', "arm", 'arm64'], ), # Visual Studio 2019 @@ -219,7 +219,7 @@ SupportedVSList = [ executable_path=r'Common7\IDE\devenv.com', # should be a fallback, prefer use vswhere installationPath batch_file_path=r'Common7\Tools\VsDevCmd.bat', - supported_arch=['x86', 'amd64', "arm"], + supported_arch=['x86', 'amd64', "arm", 'arm64'], ), # Visual Studio 2017 @@ -231,7 +231,7 @@ SupportedVSList = [ executable_path=r'Common7\IDE\devenv.com', # should be a fallback, prefer use vswhere installationPath batch_file_path=r'Common7\Tools\VsDevCmd.bat', - supported_arch=['x86', 'amd64', "arm"], + supported_arch=['x86', 'amd64', "arm", 'arm64'], ), # Visual C++ 2017 Express Edition (for Desktop) @@ -243,7 +243,7 @@ SupportedVSList = [ executable_path=r'Common7\IDE\WDExpress.exe', # should be a fallback, prefer use vswhere installationPath batch_file_path=r'Common7\Tools\VsDevCmd.bat', - supported_arch=['x86', 'amd64', "arm"], + supported_arch=['x86', 'amd64', "arm", 'arm64'], ), # Visual Studio 2015 diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index 42935a3..86395a7 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -3179,8 +3179,8 @@ is -dNOPAUSE -dBATCH -sDEVICE=pdfwrite Valid host arch values are x86 and arm for 32-bit hosts and - amd64 and x86_64 - for 64-bit hosts. + amd64, arm64, + and x86_64 for 64-bit hosts. Should be considered immutable. -- cgit v0.12 From c50f65668f3cb1470685a1379b75039e11ae94b2 Mon Sep 17 00:00:00 2001 From: Joseph Brill <48932340+jcbrill@users.noreply.github.com> Date: Sun, 19 Mar 2023 12:00:37 -0400 Subject: Update RELEASE.txt. [skip ci] --- RELEASE.txt | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/RELEASE.txt b/RELEASE.txt index 4e25b95..b3e8c1a 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -18,6 +18,11 @@ NEW FUNCTIONALITY - List new features (presumably why a checkpoint is being released) +- MSVC: If available, native arm64 tools will be used on arm64 hosts for VS2022. +- MSVC: If necessary, automatically define VSCMD_SKIP_TELEMETRY for VS2019 and later + on arm64 hosts when using an arm (32-bit) build of python to prevent a powershell + error pop-up window (powershell dll not found). + DEPRECATED FUNCTIONALITY ------------------------ @@ -29,11 +34,37 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY - List modifications to existing features, where the previous behavior wouldn't actually be considered a bug +- MSVC: When trying to find a valid msvc batch file, the existence of the msvc compiler + executable is verified for VS6 to VS2015 to avoid executing the msvc batch file when + the host/target tool is known not to be present. Always check that the msvc compiler + executable is found on the msvc script environment path after running the msvc batch + file. The is predominately needed for recent versions of Visual Studio where the msvc + batch file exists but an individual msvc toolset may not support the host/target + architecture combination. For example, when using VS2022 on arm64, the arm64 native + tools are only installed for the 14.3x toolsets. + FIXES ----- - List fixes of outright bugs +- MSVC: The installed msvc list is calculated once and cached. There was an indirect + dependency on the target architecture when determining if each version of msvc + was installed based on the initial invocation. It was possible that an msvc instance + would not be considered installed due to the tools for the requested target + architecture not being installed. The initial call to construct the installed msvc + list now uses an undefined target architecture to evaluate all potential host/target + combinations when evaluating if the msvc tools are installed for a given Visual Studio + installation. +- MSVC: Erroneous construction of the installed msvc list (as described above) caused an + index error in the msvc support code. An explicit check was added to prevent indexing + into an empty list. +- MSCommon: Test SConsTests.py would fail when mscommon debugging was enabled via the + MSVC_MSCOMMON_DEBUG environment variable. The mscommon logging filter class registered + with the python logging module was refactored to prevent test failure. +- MSVS: Add arm64 to the MSVS supported architectures list for VS2017 and later to be + consistent with the current documentation of MSVS_ARCH. + IMPROVEMENTS ------------ @@ -54,6 +85,8 @@ DOCUMENTATION typo fixes, even if they're mentioned in src/CHANGES.txt to give the contributor credit) +- HOST_ARCH: Add arm64 to the valid win32 host architectures. + DEVELOPMENT ----------- -- cgit v0.12 From 4bdb9de39d98288c564e6e1fd5eefcbe2de5803a Mon Sep 17 00:00:00 2001 From: Joseph Brill <48932340+jcbrill@users.noreply.github.com> Date: Sun, 19 Mar 2023 13:39:37 -0400 Subject: Fix typographical error in RELEASE.txt [skip ci] --- RELEASE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE.txt b/RELEASE.txt index b3e8c1a..a73919c 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -59,7 +59,7 @@ FIXES - MSVC: Erroneous construction of the installed msvc list (as described above) caused an index error in the msvc support code. An explicit check was added to prevent indexing into an empty list. -- MSCommon: Test SConsTests.py would fail when mscommon debugging was enabled via the +- MSCommon: Test SConfTests.py would fail when mscommon debugging was enabled via the MSVC_MSCOMMON_DEBUG environment variable. The mscommon logging filter class registered with the python logging module was refactored to prevent test failure. - MSVS: Add arm64 to the MSVS supported architectures list for VS2017 and later to be -- cgit v0.12 From 11ec1b43128c7eebddb93028d2e38c97af884ebb Mon Sep 17 00:00:00 2001 From: Joseph Brill <48932340+jcbrill@users.noreply.github.com> Date: Sun, 19 Mar 2023 16:22:18 -0400 Subject: Fix typographical error in RELEASE.txt [skip ci] --- RELEASE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE.txt b/RELEASE.txt index a73919c..0acf502 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -19,7 +19,7 @@ NEW FUNCTIONALITY - List new features (presumably why a checkpoint is being released) - MSVC: If available, native arm64 tools will be used on arm64 hosts for VS2022. -- MSVC: If necessary, automatically define VSCMD_SKIP_TELEMETRY for VS2019 and later +- MSVC: If necessary, automatically define VSCMD_SKIP_SENDTELEMETRY for VS2019 and later on arm64 hosts when using an arm (32-bit) build of python to prevent a powershell error pop-up window (powershell dll not found). -- cgit v0.12 From db58ed9a3be634a766399435e32456baf66fb970 Mon Sep 17 00:00:00 2001 From: Joseph Brill <48932340+jcbrill@users.noreply.github.com> Date: Mon, 20 Mar 2023 05:55:43 -0400 Subject: Fix typographical error in RELEASE.txt [skip ci] --- RELEASE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE.txt b/RELEASE.txt index 0acf502..43519d7 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -38,7 +38,7 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY executable is verified for VS6 to VS2015 to avoid executing the msvc batch file when the host/target tool is known not to be present. Always check that the msvc compiler executable is found on the msvc script environment path after running the msvc batch - file. The is predominately needed for recent versions of Visual Studio where the msvc + file. This is predominately needed for recent versions of Visual Studio where the msvc batch file exists but an individual msvc toolset may not support the host/target architecture combination. For example, when using VS2022 on arm64, the arm64 native tools are only installed for the 14.3x toolsets. -- cgit v0.12 From 6e69fddde42825e831c0aa282c30424041b5adf8 Mon Sep 17 00:00:00 2001 From: Joseph Brill <48932340+jcbrill@users.noreply.github.com> Date: Fri, 24 Mar 2023 12:08:06 -0400 Subject: Update the host architecture query function in the MSVS test framework. First query the windows registry for the processor architecture and then fallback to the platform machine architecture. The platform.machine() architecture return value for an amd64 build of python (3.6.8) on arm64 is amd64. Update the _ARCH_TO_CANONICAL dictionary from Tool\MSCommon\vc.py. --- testing/framework/TestSConsMSVS.py | 45 ++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/testing/framework/TestSConsMSVS.py b/testing/framework/TestSConsMSVS.py index b001d79..b00af32 100644 --- a/testing/framework/TestSConsMSVS.py +++ b/testing/framework/TestSConsMSVS.py @@ -40,6 +40,10 @@ import sys import platform import traceback from xml.etree import ElementTree +try: + import winreg +except ImportError: + winreg = None import SCons.Errors from TestSCons import * @@ -763,23 +767,42 @@ print("self._msvs_versions =%%s"%%str(SCons.Tool.MSCommon.query_versions())) return result def get_vs_host_arch(self): - """ Returns an MSVS, SDK , and/or MSVS acceptable platform arch. """ + """ Returns an MSVS, SDK, and/or MSVS acceptable platform arch. """ - # Dict to 'canonalize' the arch + # Dict to 'canonicalize' the arch (synchronize with MSCommon\vc.py) _ARCH_TO_CANONICAL = { - "x86": "x86", - "amd64": "amd64", - "i386": "x86", - "emt64": "amd64", - "x86_64": "amd64", - "itanium": "ia64", - "ia64": "ia64", + "amd64" : "amd64", + "emt64" : "amd64", + "i386" : "x86", + "i486" : "x86", + "i586" : "x86", + "i686" : "x86", + "ia64" : "ia64", # deprecated + "itanium" : "ia64", # deprecated + "x86" : "x86", + "x86_64" : "amd64", + "arm" : "arm", + "arm64" : "arm64", + "aarch64" : "arm64", } - host_platform = platform.machine() + host_platform = None + + if winreg: + try: + winkey = winreg.OpenKeyEx( + winreg.HKEY_LOCAL_MACHINE, + r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment' + ) + host_platform, _ = winreg.QueryValueEx(winkey, 'PROCESSOR_ARCHITECTURE') + except OSError: + pass + + if not host_platform: + host_platform = platform.machine() try: - host = _ARCH_TO_CANONICAL[host_platform] + host = _ARCH_TO_CANONICAL[host_platform.lower()] except KeyError as e: # Default to x86 for all other platforms host = 'x86' -- cgit v0.12 From d3d42299c50b1249a71deccc76d89ada335939b7 Mon Sep 17 00:00:00 2001 From: Joseph Brill <48932340+jcbrill@users.noreply.github.com> Date: Fri, 31 Mar 2023 09:09:20 -0400 Subject: Remove placeholders from added text in RELEASE.txt --- RELEASE.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/RELEASE.txt b/RELEASE.txt index dde85e9..a15fa7f 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -16,8 +16,6 @@ Here is a summary of the changes since 4.5.2: NEW FUNCTIONALITY ----------------- -- List new features (presumably why a checkpoint is being released) - - MSVC: If available, native arm64 tools will be used on arm64 hosts for VS2022. - MSVC: If necessary, automatically define VSCMD_SKIP_SENDTELEMETRY for VS2019 and later on arm64 hosts when using an arm (32-bit) build of python to prevent a powershell @@ -48,7 +46,6 @@ FIXES embedded in a sequence, or by itself. The conditional C scanner thus did not always properly apply the defines. The regular C scanner does not use these, so was not affected. [fixes #4193] - - MSVC: The installed msvc list is calculated once and cached. There was an indirect dependency on the target architecture when determining if each version of msvc was installed based on the initial invocation. It was possible that an msvc instance @@ -81,10 +78,6 @@ PACKAGING DOCUMENTATION ------------- -- List any significant changes to the documentation (not individual - typo fixes, even if they're mentioned in src/CHANGES.txt to give - the contributor credit) - - HOST_ARCH: Add arm64 to the valid win32 host architectures. DEVELOPMENT -- cgit v0.12