Skip to content

Commit ab8a9c5

Browse files
authored
Merge pull request #3690 from mwichmann/msvc-notes
msvc: fiddle debugs, add flow description
2 parents 4285ba4 + a22ee64 commit ab8a9c5

File tree

2 files changed

+140
-29
lines changed

2 files changed

+140
-29
lines changed

SCons/Tool/MSCommon/README

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
This is the flow of the compiler detection logic:
2+
3+
External to MSCommon:
4+
5+
The Tool init modules, in their exists() routines, call -> msvc_exists(env)
6+
7+
At the moment, those modules are:
8+
SCons/Tool/midl.py
9+
SCons/Tool/mslib.py
10+
SCons/Tool/mslink.py
11+
SCons/Tool/msvc.py
12+
SCons/Tool/msvs.py
13+
14+
env may contain a version request in MSVC_VERSION, but this is not used
15+
in the detection that follows from msvc_exists(), only in the later
16+
batch that starts with a call to msvc_setup_env().
17+
18+
Internal to MSCommon/vc.py:
19+
20+
+ MSCommon/vc.py:msvc_exists:
21+
| vcs = cached_get_installed_vcs(env)
22+
| returns True if vcs > 0
23+
|
24+
+-> MSCommon/vc.py:cached_get_installed_vcs:
25+
| checks global if we've run previously, if so return it
26+
| populate the global from -> get_installed_vcs(env)
27+
|
28+
+-> MSCommon/vc.py:get_installed_vcs:
29+
| loop through "known" versions of msvc, granularity is maj.min
30+
| check for product dir -> find_vc_pdir(env, ver)
31+
|
32+
+-> MSCommon/vc.py:find_vc_pdir:
33+
| From the msvc-version to pdir mapping dict, get reg key base and value
34+
| If value is none -> find_vc_pdir_vswhere(ver, env)
35+
|
36+
+-> MSCommon/vc.py:find_vc_pdir_vswhere:
37+
| From the vc-version to VS-version mapping table get string
38+
| Figure out where vswhere is -> msvc_find_vswhere()
39+
| Use subprocess to call vswhere, return first line of match
40+
/
41+
| else get product directory from registry (<= 14.0)
42+
/
43+
| if we found one -> _check_cl_exists_in_vc_dir(env, pdir, ver)
44+
|
45+
+-> MSCommon/vc.py:_check_cl_exists_in_vc_dir:
46+
| Figure out host/target pair
47+
| if version > 14.0 get specific version by looking in
48+
| pdir + Auxiliary/Build/Microsoft/VCToolsVersion/default.txt
49+
| look for pdir + Tools/MSVC/{specver}/bin/host/target/cl.exe
50+
| if 14.0 or less, "do older stuff"
51+
52+
All of this just got us a yes-no answer on whether /some/ msvc version
53+
exists, but does populate __INSTALLED_VCS_RUN with all of the top-level
54+
versions as noted for get_installed_vcs
55+
56+
Externally:
57+
58+
Once a module's exists() has been called (or, in the case of
59+
clang/clangxx, after the compiler has been detected by other means -
60+
those still expect the rest of the msvc chain but not cl.exe)
61+
the module's generate() function calls -> msvc_setup_env_once(env)
62+
63+
Internally:
64+
65+
+ MSCommon/vc.py:msvc_setup_env_once:
66+
| checks for environment flag MSVC_SETUP_RUN
67+
| if not, -> msvc_setup_env(env) and set flag
68+
|
69+
+-+ MSCommon/vc.py:msvc_setup_env:
70+
| set ver from -> get_default_version(env)
71+
|
72+
+-+ MSCommon/vc.py:get_default_version:
73+
| if no version specified in env.MSVC_VERSION:
74+
| return first entry from -> cached_get_installed_vcs(env)
75+
| else return requested version
76+
/
77+
| get script from MSVC_USE_SCRIPT if set to a filename
78+
| -> script_env(script)
79+
|
80+
+-+ MSCommon/vc.py:script_env:
81+
| return (possibly cached) script variables matching script arg
82+
/
83+
| else -> msvc_find_valid_batch_script(env, version)
84+
|
85+
+-+ MSCommon/vc.py:msvc_find_valid_batch_script:
86+
| Build a list of plausible target values, and loop through
87+
| look for host + target -> find_batch_file(env, ver, host, target)
88+
|
89+
+-+ MSCommon/vc.py:find_batch_file:
90+
| call -> find_vc_pdir (see above)
91+
| use the return to construct a version-biased batfile path, check
92+
/
93+
| if not found, try sdk scripts (unknown if this is still useful)
94+
95+
96+
Problems:
97+
- For VS >= 2017, VS and VS are not 1:1, there can be many VC for one VS
98+
- For vswhere-ready versions, detection does not proceed beyond the
99+
product level ("2019") into individual "features" (individual msvc)
100+
- As documented for MSVC_VERSION, compilers can only be requested if versions
101+
are from the set in _VCVER, so 14.1 but not 14.16 or 14.16.27023
102+
- Information found in the first pass (msvs_exists) isn't really
103+
available anywhere except the cached version list, since we just
104+
return true/false.
105+
- Since msvc_exists chain of calls does not look at version, we
106+
can proceed to compiler setup if *any* msvc was found, even if the
107+
one requested wasn't found.

