Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

msvc: fiddle debugs, add flow description #3690

Merged
merged 2 commits into from
Jun 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions SCons/Tool/MSCommon/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
This is the flow of the compiler detection logic:

External to MSCommon:

The Tool init modules, in their exists() routines, call -> msvc_exists(env)

At the moment, those modules are:
SCons/Tool/midl.py
SCons/Tool/mslib.py
SCons/Tool/mslink.py
SCons/Tool/msvc.py
SCons/Tool/msvs.py

env may contain a version request in MSVC_VERSION, but this is not used
in the detection that follows from msvc_exists(), only in the later
batch that starts with a call to msvc_setup_env().

Internal to MSCommon/vc.py:

+ MSCommon/vc.py:msvc_exists:
| vcs = cached_get_installed_vcs(env)
| returns True if vcs > 0
|
+-> MSCommon/vc.py:cached_get_installed_vcs:
| checks global if we've run previously, if so return it
| populate the global from -> get_installed_vcs(env)
|
+-> MSCommon/vc.py:get_installed_vcs:
| loop through "known" versions of msvc, granularity is maj.min
| check for product dir -> find_vc_pdir(env, ver)
|
+-> MSCommon/vc.py:find_vc_pdir:
| From the msvc-version to pdir mapping dict, get reg key base and value
| If value is none -> find_vc_pdir_vswhere(ver, env)
|
+-> MSCommon/vc.py:find_vc_pdir_vswhere:
| From the vc-version to VS-version mapping table get string
| Figure out where vswhere is -> msvc_find_vswhere()
| Use subprocess to call vswhere, return first line of match
/
| else get product directory from registry (<= 14.0)
/
| if we found one -> _check_cl_exists_in_vc_dir(env, pdir, ver)
|
+-> MSCommon/vc.py:_check_cl_exists_in_vc_dir:
| Figure out host/target pair
| if version > 14.0 get specific version by looking in
| pdir + Auxiliary/Build/Microsoft/VCToolsVersion/default.txt
| look for pdir + Tools/MSVC/{specver}/bin/host/target/cl.exe
| if 14.0 or less, "do older stuff"

All of this just got us a yes-no answer on whether /some/ msvc version
exists, but does populate __INSTALLED_VCS_RUN with all of the top-level
versions as noted for get_installed_vcs

Externally:

Once a module's exists() has been called (or, in the case of
clang/clangxx, after the compiler has been detected by other means -
those still expect the rest of the msvc chain but not cl.exe)
the module's generate() function calls -> msvc_setup_env_once(env)

Internally:

+ MSCommon/vc.py:msvc_setup_env_once:
| checks for environment flag MSVC_SETUP_RUN
| if not, -> msvc_setup_env(env) and set flag
|
+-+ MSCommon/vc.py:msvc_setup_env:
| set ver from -> get_default_version(env)
|
+-+ MSCommon/vc.py:get_default_version:
| if no version specified in env.MSVC_VERSION:
| return first entry from -> cached_get_installed_vcs(env)
| else return requested version
/
| get script from MSVC_USE_SCRIPT if set to a filename
| -> script_env(script)
|
+-+ MSCommon/vc.py:script_env:
| return (possibly cached) script variables matching script arg
/
| else -> msvc_find_valid_batch_script(env, version)
|
+-+ MSCommon/vc.py:msvc_find_valid_batch_script:
| Build a list of plausible target values, and loop through
| look for host + target -> find_batch_file(env, ver, host, target)
|
+-+ MSCommon/vc.py:find_batch_file:
| call -> find_vc_pdir (see above)
| use the return to construct a version-biased batfile path, check
/
| if not found, try sdk scripts (unknown if this is still useful)


Problems:
- For VS >= 2017, VS and VS are not 1:1, there can be many VC for one VS
- For vswhere-ready versions, detection does not proceed beyond the
product level ("2019") into individual "features" (individual msvc)
- As documented for MSVC_VERSION, compilers can only be requested if versions
are from the set in _VCVER, so 14.1 but not 14.16 or 14.16.27023
- Information found in the first pass (msvs_exists) isn't really
available anywhere except the cached version list, since we just
return true/false.
- Since msvc_exists chain of calls does not look at version, we
can proceed to compiler setup if *any* msvc was found, even if the
one requested wasn't found.
62 changes: 33 additions & 29 deletions SCons/Tool/MSCommon/vc.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,8 @@ def get_msvc_version_numeric(msvc_version):
return ''.join([x for x in msvc_version if x in string_digits + '.'])

def get_host_target(env):
debug('called')

