summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Tool
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2020-04-10 22:21:04 (GMT)
committerWilliam Deegan <bill@baddogconsulting.com>2020-04-10 22:21:04 (GMT)
commit91b699c9e13a94d37bd6467930874672eff4c5b1 (patch)
treec11bd5bcde2925f137cb261b033c19c1f8927854 /src/engine/SCons/Tool
parent23fd1a45db2d57767dcbb50c151295dc93975181 (diff)
downloadSCons-91b699c9e13a94d37bd6467930874672eff4c5b1.zip
SCons-91b699c9e13a94d37bd6467930874672eff4c5b1.tar.gz
SCons-91b699c9e13a94d37bd6467930874672eff4c5b1.tar.bz2
Resolve issue #3605. Allow specifying VSWHERE to environment
Diffstat (limited to 'src/engine/SCons/Tool')
-rw-r--r--src/engine/SCons/Tool/MSCommon/__init__.py3
-rw-r--r--src/engine/SCons/Tool/MSCommon/vc.py57
-rw-r--r--src/engine/SCons/Tool/MSCommon/vcTests.py35
-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.py5
-rw-r--r--src/engine/SCons/Tool/msvc.xml34
-rw-r--r--src/engine/SCons/Tool/msvsTests.py2
8 files changed, 126 insertions, 48 deletions
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 f5a410f..ce1341d 100644
--- a/src/engine/SCons/Tool/MSCommon/vc.py
+++ b/src/engine/SCons/Tool/MSCommon/vc.py
@@ -323,7 +323,32 @@ 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.
+ # TODO: requested to add a user-specified path to vswhere
+ # and have this routine set the same var if it finds it.
+ 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.
@@ -338,26 +363,12 @@ 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
- return None
+ vswhere_path = env.subst('$VSWHERE')
+ debug('find_vc_pdir_vswhere(): VSWHERE = %s'%vswhere_path)
vswhere_cmd = [
vswhere_path,
"-products", "*",
@@ -381,7 +392,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
@@ -412,7 +423,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
@@ -450,7 +461,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))
@@ -635,7 +646,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..f5f7a44 100644
--- a/src/engine/SCons/Tool/MSCommon/vcTests.py
+++ b/src/engine/SCons/Tool/MSCommon/vcTests.py
@@ -24,6 +24,7 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import sys
import os
import os.path
import unittest
@@ -45,12 +46,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))
+ 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 +105,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 05a20e0..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++']
@@ -277,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..bdbf253 100644
--- a/src/engine/SCons/Tool/msvc.xml
+++ b/src/engine/SCons/Tool/msvc.xml
@@ -475,4 +475,38 @@ Valid values are '1' or '0'
</summary>
</cvar>
+<cvar name="VSWHERE">
+<summary>
+<para>
+Specify the location of vswhere.exe.
+</para>
+
+<para>
+<literal>vswhere.exe</literal> is used to locate MSVC/MSVS installations.
+It was initially distributed with MSVS 2017. But can detect MSVC 2010 and newer with <literal>-legacy</literal> argument.
+If &cv-VSWHERE; is set, SCons will use that location.
+</para>
+<para>
+Otherwise SCons will look in the following locations and set VSWHERE to the PATH <literal>vswhere.exe</literal>
+is located.
+</para>
+<para>
+Note that &cv-VSWHERE; must be set in when tool msvc is initialized. This is either in the call to
+<literal>Environment(VSWHERE='c:/my/path/to/vswhere')</literal> or
+if Environment created specifying not to automatically initialize any tools or tools which doesn't include msvc or MSVS
+such as <literal>Environment(Tools=[])</literal>
+</para>
+
+
+
+<itemizedlist>
+<listitem><literal>%ProgramFiles(x86)%\Microsoft Visual Studio\Installer</literal></listitem>
+<listitem><literal>"%ProgramFiles%\Microsoft Visual Studio\Installer</literal></listitem>
+<listitem><literal>%ChocolateyInstall%\bin</literal></listitem>
+</itemizedlist>
+
+</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