SCons/Tool/MSCommon/vc.py

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,8 @@ def get_msvc_version_numeric(msvc_version):
190190
return ''.join([x for x in msvc_version if x in string_digits + '.'])
191191

192192
def get_host_target(env):
193-
debug('called')
194-
195193
host_platform = env.get('HOST_ARCH')
194+
debug("HOST_ARCH:" + str(host_platform))
196195
if not host_platform:
197196
host_platform = platform.machine()
198197

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

206205
# Retain user requested TARGET_ARCH
207206
req_target_platform = env.get('TARGET_ARCH')
208-
debug('req_target_platform:%s' % req_target_platform)
209-
207+
debug("HOST_ARCH:" + str(req_target_platform))
210208
if req_target_platform:
211209
# If user requested a specific platform then only try that one.
212210
target_platform = req_target_platform
@@ -308,12 +306,17 @@ def msvc_version_to_maj_min(msvc_version):
308306
def is_host_target_supported(host_target, msvc_version):
309307
"""Check if (host, target) pair is supported for a VC version.
310308
311-
:note: only checks whether a given version *may* support the given (host,
312-
target), not that the toolchain is actually present on the machine.
313-
:param tuple host_target: canonalized host-targets pair, e.g.
314-
("x86", "amd64") for cross compilation from 32 bit Windows to 64 bits.
315-
:param str msvc_version: Visual C++ version (major.minor), e.g. "10.0"
316-
:returns: True or False
309+
Only checks whether a given version *may* support the given
310+
(host, target) pair, not that the toolchain is actually on the machine.
311+
312+
Args:
313+
host_target: canonalized host-target pair, e.g.
314+
("x86", "amd64") for cross compilation from 32- to 64-bit Windows.
315+
msvc_version: Visual C++ version (major.minor), e.g. "10.0"
316+
317+
Returns:
318+
True or False
319+
317320
"""
318321
# We assume that any Visual Studio version supports x86 as a target
319322
if host_target[1] != "x86":
@@ -330,9 +333,7 @@ def is_host_target_supported(host_target, msvc_version):
330333
]]
331334

332335
def msvc_find_vswhere():
333-
"""
334-
Find the location of vswhere
335-
"""
336+
""" Find the location of vswhere """
336337
# For bug 3333: support default location of vswhere for both
337338
# 64 and 32 bit windows installs.
338339
# For bug 3542: also accommodate not being on C: drive.
@@ -347,14 +348,19 @@ def msvc_find_vswhere():
347348
return vswhere_path
348349

