diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2019-07-23 16:55:05 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2019-07-23 16:55:05 +0200 |
commit | d240a76169c685e488fe7352adec69d39c60ef9f (patch) | |
tree | 144aeb4702d258b0cfaf99cffb9f21e94b026459 /src/engine/SCons/Tool/MSCommon/vc.py | |
parent | 6ca68f29862bc7cbe5428426eee600cb1f3c05c1 (diff) | |
parent | c2d9eaeffe9d77d8d5087fb21a3256fde32047d4 (diff) |
Merge branch 'feature/upstream' into develop
Diffstat (limited to 'src/engine/SCons/Tool/MSCommon/vc.py')
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/vc.py | 145 |
1 files changed, 84 insertions, 61 deletions
diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 5de85d6..fa7be96 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -30,7 +30,7 @@ # * test on 64 bits XP + VS 2005 (and VS 6 if possible) # * SDK # * Assembly -__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" __doc__ = """Module for Visual C/C++ detection and configuration. """ @@ -60,7 +60,10 @@ class VisualCException(Exception): class UnsupportedVersion(VisualCException): pass -class UnsupportedArch(VisualCException): +class MSVCUnsupportedHostArch(VisualCException): + pass + +class MSVCUnsupportedTargetArch(VisualCException): pass class MissingConfiguration(VisualCException): @@ -89,17 +92,15 @@ _ARCH_TO_CANONICAL = { "aarch64" : "arm64", } -# get path to the cl.exe dir for newer VS versions -# based off a tuple of (host, target) platforms _HOST_TARGET_TO_CL_DIR_GREATER_THAN_14 = { - ("amd64","amd64") : "Hostx64\\x64", - ("amd64","x86") : "Hostx64\\x86", - ("amd64","arm") : "Hostx64\\arm", - ("amd64","arm64") : "Hostx64\\arm64", - ("x86","amd64") : "Hostx86\\x64", - ("x86","x86") : "Hostx86\\x86", - ("x86","arm") : "Hostx86\\arm", - ("x86","arm64") : "Hostx86\\arm64", + ("amd64","amd64") : ("Hostx64","x64"), + ("amd64","x86") : ("Hostx64","x86"), + ("amd64","arm") : ("Hostx64","arm"), + ("amd64","arm64") : ("Hostx64","arm64"), + ("x86","amd64") : ("Hostx86","x64"), + ("x86","x86") : ("Hostx86","x86"), + ("x86","arm") : ("Hostx86","arm"), + ("x86","arm64") : ("Hostx86","arm64"), } # get path to the cl.exe dir for older VS versions @@ -174,25 +175,33 @@ def get_host_target(env): try: host = _ARCH_TO_CANONICAL[host_platform.lower()] - except KeyError as e: + except KeyError: msg = "Unrecognized host architecture %s" - raise ValueError(msg % repr(host_platform)) + raise MSVCUnsupportedHostArch(msg % repr(host_platform)) try: target = _ARCH_TO_CANONICAL[target_platform.lower()] - except KeyError as e: + except KeyError: all_archs = str(list(_ARCH_TO_CANONICAL.keys())) - raise ValueError("Unrecognized target architecture %s\n\tValid architectures: %s" % (target_platform, all_archs)) + raise MSVCUnsupportedTargetArch("Unrecognized target architecture %s\n\tValid architectures: %s" % (target_platform, all_archs)) return (host, target,req_target_platform) # If you update this, update SupportedVSList in Tool/MSCommon/vs.py, and the # MSVC_VERSION documentation in Tool/msvc.xml. -_VCVER = ["14.1", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"] +_VCVER = ["14.2", "14.1", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"] + +# if using vswhere, a further mapping is needed +_VCVER_TO_VSWHERE_VER = { + '14.2' : '[16.0, 17.0)', + '14.1' : '[15.0, 16.0)', +} _VCVER_TO_PRODUCT_DIR = { + '14.2' : [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # VS 2019 doesn't set this key '14.1' : [ - (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # Visual Studio 2017 doesn't set this registry key anymore + (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # VS 2017 doesn't set this key '14.0' : [ (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\14.0\Setup\VC\ProductDir')], '14.0Exp' : [ @@ -253,42 +262,40 @@ def msvc_version_to_maj_min(msvc_version): raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) def is_host_target_supported(host_target, msvc_version): - """Check if the given (host, target) tuple is supported for given version. + """Check if (host, target) pair is supported for a VC version. - Args: - host_target: tuple - tuple of (canonalized) host-targets, e.g. ("x86", "amd64") - for cross compilation from 32 bit Windows to 64 bits. - msvc_version: str - msvc version (major.minor, e.g. 10.0) - - Returns: - bool: - - Note: - This only checks whether a given version *may* support the given (host, + :note: only checks whether a given version *may* support the given (host, target), not that the toolchain is actually present on the machine. + :param tuple host_target: canonalized host-targets pair, e.g. + ("x86", "amd64") for cross compilation from 32 bit Windows to 64 bits. + :param str msvc_version: Visual C++ version (major.minor), e.g. "10.0" + :returns: True or False """ # We assume that any Visual Studio version supports x86 as a target if host_target[1] != "x86": maj, min = msvc_version_to_maj_min(msvc_version) if maj < 8: return False - return True def find_vc_pdir_vswhere(msvc_version): """ - Find the MSVC product directory using vswhere.exe. + Find the MSVC product directory using the vswhere program. - Run it asking for specified version and get MSVS install location - :param msvc_version: + :param msvc_version: MSVC version to search for :return: MSVC install dir or None + :raises UnsupportedVersion: if the version is not known by this file """ + try: + vswhere_version = _VCVER_TO_VSWHERE_VER[msvc_version] + except KeyError: + debug("Unknown version of MSVC: %s" % msvc_version) + raise UnsupportedVersion("Unknown version %s" % msvc_version) + # For bug 3333 - support default location of vswhere for both 64 and 32 bit windows - # installs. + # installs. for pf in ['Program Files (x86)', 'Program Files']: vswhere_path = os.path.join( 'C:\\', @@ -300,31 +307,36 @@ def find_vc_pdir_vswhere(msvc_version): if os.path.exists(vswhere_path): # If we found vswhere, then use it. break + else: + # No vswhere on system, no install info available + return None - vswhere_cmd = [vswhere_path, '-products', '*', '-version', msvc_version, '-property', 'installationPath'] - - if os.path.exists(vswhere_path): - #TODO PY27 cannot use Popen as context manager - # try putting it back to the old way for now - sp = subprocess.Popen(vswhere_cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - vsdir, err = sp.communicate() - if vsdir: - vsdir = vsdir.decode("mbcs").splitlines() - # vswhere could easily return multiple lines - # we could define a way to pick the one we prefer, but since - # this data is currently only used to make a check for existence, - # returning the first hit should be good enough for now. - vc_pdir = os.path.join(vsdir[0], 'VC') - return vc_pdir + vswhere_cmd = [vswhere_path, + '-products', '*', + '-version', vswhere_version, + '-property', 'installationPath'] + + #TODO PY27 cannot use Popen as context manager + # try putting it back to the old way for now + sp = subprocess.Popen(vswhere_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + vsdir, err = sp.communicate() + if vsdir: + vsdir = vsdir.decode("mbcs").splitlines() + # vswhere could easily return multiple lines + # we could define a way to pick the one we prefer, but since + # this data is currently only used to make a check for existence, + # returning the first hit should be good enough for now. + vc_pdir = os.path.join(vsdir[0], 'VC') + return vc_pdir else: # No vswhere on system, no install info available return None def find_vc_pdir(msvc_version): - """Find the product directory for the given version. + """Find the MSVC product directory for the given version. Tries to look up the path using a registry key from the table _VCVER_TO_PRODUCT_DIR; if there is no key, calls find_vc_pdir_wshere @@ -425,6 +437,8 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): __INSTALLED_VCS_RUN = None +_VC_TOOLS_VERSION_FILE_PATH = ['Auxiliary', 'Build', 'Microsoft.VCToolsVersion.default.txt'] +_VC_TOOLS_VERSION_FILE = os.sep.join(_VC_TOOLS_VERSION_FILE_PATH) def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): """Find the cl.exe on the filesystem in the vc_dir depending on @@ -459,7 +473,7 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): host_platform = _ARCH_TO_CANONICAL[host_platform] target_platform = _ARCH_TO_CANONICAL[target_platform] - debug('_check_cl_exists_in_vc_dir(): host platform %s, target platform %s' % (host_platform, target_platform)) + debug('_check_cl_exists_in_vc_dir(): host platform %s, target platform %s for version %s' % (host_platform, target_platform, msvc_version)) ver_num = float(get_msvc_version_numeric(msvc_version)) @@ -468,7 +482,7 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): # 2017 and newer allowed multiple versions of the VC toolset to be installed at the same time. # Just get the default tool version for now #TODO: support setting a specific minor VC version - default_toolset_file = os.path.join(vc_dir, r'Auxiliary\Build\Microsoft.VCToolsVersion.default.txt') + default_toolset_file = os.path.join(vc_dir, _VC_TOOLS_VERSION_FILE) try: with open(default_toolset_file) as f: vc_specific_version = f.readlines()[0].strip() @@ -480,11 +494,11 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): return False host_trgt_dir = _HOST_TARGET_TO_CL_DIR_GREATER_THAN_14.get((host_platform, target_platform), None) - if not host_trgt_dir: - debug('_check_cl_exists_in_vc_dir(): unsupported host/target platform combo') + if host_trgt_dir is None: + debug('_check_cl_exists_in_vc_dir(): unsupported host/target platform combo: (%s,%s)'%(host_platform, target_platform)) return False - cl_path = os.path.join(vc_dir, r'Tools\MSVC', vc_specific_version, 'bin', host_trgt_dir, _CL_EXE_NAME) + cl_path = os.path.join(vc_dir, 'Tools','MSVC', vc_specific_version, 'bin', host_trgt_dir[0], host_trgt_dir[1], _CL_EXE_NAME) debug('_check_cl_exists_in_vc_dir(): checking for ' + _CL_EXE_NAME + ' at ' + cl_path) if os.path.exists(cl_path): debug('_check_cl_exists_in_vc_dir(): found ' + _CL_EXE_NAME + '!') @@ -492,8 +506,10 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): elif ver_num <= 14 and ver_num >= 8: + # Set default value to be -1 as "" which is the value for x86/x86 yields true when tested + # if not host_trgt_dir host_trgt_dir = _HOST_TARGET_TO_CL_DIR.get((host_platform, target_platform), None) - if not host_trgt_dir: + if host_trgt_dir is None: debug('_check_cl_exists_in_vc_dir(): unsupported host/target platform combo') return False @@ -505,8 +521,11 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): # older versions of visual studio only had x86 binaries, # so if the host platform is amd64, we need to check cross # compile options (x86 binary compiles some other target on a 64 bit os) + + # Set default value to be -1 as "" which is the value for x86/x86 yields true when tested + # if not host_trgt_dir host_trgt_dir = _HOST_TARGET_TO_CL_DIR.get(('x86', target_platform), None) - if not host_trgt_dir: + if host_trgt_dir is None: return False cl_path = os.path.join(vc_dir, 'bin', host_trgt_dir, _CL_EXE_NAME) @@ -554,6 +573,10 @@ def get_installed_vcs(env=None): debug('find_vc_pdir no compiler found %s' % ver) else: debug('find_vc_pdir return None for ver %s' % ver) + except (MSVCUnsupportedTargetArch, MSVCUnsupportedHostArch): + # Allow this exception to propagate further as it should cause + # SCons to exit with an error code + raise except VisualCException as e: debug('did not find VC %s: caught exception %s' % (ver, str(e))) return installed_versions |