summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2020-04-23 19:07:36 (GMT)
committerGitHub <noreply@github.com>2020-04-23 19:07:36 (GMT)
commitb235883c0be3ae674634d2ce8b24250732273432 (patch)
treeda16d45e20d97291433d1d2601bd5e9639313fa8 /src
parent21c6da46ed6aff3fc36aae1a7862c984559fcaa1 (diff)
parent7ec2c76c12d1254c2c31a20d15ae5c39540adb3e (diff)
downloadSCons-b235883c0be3ae674634d2ce8b24250732273432.zip
SCons-b235883c0be3ae674634d2ce8b24250732273432.tar.gz
SCons-b235883c0be3ae674634d2ce8b24250732273432.tar.bz2
Merge pull request #3608 from bdbaddog/add_vswhere_variable
Add VSWHERE variable
Diffstat (limited to 'src')
-rwxr-xr-xsrc/CHANGES.txt2
-rw-r--r--src/engine/SCons/Tool/MSCommon/__init__.py3
-rw-r--r--src/engine/SCons/Tool/MSCommon/vc.py70
-rw-r--r--src/engine/SCons/Tool/MSCommon/vcTests.py34
-rw-r--r--src/engine/SCons/Tool/MSCommon/vs.py36
-rw-r--r--src/engine/SCons/Tool/linkloc.py2
-rw-r--r--src/engine/SCons/Tool/msvc.py6
-rw-r--r--src/engine/SCons/Tool/msvc.xml50
-rw-r--r--src/engine/SCons/Tool/msvsTests.py2
9 files changed, 153 insertions, 52 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index c1bf24c..e1b7c00 100755
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -30,6 +30,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
- Add msys2 installed mingw default path to PATH for mingw tool.
- C:\msys64\mingw64\bin
- Purge obsolete internal build and tooling scripts
+ - Allow user specified location for vswhere.exe specified by VSWHERE.
+ NOTE: This must be set at the time the 'msvc' 'msvs' and/or 'mslink' tool(s) are initialized to have any effect.
- Resolve Issue #3451 and Issue #3450 - Rewrite SCons setup.py and packaging. Move script logic to entry points so
package can create scripts which use the correct version of Python.
- Resolve Issue #3248 - Removing '-Wl,-Bsymbolic' from SHLIBVERSIONFLAGS
diff --git a/src/engine/SCons/Tool/MSCommon/__init__.py b/src/engine/SCons/Tool/MSCommon/__init__.py
index c87bf71..be7720a 100644
--- a/src/engine/SCons/Tool/MSCommon/__init__.py
+++ b/src/engine/SCons/Tool/MSCommon/__init__.py
@@ -42,7 +42,8 @@ from SCons.Tool.MSCommon.sdk import mssdk_exists, \
from SCons.Tool.MSCommon.vc import msvc_exists, \
msvc_setup_env, \
msvc_setup_env_once, \
- msvc_version_to_maj_min
+ msvc_version_to_maj_min, \
+ msvc_find_vswhere
from SCons.Tool.MSCommon.vs import get_default_version, \
get_vs_by_version, \
diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py
index 82fb6b9..58be07c 100644
--- a/src/engine/SCons/Tool/MSCommon/vc.py
+++ b/src/engine/SCons/Tool/MSCommon/vc.py
@@ -233,16 +233,16 @@ _VCVER = ["14.2", "14.1", "14.1Exp", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.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)',
+ '14.2': '[16.0, 17.0)',
+ '14.1': '[15.0, 16.0)',
}
_VCVER_TO_PRODUCT_DIR = {
- '14.2' : [
+ '14.2': [
(SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version
- '14.1' : [
+ '14.1': [
(SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version
- '14.1Exp' : [
+ '14.1Exp': [
(SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version
'14.0' : [
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\14.0\Setup\VC\ProductDir')],
@@ -290,6 +290,7 @@ _VCVER_TO_PRODUCT_DIR = {
]
}
+
def msvc_version_to_maj_min(msvc_version):
msvc_version_numeric = get_msvc_version_numeric(msvc_version)
@@ -303,6 +304,7 @@ def msvc_version_to_maj_min(msvc_version):
except ValueError as e:
raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric))
+
def is_host_target_supported(host_target, msvc_version):
"""Check if (host, target) pair is supported for a VC version.
@@ -321,7 +323,30 @@ def is_host_target_supported(host_target, msvc_version):
return True
-def find_vc_pdir_vswhere(msvc_version):
+VSWHERE_PATHS = [os.path.join(p,'vswhere.exe') for p in [
+ os.path.expandvars(r"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer"),
+ os.path.expandvars(r"%ProgramFiles%\Microsoft Visual Studio\Installer"),
+ os.path.expandvars(r"%ChocolateyInstall%\bin"),
+]]
+
+def msvc_find_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.
+ # NB: this gets called from testsuite on non-Windows platforms.
+ # Whether that makes sense or not, don't break it for those.
+ vswhere_path = None
+ for pf in VSWHERE_PATHS:
+ if os.path.exists(pf):
+ vswhere_path = pf
+ break
+
+ return vswhere_path
+
+def find_vc_pdir_vswhere(msvc_version, env=None):
"""
Find the MSVC product directory using the vswhere program.
@@ -336,26 +361,15 @@ def find_vc_pdir_vswhere(msvc_version):
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.
- # For bug 3542: also accommodate not being on C: drive.
- # NB: this gets called from testsuite on non-Windows platforms.
- # Whether that makes sense or not, don't break it for those.
- # TODO: requested to add a user-specified path to vswhere
- # and have this routine set the same var if it finds it.
- pfpaths = [
- os.path.expandvars(r"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer"),
- os.path.expandvars(r"%ProgramFiles%\Microsoft Visual Studio\Installer"),
- os.path.expandvars(r"%ChocolateyInstall%\bin"),
- ]
- for pf in pfpaths:
- vswhere_path = os.path.join(pf, "vswhere.exe")
- if os.path.exists(vswhere_path):
- break
+ if env is None or not env.get('VSWHERE'):
+ vswhere_path = msvc_find_vswhere()
else:
- # No vswhere on system, no install info available this way
+ vswhere_path = env.subst('$VSWHERE')
+
+ if vswhere_path is None:
return None
+ debug('find_vc_pdir_vswhere(): VSWHERE = %s'%vswhere_path)
vswhere_cmd = [
vswhere_path,
"-products", "*",
@@ -363,6 +377,8 @@ def find_vc_pdir_vswhere(msvc_version):
"-property", "installationPath",
]
+ debug("find_vc_pdir_vswhere(): running: %s" % vswhere_cmd)
+
#cp = subprocess.run(vswhere_cmd, capture_output=True) # 3.7+ only
cp = subprocess.run(vswhere_cmd, stdout=PIPE, stderr=PIPE)
@@ -379,7 +395,7 @@ def find_vc_pdir_vswhere(msvc_version):
return None
-def find_vc_pdir(msvc_version):
+def find_vc_pdir(env, msvc_version):
"""Find the MSVC product directory for the given version.
Tries to look up the path using a registry key from the table
@@ -410,7 +426,7 @@ def find_vc_pdir(msvc_version):
try:
comps = None
if not key:
- comps = find_vc_pdir_vswhere(msvc_version)
+ comps = find_vc_pdir_vswhere(msvc_version, env)
if not comps:
debug('find_vc_pdir_vswhere(): no VC found for version {}'.format(repr(msvc_version)))
raise SCons.Util.WinError
@@ -448,7 +464,7 @@ def find_batch_file(env,msvc_version,host_arch,target_arch):
so use that and return an indication we don't need the argument
we would have computed to run vcvarsall.bat.
"""
- pdir = find_vc_pdir(msvc_version)
+ 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))
@@ -633,7 +649,7 @@ def get_installed_vcs(env=None):
for ver in _VCVER:
debug('trying to find VC %s' % ver)
try:
- VC_DIR = find_vc_pdir(ver)
+ VC_DIR = find_vc_pdir(env, ver)
if VC_DIR:
debug('found VC %s' % ver)
if _check_cl_exists_in_vc_dir(env, VC_DIR, ver):
diff --git a/src/engine/SCons/Tool/MSCommon/vcTests.py b/src/engine/SCons/Tool/MSCommon/vcTests.py
index 09991f5..eb09def 100644
--- a/src/engine/SCons/Tool/MSCommon/vcTests.py
+++ b/src/engine/SCons/Tool/MSCommon/vcTests.py
@@ -45,12 +45,42 @@ MSVCUnsupportedTargetArch = SCons.Tool.MSCommon.vc.MSVCUnsupportedTargetArch
MS_TOOLS_VERSION='1.1.1'
+class VswhereTestCase(unittest.TestCase):
+ @staticmethod
+ def _createVSWhere(path):
+ os.makedirs(os.path.dirname(path), exist_ok=True)
+ with open(path, 'w') as f:
+ f.write("Created:%s"%f)
+
+ def testDefaults(self):
+ """
+ Verify that msvc_find_vswhere() find's files in the specified paths
+ """
+ # import pdb; pdb.set_trace()
+ vswhere_dirs = [os.path.splitdrive(p)[1] for p in SCons.Tool.MSCommon.vc.VSWHERE_PATHS]
+ base_dir = test.workpath('fake_vswhere')
+ test_vswhere_dirs = [os.path.join(base_dir,d[1:]) for d in vswhere_dirs]
+
+ SCons.Tool.MSCommon.vc.VSWHERE_PATHS = test_vswhere_dirs
+ for vsw in test_vswhere_dirs:
+ VswhereTestCase._createVSWhere(vsw)
+ find_path = SCons.Tool.MSCommon.vc.msvc_find_vswhere()
+ self.assertTrue(vsw == find_path, "Didn't find vswhere in %s found in %s"%(vsw, find_path))
+ os.remove(vsw)
+
+ # def specifiedVswherePathTest(self):
+ # "Verify that msvc.generate() respects VSWHERE Specified"
+
+
+
+
+
class MSVcTestCase(unittest.TestCase):
@staticmethod
def _createDummyCl(path, add_bin=True):
"""
- Creates a dummy cl.ex in the correct directory.
+ Creates a dummy cl.exe in the correct directory.
It will create all missing parent directories as well
Args:
@@ -74,8 +104,6 @@ class MSVcTestCase(unittest.TestCase):
ct.write('created')
-
-
def runTest(self):
"""
Check that all proper HOST_PLATFORM and TARGET_PLATFORM are handled.
diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py
index e13f52f..e71eb27 100644
--- a/src/engine/SCons/Tool/MSCommon/vs.py
+++ b/src/engine/SCons/Tool/MSCommon/vs.py
@@ -64,22 +64,22 @@ class VisualStudio(object):
return None
return batch_file
- def find_vs_dir_by_vc(self):
- SCons.Tool.MSCommon.vc.get_installed_vcs()
- dir = SCons.Tool.MSCommon.vc.find_vc_pdir(self.vc_version)
+ def find_vs_dir_by_vc(self, env):
+ SCons.Tool.MSCommon.vc.get_installed_vcs(env)
+ dir = SCons.Tool.MSCommon.vc.find_vc_pdir(env, self.vc_version)
if not dir:
debug('find_vs_dir_by_vc(): no installed VC %s' % self.vc_version)
return None
return os.path.abspath(os.path.join(dir, os.pardir))
- def find_vs_dir_by_reg(self):
+ def find_vs_dir_by_reg(self, env):
root = 'Software\\'
if is_win64():
root = root + 'Wow6432Node\\'
for key in self.hkeys:
if key=='use_dir':
- return self.find_vs_dir_by_vc()
+ return self.find_vs_dir_by_vc(env)
key = root + key
try:
comps = read_reg(key)
@@ -90,19 +90,19 @@ class VisualStudio(object):
return comps
return None
- def find_vs_dir(self):
+ def find_vs_dir(self, env):
""" Can use registry or location of VC to find vs dir
First try to find by registry, and if that fails find via VC dir
"""
- vs_dir=self.find_vs_dir_by_reg()
+ vs_dir=self.find_vs_dir_by_reg(env)
if not vs_dir:
- vs_dir = self.find_vs_dir_by_vc()
+ vs_dir = self.find_vs_dir_by_vc(env)
debug('find_vs_dir(): found VS in ' + str(vs_dir ))
return vs_dir
- def find_executable(self):
- vs_dir = self.get_vs_dir()
+ def find_executable(self, env):
+ vs_dir = self.get_vs_dir(env)
if not vs_dir:
debug('find_executable(): no vs_dir ({})'.format(vs_dir))
return None
@@ -121,21 +121,21 @@ class VisualStudio(object):
self._cache['batch_file'] = batch_file
return batch_file
- def get_executable(self):
+ def get_executable(self, env=None):
try:
debug('get_executable using cache:%s'%self._cache['executable'])
return self._cache['executable']
except KeyError:
- executable = self.find_executable()
+ executable = self.find_executable(env)
self._cache['executable'] = executable
debug('get_executable not in cache:%s'%executable)
return executable
- def get_vs_dir(self):
+ def get_vs_dir(self, env):
try:
return self._cache['vs_dir']
except KeyError:
- vs_dir = self.find_vs_dir()
+ vs_dir = self.find_vs_dir(env)
self._cache['vs_dir'] = vs_dir
return vs_dir
@@ -413,7 +413,7 @@ for vs in SupportedVSList:
InstalledVSList = None
InstalledVSMap = None
-def get_installed_visual_studios():
+def get_installed_visual_studios(env=None):
global InstalledVSList
global InstalledVSMap
if InstalledVSList is None:
@@ -421,7 +421,7 @@ def get_installed_visual_studios():
InstalledVSMap = {}
for vs in SupportedVSList:
debug('trying to find VS %s' % vs.version)
- if vs.get_executable():
+ if vs.get_executable(env):
debug('found VS %s' % vs.version)
InstalledVSList.append(vs)
InstalledVSMap[vs.version] = vs
@@ -472,8 +472,8 @@ def reset_installed_visual_studios():
# for variable, directory in env_tuple_list:
# env.PrependENVPath(variable, directory)
-def msvs_exists():
- return (len(get_installed_visual_studios()) > 0)
+def msvs_exists(env=None):
+ return (len(get_installed_visual_studios(env)) > 0)
def get_vs_by_version(msvs):
global InstalledVSMap
diff --git a/src/engine/SCons/Tool/linkloc.py b/src/engine/SCons/Tool/linkloc.py
index c73852b..ad189b2 100644
--- a/src/engine/SCons/Tool/linkloc.py
+++ b/src/engine/SCons/Tool/linkloc.py
@@ -101,7 +101,7 @@ def generate(env):
addPharLapPaths(env)
def exists(env):
- if msvs_exists():
+ if msvs_exists(env):
return env.Detect('linkloc')
else:
return 0
diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py
index 65c0e91..463e372 100644
--- a/src/engine/SCons/Tool/msvc.py
+++ b/src/engine/SCons/Tool/msvc.py
@@ -48,7 +48,7 @@ import SCons.Util
import SCons.Warnings
import SCons.Scanner.RC
-from .MSCommon import msvc_exists, msvc_setup_env_once, msvc_version_to_maj_min
+from .MSCommon import msvc_exists, msvc_setup_env_once, msvc_version_to_maj_min, msvc_find_vswhere
CSuffixes = ['.c', '.C']
CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
@@ -214,6 +214,7 @@ ShCXXAction = SCons.Action.Action("$SHCXXCOM", "$SHCXXCOMSTR",
batch_key=msvc_batch_key,
targets='$CHANGED_TARGETS')
+
def generate(env):
"""Add Builders and construction variables for MSVC++ to an Environment."""
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
@@ -276,6 +277,9 @@ def generate(env):
# without it for lex generation
env["LEXUNISTD"] = SCons.Util.CLVar("--nounistd")
+ # Get user specified vswhere location or locate.
+ env['VSWHERE'] = env.get('VSWHERE', msvc_find_vswhere())
+
# Set-up ms tools paths
msvc_setup_env_once(env)
diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml
index 100c84c..e92fa9b 100644
--- a/src/engine/SCons/Tool/msvc.xml
+++ b/src/engine/SCons/Tool/msvc.xml
@@ -475,4 +475,54 @@ Valid values are '1' or '0'
</summary>
</cvar>
+<cvar name="VSWHERE">
+<summary>
+<para>
+Specify the location of <filename>vswhere.exe</filename>.
+</para>
+
+<para>
+ The <filename>vswhere.exe</filename> executable is distributed with Microsoft Visual Studio and Build
+ Tools since the 2017 edition, but is also available standalone.
+ It provides full information about installations of 2017 and later editions.
+ With the <option>-legacy</option> argument, <filename>vswhere.exe</filename> can detect installations of the 2010 through 2015
+ editions with limited data returned.
+If <envar>VSWHERE</envar> is set, SCons will use that location.
+</para>
+<para>
+ Otherwise SCons will look in the following locations and set <envar>VSWHERE</envar> to the path of the first <filename>vswhere.exe</filename>
+located.
+</para>
+
+<itemizedlist>
+<listitem><para><literal>%ProgramFiles(x86)%\Microsoft Visual Studio\Installer</literal></para></listitem>
+<listitem><para><literal>%ProgramFiles%\Microsoft Visual Studio\Installer</literal></para></listitem>
+<listitem><para><literal>%ChocolateyInstall%\bin</literal></para></listitem>
+</itemizedlist>
+
+<para>
+ Note that <envar>VSWHERE</envar> must be set at the same time or prior to any of &t-link-msvc;, &t-link-msvs; , and/or &t-link-mslink; &f-link-Tool; being initialized.
+
+ Either set it as follows
+<programlisting>
+env = Environment(VSWHERE='c:/my/path/to/vswhere')
+</programlisting>
+
+or if your &consenv; is created specifying an empty tools list
+(or a list of tools which omits all of default, msvs, msvc, and mslink),
+and also before &f-link-env-Tool; is called to ininitialize any of those tools:
+
+<programlisting>
+ env = Environment(tools=[])
+ env['VSWHERE'] = r'c:/my/vswhere/install/location/vswhere.exe'
+ env.Tool('msvc')
+ env.Tool('mslink')
+ env.Tool('msvs')
+ </programlisting>
+</para>
+
+</summary>
+</cvar>
+
+
</sconsdoc>
diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py
index b3373ea..1bacc2c 100644
--- a/src/engine/SCons/Tool/msvsTests.py
+++ b/src/engine/SCons/Tool/msvsTests.py
@@ -580,7 +580,7 @@ def DummyQueryValue(key, value):
def DummyExists(path):
return 1
-def DummyVsWhere(msvc_version):
+def DummyVsWhere(msvc_version, env):
# not testing versions with vswhere, so return none
return None