349350
def find_vc_pdir_vswhere(msvc_version, env=None):
350-
"""
351-
Find the MSVC product directory using the vswhere program.
351+
""" Find the MSVC product directory using the vswhere program.
352352
353-
:param msvc_version: MSVC version to search for
354-
:return: MSVC install dir or None
355-
:raises UnsupportedVersion: if the version is not known by this file
356-
"""
353+
Args:
354+
msvc_version: MSVC version to search for
355+
env: optional to look up VSWHERE variable
357356
357+
Returns:
358+
MSVC install dir or None
359+
360+
Raises:
361+
UnsupportedVersion: if the version is not known by this file
362+
363+
"""
358364
try:
359365
vswhere_version = _VCVER_TO_VSWHERE_VER[msvc_version]
360366
except KeyError:
@@ -369,7 +375,7 @@ def find_vc_pdir_vswhere(msvc_version, env=None):
369375
if vswhere_path is None:
370376
return None
371377

372-
debug('VSWHERE = %s'%vswhere_path)
378+
debug('VSWHERE: %s' % vswhere_path)
373379
vswhere_cmd = [
374380
vswhere_path,
375381
"-products", "*",
@@ -414,6 +420,7 @@ def find_vc_pdir(env, msvc_version):
414420
MissingConfiguration: found version but the directory is missing.
415421
416422
Both exceptions inherit from VisualCException.
423+
417424
"""
418425
root = 'Software\\'
419426
try:
@@ -467,7 +474,7 @@ def find_batch_file(env,msvc_version,host_arch,target_arch):
467474
pdir = find_vc_pdir(env, msvc_version)
468475
if pdir is None:
469476
raise NoVersionFound("No version of Visual Studio found")
470-
debug('find_batch_file() in {}'.format(pdir))
477+
debug('looking in {}'.format(pdir))
471478

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

592599
elif 14 >= ver_num >= 8:
593-
594-
# Set default value to be -1 as "" which is the value for x86/x86
600+
# Set default value to be -1 as "", which is the value for x86/x86,
595601
# yields true when tested if not host_trgt_dir
596602
host_trgt_dir = _HOST_TARGET_TO_CL_DIR.get((host_platform, target_platform), None)
597603
if host_trgt_dir is None:
@@ -714,12 +720,9 @@ def script_env(script, args=None):
714720
return cache_data
715721

716722
def get_default_version(env):
717-
debug('called')
718-
719723
msvc_version = env.get('MSVC_VERSION')
720724
msvs_version = env.get('MSVS_VERSION')
721-
722-
debug('msvc_version:%s msvs_version:%s' % (msvc_version,msvs_version))
725+
debug('msvc_version:%s msvs_version:%s' % (msvc_version, msvs_version))
723726

724727
if msvs_version and not msvc_version:
725728
SCons.Warnings.warn(
@@ -735,6 +738,7 @@ def get_default_version(env):
735738
"visual studio version, MSVS_VERSION is deprecated" \
736739
% (msvc_version, msvs_version))
737740
return msvs_version
741+
738742
if not msvc_version:
739743
installed_vcs = cached_get_installed_vcs(env)
740744
debug('installed_vcs:%s' % installed_vcs)
@@ -746,6 +750,8 @@ def get_default_version(env):
746750
return None
747751
msvc_version = installed_vcs[0]
748752
debug('using default installed MSVC version %s' % repr(msvc_version))
753+
else:
754+
debug('using specified MSVC version %s' % repr(msvc_version))
749755

750756
return msvc_version
751757

@@ -879,14 +885,12 @@ def msvc_find_valid_batch_script(env, version):
879885

880886
def msvc_setup_env(env):
881887
debug('called')
882-
883888
version = get_default_version(env)
884889
if version is None:
885890
warn_msg = "No version of Visual Studio compiler found - C/C++ " \
886891
"compilers most likely not set correctly"
887892
SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
888893
return None
889-
debug('using specified MSVC version %s' % repr(version))
890894

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

0 commit comments

Comments
 (0)