host_platform = env.get('HOST_ARCH')
debug("HOST_ARCH:" + str(host_platform))
if not host_platform:
host_platform = platform.machine()

Expand All @@ -205,8 +204,7 @@ def get_host_target(env):

# Retain user requested TARGET_ARCH
req_target_platform = env.get('TARGET_ARCH')
debug('req_target_platform:%s' % req_target_platform)

debug("HOST_ARCH:" + str(req_target_platform))
if req_target_platform:
# If user requested a specific platform then only try that one.
target_platform = req_target_platform
Expand Down Expand Up @@ -308,12 +306,17 @@ def msvc_version_to_maj_min(msvc_version):
def is_host_target_supported(host_target, msvc_version):
"""Check if (host, target) pair is supported for a VC version.

: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
Only checks whether a given version *may* support the given
(host, target) pair, not that the toolchain is actually on the machine.

Args:
host_target: canonalized host-target pair, e.g.
("x86", "amd64") for cross compilation from 32- to 64-bit Windows.
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":
Expand All @@ -330,9 +333,7 @@ def is_host_target_supported(host_target, msvc_version):
]]

def msvc_find_vswhere():
"""
Find the location of vswhere
"""
""" Find the location of vswhere """
# For bug 3333: support default location of vswhere for both
# 64 and 32 bit windows installs.
# For bug 3542: also accommodate not being on C: drive.
Expand All @@ -347,14 +348,19 @@ def msvc_find_vswhere():
return vswhere_path

def find_vc_pdir_vswhere(msvc_version, env=None):
"""
Find the MSVC product directory using the vswhere program.
""" Find the MSVC product directory using the vswhere program.

: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
"""
Args:
msvc_version: MSVC version to search for
env: optional to look up VSWHERE variable

Returns:
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:
Expand All @@ -369,7 +375,7 @@ def find_vc_pdir_vswhere(msvc_version, env=None):
if vswhere_path is None:
return None

debug('VSWHERE = %s'%vswhere_path)
debug('VSWHERE: %s' % vswhere_path)
vswhere_cmd = [
vswhere_path,
"-products", "*",
Expand Down Expand Up @@ -414,6 +420,7 @@ def find_vc_pdir(env, msvc_version):
MissingConfiguration: found version but the directory is missing.

Both exceptions inherit from VisualCException.

"""
root = 'Software\\'
try:
Expand Down Expand Up @@ -467,7 +474,7 @@ def find_batch_file(env,msvc_version,host_arch,target_arch):
pdir = find_vc_pdir(env, msvc_version)
if pdir is None:
raise NoVersionFound("No version of Visual Studio found")
debug('find_batch_file() in {}'.format(pdir))
debug('looking in {}'.format(pdir))

# filter out e.g. "Exp" from the version name
msvc_ver_numeric = get_msvc_version_numeric(msvc_version)
Expand Down Expand Up @@ -590,8 +597,7 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version):
return True

elif 14 >= ver_num >= 8:

# Set default value to be -1 as "" which is the value for x86/x86
# 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 host_trgt_dir is None:
Expand Down Expand Up @@ -714,12 +720,9 @@ def script_env(script, args=None):
return cache_data

def get_default_version(env):
debug('called')

msvc_version = env.get('MSVC_VERSION')
msvs_version = env.get('MSVS_VERSION')

debug('msvc_version:%s msvs_version:%s' % (msvc_version,msvs_version))
debug('msvc_version:%s msvs_version:%s' % (msvc_version, msvs_version))

if msvs_version and not msvc_version:
SCons.Warnings.warn(
Expand All @@ -735,6 +738,7 @@ def get_default_version(env):
"visual studio version, MSVS_VERSION is deprecated" \
% (msvc_version, msvs_version))
return msvs_version

if not msvc_version:
installed_vcs = cached_get_installed_vcs(env)
debug('installed_vcs:%s' % installed_vcs)
Expand All @@ -746,6 +750,8 @@ def get_default_version(env):
return None
msvc_version = installed_vcs[0]
debug('using default installed MSVC version %s' % repr(msvc_version))
else:
debug('using specified MSVC version %s' % repr(msvc_version))

return msvc_version

Expand Down Expand Up @@ -879,14 +885,12 @@ def msvc_find_valid_batch_script(env, version):

def msvc_setup_env(env):
debug('called')

version = get_default_version(env)
if version is None:
warn_msg = "No version of Visual Studio compiler found - C/C++ " \
"compilers most likely not set correctly"
SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
return None
debug('using specified MSVC version %s' % repr(version))

# XXX: we set-up both MSVS version for backward
# compatibility with the msvs tool
Expand Down