diff options
author | William Deegan <bill@baddogconsulting.com> | 2020-04-23 19:07:36 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-23 19:07:36 (GMT) |
commit | b235883c0be3ae674634d2ce8b24250732273432 (patch) | |
tree | da16d45e20d97291433d1d2601bd5e9639313fa8 /src | |
parent | 21c6da46ed6aff3fc36aae1a7862c984559fcaa1 (diff) | |
parent | 7ec2c76c12d1254c2c31a20d15ae5c39540adb3e (diff) | |
download | SCons-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-x | src/CHANGES.txt | 2 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/__init__.py | 3 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/vc.py | 70 | ||||
-rw-r--r-- | src/engine/SCons/Tool/MSCommon/vcTests.py | 34 | ||||
-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 | 6 | ||||
-rw-r--r-- | src/engine/SCons/Tool/msvc.xml | 50 | ||||
-rw-r--r-- | src/engine/SCons/Tool/msvsTests.py | 2 |
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 |