diff options
author | William Deegan <bill@baddogconsulting.com> | 2020-04-10 22:21:04 (GMT) |
---|---|---|
committer | William Deegan <bill@baddogconsulting.com> | 2020-04-10 22:21:04 (GMT) |
commit | 91b699c9e13a94d37bd6467930874672eff4c5b1 (patch) | |
tree | c11bd5bcde2925f137cb261b033c19c1f8927854 /src/engine/SCons/Tool | |
parent | 23fd1a45db2d57767dcbb50c151295dc93975181 (diff) | |
download | SCons-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__.py | 3 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/vc.py | 57 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/vcTests.py | 35 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/vs.py | 36 | ||||
-rw-r--r-- | src/engine/SCons/Tool/linkloc.py | 2 | ||||
-rw-r--r-- | src/engine/SCons/Tool/msvc.py | 5 | ||||
-rw-r--r-- | src/engine/SCons/Tool/msvc.xml | 34 | ||||
-rw-r--r-- | src/engine/SCons/Tool/msvsTests.py | 2 |
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 |