[pypy-commit] pypy msvc-discovery: simplify, use only setuptools.msvc to find msvc compilers
mattip
pypy.commits at gmail.com
Sun Nov 10 18:16:37 EST 2019
Author: Matti Picus <matti.picus at gmail.com>
Branch: msvc-discovery
Changeset: r98012:f53664167f74
Date: 2019-11-08 21:55 +0200
http://bitbucket.org/pypy/pypy/changeset/f53664167f74/
Log: simplify, use only setuptools.msvc to find msvc compilers
diff --git a/rpython/tool/setuptools_msvc.py b/rpython/tool/setuptools_msvc.py
--- a/rpython/tool/setuptools_msvc.py
+++ b/rpython/tool/setuptools_msvc.py
@@ -11,35 +11,39 @@
Microsoft Visual C++ 10.0:
Microsoft Windows SDK 7.1 (x86, x64, ia64)
-Microsoft Visual C++ 14.0:
+Microsoft Visual C++ 14.X:
Microsoft Visual C++ Build Tools 2015 (x86, x64, arm)
- Microsoft Visual Studio 2017 (x86, x64, arm, arm64)
Microsoft Visual Studio Build Tools 2017 (x86, x64, arm, arm64)
+ Microsoft Visual Studio Build Tools 2019 (x86, x64, arm, arm64)
+
+This may also support compilers shipped with compatible Visual Studio versions.
"""
-# copied as-is from python3
-# modified to:
+# copied as-is from setuptools v41.6.0 setuptools/msvc.py
+# modified to (search for `"modified"):
# - commented out monkey patching
# - lookup() returns str not unicode
-import os
+import json
+from io import open
+from os import listdir, pathsep
+from os.path import join, isfile, isdir, dirname
import sys
import platform
import itertools
import distutils.errors
+from setuptools.extern.packaging.version import LegacyVersion
from setuptools.extern.six.moves import filterfalse
-#from .monkey import get_unpatched
+# modified
+# from .monkey import get_unpatched
if platform.system() == 'Windows':
from setuptools.extern.six.moves import winreg
- safe_env = os.environ
+ from os import environ
else:
- """
- Mock winreg and environ so the module can be imported
- on this platform.
- """
+ # Mock winreg and environ so the module can be imported on this platform.
class winreg:
HKEY_USERS = None
@@ -47,12 +51,12 @@
HKEY_LOCAL_MACHINE = None
HKEY_CLASSES_ROOT = None
- safe_env = dict()
+ environ = dict()
_msvc9_suppress_errors = (
# msvc9compiler isn't available on some platforms
ImportError,
-
+
# msvc9compiler raises DistutilsPlatformError in some
# environments. See #1118.
distutils.errors.DistutilsPlatformError,
@@ -67,16 +71,14 @@
def msvc9_find_vcvarsall(version):
"""
Patched "distutils.msvc9compiler.find_vcvarsall" to use the standalone
- compiler build for Python (VCForPython). Fall back to original behavior
- when the standalone compiler is not available.
+ compiler build for Python
+ (VCForPython / Microsoft Visual C++ Compiler for Python 2.7).
+
+ Fall back to original behavior when the standalone compiler is not
+ available.
Redirect the path of "vcvarsall.bat".
- Known supported compilers
- -------------------------
- Microsoft Visual C++ 9.0:
- Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64)
-
Parameters
----------
version: float
@@ -84,24 +86,25 @@
Return
------
- vcvarsall.bat path: str
+ str
+ vcvarsall.bat path
"""
- VC_BASE = r'Software\%sMicrosoft\DevDiv\VCForPython\%0.1f'
- key = VC_BASE % ('', version)
+ vc_base = r'Software\%sMicrosoft\DevDiv\VCForPython\%0.1f'
+ key = vc_base % ('', version)
try:
# Per-user installs register the compiler path here
productdir = Reg.get_value(key, "installdir")
except KeyError:
try:
# All-user installs on a 64-bit system register here
- key = VC_BASE % ('Wow6432Node\\', version)
+ key = vc_base % ('Wow6432Node\\', version)
productdir = Reg.get_value(key, "installdir")
except KeyError:
productdir = None
if productdir:
- vcvarsall = os.path.os.path.join(productdir, "vcvarsall.bat")
- if os.path.isfile(vcvarsall):
+ vcvarsall = join(productdir, "vcvarsall.bat")
+ if isfile(vcvarsall):
return vcvarsall
return get_unpatched(msvc9_find_vcvarsall)(version)
@@ -110,20 +113,10 @@
def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs):
"""
Patched "distutils.msvc9compiler.query_vcvarsall" for support extra
- compilers.
+ Microsoft Visual C++ 9.0 and 10.0 compilers.
Set environment without use of "vcvarsall.bat".
- Known supported compilers
- -------------------------
- Microsoft Visual C++ 9.0:
- Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64)
- Microsoft Windows SDK 6.1 (x86, x64, ia64)
- Microsoft Windows SDK 7.0 (x86, x64, ia64)
-
- Microsoft Visual C++ 10.0:
- Microsoft Windows SDK 7.1 (x86, x64, ia64)
-
Parameters
----------
ver: float
@@ -133,9 +126,10 @@
Return
------
- environment: dict
+ dict
+ environment
"""
- # Try to get environement from vcvarsall.bat (Classical way)
+ # Try to get environment from vcvarsall.bat (Classical way)
#try:
# orig = get_unpatched(msvc9_query_vcvarsall)
# return orig(ver, arch, *args, **kwargs)
@@ -157,17 +151,10 @@
def msvc14_get_vc_env(plat_spec):
"""
Patched "distutils._msvccompiler._get_vc_env" for support extra
- compilers.
+ Microsoft Visual C++ 14.X compilers.
Set environment without use of "vcvarsall.bat".
- Known supported compilers
- -------------------------
- Microsoft Visual C++ 14.0:
- Microsoft Visual C++ Build Tools 2015 (x86, x64, arm)
- Microsoft Visual Studio 2017 (x86, x64, arm, arm64)
- Microsoft Visual Studio Build Tools 2017 (x86, x64, arm, arm64)
-
Parameters
----------
plat_spec: str
@@ -175,7 +162,8 @@
Return
------
- environment: dict
+ dict
+ environment
"""
# Try to get environment from vcvarsall.bat (Classical way)
#try:
@@ -200,7 +188,6 @@
"""
if "numpy.distutils" in sys.modules:
import numpy as np
- from pkg_resources.extern.packaging.version import LegacyVersion
if LegacyVersion(np.__version__) < LegacyVersion('1.11.2'):
return np.distutils.ccompiler.gen_lib_options(*args, **kwargs)
return get_unpatched(msvc14_gen_lib_options)(*args, **kwargs)
@@ -222,9 +209,9 @@
if version == 9.0:
if arch.lower().find('ia64') > -1:
# For VC++ 9.0, if IA64 support is needed, redirect user
- # to Windows SDK 7.0
- message += ' Get it with "Microsoft Windows SDK 7.0": '
- message += msdownload % 3138
+ # to Windows SDK 7.0.
+ # Note: No download link available from Microsoft.
+ message += ' Get it with "Microsoft Windows SDK 7.0"'
else:
# For VC++ 9.0 redirect user to Vc++ for Python 2.7 :
# This redirection link is maintained by Microsoft.
@@ -235,36 +222,59 @@
message += ' Get it with "Microsoft Windows SDK 7.1": '
message += msdownload % 8279
elif version >= 14.0:
- # For VC++ 14.0 Redirect user to Visual C++ Build Tools
- message += (' Get it with "Microsoft Visual C++ Build Tools": '
- r'http://landinghub.visualstudio.com/'
- 'visual-cpp-build-tools')
+ # For VC++ 14.X Redirect user to latest Visual C++ Build Tools
+ message += (' Get it with "Build Tools for Visual Studio": '
+ r'https://visualstudio.microsoft.com/downloads/')
exc.args = (message, )
class PlatformInfo:
"""
- Current and Target Architectures informations.
+ Current and Target Architectures information.
Parameters
----------
arch: str
Target architecture.
"""
- current_cpu = safe_env.get('processor_architecture', '').lower()
+ current_cpu = environ.get('processor_architecture', '').lower()
def __init__(self, arch):
self.arch = arch.lower().replace('x64', 'amd64')
@property
def target_cpu(self):
+ """
+ Return Target CPU architecture.
+
+ Return
+ ------
+ str
+ Target CPU
+ """
return self.arch[self.arch.find('_') + 1:]
def target_is_x86(self):
+ """
+ Return True if target CPU is x86 32 bits..
+
+ Return
+ ------
+ bool
+ CPU is x86 32 bits
+ """
return self.target_cpu == 'x86'
def current_is_x86(self):
+ """
+ Return True if current CPU is x86 32 bits..
+
+ Return
+ ------
+ bool
+ CPU is x86 32 bits
+ """
return self.current_cpu == 'x86'
def current_dir(self, hidex86=False, x64=False):
@@ -280,8 +290,8 @@
Return
------
- subfolder: str
- '\target', or '' (see hidex86 parameter)
+ str
+ subfolder: '\target', or '' (see hidex86 parameter)
"""
return (
'' if (self.current_cpu == 'x86' and hidex86) else
@@ -302,8 +312,8 @@
Return
------
- subfolder: str
- '\current', or '' (see hidex86 parameter)
+ str
+ subfolder: '\current', or '' (see hidex86 parameter)
"""
return (
'' if (self.target_cpu == 'x86' and hidex86) else
@@ -318,13 +328,13 @@
Parameters
----------
forcex86: bool
- Use 'x86' as current architecture even if current acritecture is
+ Use 'x86' as current architecture even if current architecture is
not x86.
Return
------
- subfolder: str
- '' if target architecture is current architecture,
+ str
+ subfolder: '' if target architecture is current architecture,
'\current_target' if not.
"""
current = 'x86' if forcex86 else self.current_cpu
@@ -336,7 +346,7 @@
class RegistryInfo:
"""
- Microsoft Visual Studio related registry informations.
+ Microsoft Visual Studio related registry information.
Parameters
----------
@@ -355,6 +365,11 @@
def visualstudio(self):
"""
Microsoft Visual Studio root registry key.
+
+ Return
+ ------
+ str
+ Registry key
"""
return 'VisualStudio'
@@ -362,27 +377,47 @@
def sxs(self):
"""
Microsoft Visual Studio SxS registry key.
+
+ Return
+ ------
+ str
+ Registry key
"""
- return os.path.join(self.visualstudio, 'SxS')
+ return join(self.visualstudio, 'SxS')
@property
def vc(self):
"""
Microsoft Visual C++ VC7 registry key.
+
+ Return
+ ------
+ str
+ Registry key
"""
- return os.path.join(self.sxs, 'VC7')
+ return join(self.sxs, 'VC7')
@property
def vs(self):
"""
Microsoft Visual Studio VS7 registry key.
+
+ Return
+ ------
+ str
+ Registry key
"""
- return os.path.join(self.sxs, 'VS7')
+ return join(self.sxs, 'VS7')
@property
def vc_for_python(self):
"""
Microsoft Visual C++ for Python registry key.
+
+ Return
+ ------
+ str
+ Registry key
"""
return r'DevDiv\VCForPython'
@@ -390,6 +425,11 @@
def microsoft_sdk(self):
"""
Microsoft SDK registry key.
+
+ Return
+ ------
+ str
+ Registry key
"""
return 'Microsoft SDKs'
@@ -397,20 +437,35 @@
def windows_sdk(self):
"""
Microsoft Windows/Platform SDK registry key.
+
+ Return
+ ------
+ str
+ Registry key
"""
- return os.path.join(self.microsoft_sdk, 'Windows')
+ return join(self.microsoft_sdk, 'Windows')
@property
def netfx_sdk(self):
"""
Microsoft .NET Framework SDK registry key.
+
+ Return
+ ------
+ str
+ Registry key
"""
- return os.path.join(self.microsoft_sdk, 'NETFXSDK')
+ return join(self.microsoft_sdk, 'NETFXSDK')
@property
def windows_kits_roots(self):
"""
Microsoft Windows Kits Roots registry key.
+
+ Return
+ ------
+ str
+ Registry key
"""
return r'Windows Kits\Installed Roots'
@@ -427,10 +482,11 @@
Return
------
- str: value
+ str
+ Registry key
"""
node64 = '' if self.pi.current_is_x86() or x86 else 'Wow6432Node'
- return os.path.join('Software', node64, 'Microsoft', key)
+ return join('Software', node64, 'Microsoft', key)
def lookup(self, key, name):
"""
@@ -445,18 +501,19 @@
Return
------
- str: value
+ str
+ value
"""
- KEY_READ = winreg.KEY_READ
+ key_read = winreg.KEY_READ
openkey = winreg.OpenKey
ms = self.microsoft
for hkey in self.HKEYS:
try:
- bkey = openkey(hkey, ms(key), 0, KEY_READ)
+ bkey = openkey(hkey, ms(key), 0, key_read)
except (OSError, IOError):
if not self.pi.current_is_x86():
try:
- bkey = openkey(hkey, ms(key, True), 0, KEY_READ)
+ bkey = openkey(hkey, ms(key, True), 0, key_read)
except (OSError, IOError):
continue
else:
@@ -470,7 +527,7 @@
class SystemInfo:
"""
- Microsoft Windows and Visual Studio related system inormations.
+ Microsoft Windows and Visual Studio related system information.
Parameters
----------
@@ -481,30 +538,52 @@
"""
# Variables and properties in this class use originals CamelCase variables
- # names from Microsoft source files for more easy comparaison.
- WinDir = safe_env.get('WinDir', '')
- ProgramFiles = safe_env.get('ProgramFiles', '')
- ProgramFilesx86 = safe_env.get('ProgramFiles(x86)', ProgramFiles)
+ # names from Microsoft source files for more easy comparison.
+ WinDir = environ.get('WinDir', '')
+ ProgramFiles = environ.get('ProgramFiles', '')
+ ProgramFilesx86 = environ.get('ProgramFiles(x86)', ProgramFiles)
def __init__(self, registry_info, vc_ver=None):
self.ri = registry_info
self.pi = self.ri.pi
- self.vc_ver = vc_ver or self._find_latest_available_vc_ver()
- def _find_latest_available_vc_ver(self):
- try:
- return self.find_available_vc_vers()[-1]
- except IndexError:
- err = 'No Microsoft Visual C++ version found'
- raise distutils.errors.DistutilsPlatformError(err)
+ self.known_vs_paths = self.find_programdata_vs_vers()
- def find_available_vc_vers(self):
+ # Except for VS15+, VC version is aligned with VS version
+ self.vs_ver = self.vc_ver = (
+ vc_ver or self._find_latest_available_vs_ver())
+
+ def _find_latest_available_vs_ver(self):
"""
- Find all available Microsoft Visual C++ versions.
+ Find the latest VC version
+
+ Return
+ ------
+ float
+ version
+ """
+ reg_vc_vers = self.find_reg_vs_vers()
+
+ if not (reg_vc_vers or self.known_vs_paths):
+ raise distutils.errors.DistutilsPlatformError(
+ 'No Microsoft Visual C++ version found')
+
+ vc_vers = set(reg_vc_vers)
+ vc_vers.update(self.known_vs_paths)
+ return sorted(vc_vers)[-1]
+
+ def find_reg_vs_vers(self):
+ """
+ Find Microsoft Visual Studio versions available in registry.
+
+ Return
+ ------
+ list of float
+ Versions
"""
ms = self.ri.microsoft
vckeys = (self.ri.vc, self.ri.vc_for_python, self.ri.vs)
- vc_vers = []
+ vs_vers = []
for hkey in self.ri.HKEYS:
for key in vckeys:
try:
@@ -515,49 +594,109 @@
for i in range(values):
try:
ver = float(winreg.EnumValue(bkey, i)[0])
- if ver not in vc_vers:
- vc_vers.append(ver)
+ if ver not in vs_vers:
+ vs_vers.append(ver)
except ValueError:
pass
for i in range(subkeys):
try:
ver = float(winreg.EnumKey(bkey, i))
- if ver not in vc_vers:
- vc_vers.append(ver)
+ if ver not in vs_vers:
+ vs_vers.append(ver)
except ValueError:
pass
- return sorted(vc_vers)
+ return sorted(vs_vers)
+
+ def find_programdata_vs_vers(self):
+ r"""
+ Find Visual studio 2017+ versions from information in
+ "C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances".
+
+ Return
+ ------
+ dict
+ float version as key, path as value.
+ """
+ vs_versions = {}
+ instances_dir = \
+ r'C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances'
+
+ try:
+ hashed_names = listdir(instances_dir)
+
+ except (OSError, IOError):
+ # Directory not exists with all Visual Studio versions
+ return vs_versions
+
+ for name in hashed_names:
+ try:
+ # Get VS installation path from "state.json" file
+ state_path = join(instances_dir, name, 'state.json')
+ with open(state_path, 'rt', encoding='utf-8') as state_file:
+ state = json.load(state_file)
+ vs_path = state['installationPath']
+
+ # Raises OSError if this VS installation does not contain VC
+ listdir(join(vs_path, r'VC\Tools\MSVC'))
+
+ # Store version and path
+ # modified for python2 to encode paths
+ vs_versions[self._as_float_version(
+ state['installationVersion'])] = vs_path.encode('utf-8')
+
+ except (OSError, IOError, KeyError):
+ # Skip if "state.json" file is missing or bad format
+ continue
+
+ return vs_versions
+
+ @staticmethod
+ def _as_float_version(version):
+ """
+ Return a string version as a simplified float version (major.minor)
+
+ Parameters
+ ----------
+ version: str
+ Version.
+
+ Return
+ ------
+ float
+ version
+ """
+ return float('.'.join(version.split('.')[:2]))
@property
def VSInstallDir(self):
"""
Microsoft Visual Studio directory.
+
+ Return
+ ------
+ str
+ path
"""
# Default path
- name = 'Microsoft Visual Studio %0.1f' % self.vc_ver
- default = os.path.join(self.ProgramFilesx86, name)
+ default = join(self.ProgramFilesx86,
+ 'Microsoft Visual Studio %0.1f' % self.vs_ver)
# Try to get path from registry, if fail use default path
- return self.ri.lookup(self.ri.vs, '%0.1f' % self.vc_ver) or default
+ return self.ri.lookup(self.ri.vs, '%0.1f' % self.vs_ver) or default
@property
def VCInstallDir(self):
"""
Microsoft Visual C++ directory.
+
+ Return
+ ------
+ str
+ path
"""
- self.VSInstallDir
+ path = self._guess_vc() or self._guess_vc_legacy()
- guess_vc = self._guess_vc() or self._guess_vc_legacy()
-
- # Try to get "VC++ for Python" path from registry as default path
- reg_path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vc_ver)
- python_vc = self.ri.lookup(reg_path, 'installdir')
- default_vc = os.path.join(python_vc, 'VC') if python_vc else guess_vc
-
- # Try to get path from registry, if fail use default path
- path = self.ri.lookup(self.ri.vc, '%0.1f' % self.vc_ver) or default_vc
-
- if not os.path.isdir(path):
+ if not isdir(path):
msg = 'Microsoft Visual C++ directory not found'
raise distutils.errors.DistutilsPlatformError(msg)
@@ -565,186 +704,256 @@
def _guess_vc(self):
"""
- Locate Visual C for 2017
+ Locate Visual C++ for VS2017+.
+
+ Return
+ ------
+ str
+ path
"""
- if self.vc_ver <= 14.0:
- return
+ if self.vs_ver <= 14.0:
+ return ''
- default = r'VC\Tools\MSVC'
- guess_vc = os.path.join(self.VSInstallDir, default)
+ try:
+ # First search in known VS paths
+ vs_dir = self.known_vs_paths[self.vs_ver]
+ except KeyError:
+ # Else, search with path from registry
+ vs_dir = self.VSInstallDir
+
+ guess_vc = join(vs_dir, r'VC\Tools\MSVC')
+
# Subdir with VC exact version as name
try:
- vc_exact_ver = os.listdir(guess_vc)[-1]
- return os.path.join(guess_vc, vc_exact_ver)
+ # Update the VC version with real one instead of VS version
+ vc_ver = listdir(guess_vc)[-1]
+ self.vc_ver = self._as_float_version(vc_ver)
+ return join(guess_vc, vc_ver)
except (OSError, IOError, IndexError):
- pass
+ return ''
def _guess_vc_legacy(self):
"""
- Locate Visual C for versions prior to 2017
+ Locate Visual C++ for versions prior to 2017.
+
+ Return
+ ------
+ str
+ path
"""
- default = r'Microsoft Visual Studio %0.1f\VC' % self.vc_ver
- return os.path.join(self.ProgramFilesx86, default)
+ default = join(self.ProgramFilesx86,
+ r'Microsoft Visual Studio %0.1f\VC' % self.vs_ver)
+
+ # Try to get "VC++ for Python" path from registry as default path
+ reg_path = join(self.ri.vc_for_python, '%0.1f' % self.vs_ver)
+ python_vc = self.ri.lookup(reg_path, 'installdir')
+ default_vc = join(python_vc, 'VC') if python_vc else default
+
+ # Try to get path from registry, if fail use default path
+ return self.ri.lookup(self.ri.vc, '%0.1f' % self.vs_ver) or default_vc
@property
def WindowsSdkVersion(self):
"""
Microsoft Windows SDK versions for specified MSVC++ version.
+
+ Return
+ ------
+ tuple of str
+ versions
"""
- if self.vc_ver <= 9.0:
- return ('7.0', '6.1', '6.0a')
- elif self.vc_ver == 10.0:
- return ('7.1', '7.0a')
- elif self.vc_ver == 11.0:
- return ('8.0', '8.0a')
- elif self.vc_ver == 12.0:
- return ('8.1', '8.1a')
- elif self.vc_ver >= 14.0:
- return ('10.0', '8.1')
+ if self.vs_ver <= 9.0:
+ return '7.0', '6.1', '6.0a'
+ elif self.vs_ver == 10.0:
+ return '7.1', '7.0a'
+ elif self.vs_ver == 11.0:
+ return '8.0', '8.0a'
+ elif self.vs_ver == 12.0:
+ return '8.1', '8.1a'
+ elif self.vs_ver >= 14.0:
+ return '10.0', '8.1'
@property
def WindowsSdkLastVersion(self):
"""
- Microsoft Windows SDK last version
+ Microsoft Windows SDK last version.
+
+ Return
+ ------
+ str
+ version
"""
- return self._use_last_dir_name(os.path.join(
- self.WindowsSdkDir, 'lib'))
+ return self._use_last_dir_name(join(self.WindowsSdkDir, 'lib'))
@property
def WindowsSdkDir(self):
"""
Microsoft Windows SDK directory.
+
+ Return
+ ------
+ str
+ path
"""
sdkdir = ''
for ver in self.WindowsSdkVersion:
# Try to get it from registry
- loc = os.path.join(self.ri.windows_sdk, 'v%s' % ver)
+ loc = join(self.ri.windows_sdk, 'v%s' % ver)
sdkdir = self.ri.lookup(loc, 'installationfolder')
if sdkdir:
break
- if not sdkdir or not os.path.isdir(sdkdir):
+ if not sdkdir or not isdir(sdkdir):
# Try to get "VC++ for Python" version from registry
- path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vc_ver)
+ path = join(self.ri.vc_for_python, '%0.1f' % self.vc_ver)
install_base = self.ri.lookup(path, 'installdir')
if install_base:
- sdkdir = os.path.join(install_base, 'WinSDK')
- if not sdkdir or not os.path.isdir(sdkdir):
+ sdkdir = join(install_base, 'WinSDK')
+ if not sdkdir or not isdir(sdkdir):
# If fail, use default new path
for ver in self.WindowsSdkVersion:
intver = ver[:ver.rfind('.')]
- path = r'Microsoft SDKs\Windows Kits\%s' % (intver)
- d = os.path.join(self.ProgramFiles, path)
- if os.path.isdir(d):
+ path = r'Microsoft SDKs\Windows Kits\%s' % intver
+ d = join(self.ProgramFiles, path)
+ if isdir(d):
sdkdir = d
- if not sdkdir or not os.path.isdir(sdkdir):
+ if not sdkdir or not isdir(sdkdir):
# If fail, use default old path
for ver in self.WindowsSdkVersion:
path = r'Microsoft SDKs\Windows\v%s' % ver
- d = os.path.join(self.ProgramFiles, path)
- if os.path.isdir(d):
+ d = join(self.ProgramFiles, path)
+ if isdir(d):
sdkdir = d
if not sdkdir:
# If fail, use Platform SDK
- sdkdir = os.path.join(self.VCInstallDir, 'PlatformSDK')
+ sdkdir = join(self.VCInstallDir, 'PlatformSDK')
return sdkdir
@property
def WindowsSDKExecutablePath(self):
"""
Microsoft Windows SDK executable directory.
+
+ Return
+ ------
+ str
+ path
"""
# Find WinSDK NetFx Tools registry dir name
- if self.vc_ver <= 11.0:
+ if self.vs_ver <= 11.0:
netfxver = 35
arch = ''
else:
netfxver = 40
- hidex86 = True if self.vc_ver <= 12.0 else False
+ hidex86 = True if self.vs_ver <= 12.0 else False
arch = self.pi.current_dir(x64=True, hidex86=hidex86)
fx = 'WinSDK-NetFx%dTools%s' % (netfxver, arch.replace('\\', '-'))
- # liste all possibles registry paths
+ # list all possibles registry paths
regpaths = []
- if self.vc_ver >= 14.0:
+ if self.vs_ver >= 14.0:
for ver in self.NetFxSdkVersion:
- regpaths += [os.path.join(self.ri.netfx_sdk, ver, fx)]
+ regpaths += [join(self.ri.netfx_sdk, ver, fx)]
for ver in self.WindowsSdkVersion:
- regpaths += [os.path.join(self.ri.windows_sdk, 'v%sA' % ver, fx)]
+ regpaths += [join(self.ri.windows_sdk, 'v%sA' % ver, fx)]
# Return installation folder from the more recent path
for path in regpaths:
execpath = self.ri.lookup(path, 'installationfolder')
if execpath:
- break
- return execpath
+ return execpath
@property
def FSharpInstallDir(self):
"""
Microsoft Visual F# directory.
+
+ Return
+ ------
+ str
+ path
"""
- path = r'%0.1f\Setup\F#' % self.vc_ver
- path = os.path.join(self.ri.visualstudio, path)
+ path = join(self.ri.visualstudio, r'%0.1f\Setup\F#' % self.vs_ver)
return self.ri.lookup(path, 'productdir') or ''
@property
def UniversalCRTSdkDir(self):
"""
Microsoft Universal CRT SDK directory.
+
+ Return
+ ------
+ str
+ path
"""
# Set Kit Roots versions for specified MSVC++ version
- if self.vc_ver >= 14.0:
- vers = ('10', '81')
- else:
- vers = ()
+ vers = ('10', '81') if self.vs_ver >= 14.0 else ()
# Find path of the more recent Kit
for ver in vers:
sdkdir = self.ri.lookup(self.ri.windows_kits_roots,
'kitsroot%s' % ver)
if sdkdir:
- break
- return sdkdir or ''
+ return sdkdir or ''
@property
def UniversalCRTSdkLastVersion(self):
"""
- Microsoft Universal C Runtime SDK last version
+ Microsoft Universal C Runtime SDK last version.
+
+ Return
+ ------
+ str
+ version
"""
- return self._use_last_dir_name(os.path.join(
- self.UniversalCRTSdkDir, 'lib'))
+ return self._use_last_dir_name(join(self.UniversalCRTSdkDir, 'lib'))
@property
def NetFxSdkVersion(self):
"""
Microsoft .NET Framework SDK versions.
+
+ Return
+ ------
+ tuple of str
+ versions
"""
- # Set FxSdk versions for specified MSVC++ version
- if self.vc_ver >= 14.0:
- return ('4.6.1', '4.6')
- else:
- return ()
+ # Set FxSdk versions for specified VS version
+ return (('4.7.2', '4.7.1', '4.7',
+ '4.6.2', '4.6.1', '4.6',
+ '4.5.2', '4.5.1', '4.5')
+ if self.vs_ver >= 14.0 else ())
@property
def NetFxSdkDir(self):
"""
Microsoft .NET Framework SDK directory.
+
+ Return
+ ------
+ str
+ path
"""
+ sdkdir = ''
for ver in self.NetFxSdkVersion:
- loc = os.path.join(self.ri.netfx_sdk, ver)
+ loc = join(self.ri.netfx_sdk, ver)
sdkdir = self.ri.lookup(loc, 'kitsinstallationfolder')
if sdkdir:
break
- return sdkdir or ''
+ return sdkdir
@property
def FrameworkDir32(self):
"""
Microsoft .NET Framework 32bit directory.
+
+ Return
+ ------
+ str
+ path
"""
# Default path
- guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework')
+ guess_fw = join(self.WinDir, r'Microsoft.NET\Framework')
# Try to get path from registry, if fail use default path
return self.ri.lookup(self.ri.vc, 'frameworkdir32') or guess_fw
@@ -753,9 +962,14 @@
def FrameworkDir64(self):
"""
Microsoft .NET Framework 64bit directory.
+
+ Return
+ ------
+ str
+ path
"""
# Default path
- guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework64')
+ guess_fw = join(self.WinDir, r'Microsoft.NET\Framework64')
# Try to get path from registry, if fail use default path
return self.ri.lookup(self.ri.vc, 'frameworkdir64') or guess_fw
@@ -764,6 +978,11 @@
def FrameworkVersion32(self):
"""
Microsoft .NET Framework 32bit versions.
+
+ Return
+ ------
+ tuple of str
+ versions
"""
return self._find_dot_net_versions(32)
@@ -771,6 +990,11 @@
def FrameworkVersion64(self):
"""
Microsoft .NET Framework 64bit versions.
+
+ Return
+ ------
+ tuple of str
+ versions
"""
return self._find_dot_net_versions(64)
@@ -782,6 +1006,11 @@
----------
bits: int
Platform number of bits: 32 or 64.
+
+ Return
+ ------
+ tuple of str
+ versions
"""
# Find actual .NET version in registry
reg_ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits)
@@ -789,18 +1018,17 @@
ver = reg_ver or self._use_last_dir_name(dot_net_dir, 'v') or ''
# Set .NET versions for specified MSVC++ version
- if self.vc_ver >= 12.0:
- frameworkver = (ver, 'v4.0')
- elif self.vc_ver >= 10.0:
- frameworkver = ('v4.0.30319' if ver.lower()[:2] != 'v4' else ver,
- 'v3.5')
- elif self.vc_ver == 9.0:
- frameworkver = ('v3.5', 'v2.0.50727')
- if self.vc_ver == 8.0:
- frameworkver = ('v3.0', 'v2.0.50727')
- return frameworkver
+ if self.vs_ver >= 12.0:
+ return ver, 'v4.0'
+ elif self.vs_ver >= 10.0:
+ return 'v4.0.30319' if ver.lower()[:2] != 'v4' else ver, 'v3.5'
+ elif self.vs_ver == 9.0:
+ return 'v3.5', 'v2.0.50727'
+ elif self.vs_ver == 8.0:
+ return 'v3.0', 'v2.0.50727'
- def _use_last_dir_name(self, path, prefix=''):
+ @staticmethod
+ def _use_last_dir_name(path, prefix=''):
"""
Return name of the last dir in path or '' if no dir found.
@@ -809,12 +1037,17 @@
path: str
Use dirs in this path
prefix: str
- Use only dirs startings by this prefix
+ Use only dirs starting by this prefix
+
+ Return
+ ------
+ str
+ name
"""
matching_dirs = (
dir_name
- for dir_name in reversed(os.listdir(path))
- if os.path.isdir(os.path.join(path, dir_name)) and
+ for dir_name in reversed(listdir(path))
+ if isdir(join(path, dir_name)) and
dir_name.startswith(prefix)
)
return next(matching_dirs, None) or ''
@@ -825,7 +1058,7 @@
Return environment variables for specified Microsoft Visual C++ version
and platform : Lib, Include, Path and libpath.
- This function is compatible with Microsoft Visual C++ 9.0 to 14.0.
+ This function is compatible with Microsoft Visual C++ 9.0 to 14.X.
Script created by analysing Microsoft environment configuration files like
"vcvars[...].bat", "SetEnv.Cmd", "vcbuildtools.bat", ...
@@ -842,7 +1075,7 @@
"""
# Variables and properties in this class use originals CamelCase variables
- # names from Microsoft source files for more easy comparaison.
+ # names from Microsoft source files for more easy comparison.
def __init__(self, arch, vc_ver=None, vc_min_ver=0):
self.pi = PlatformInfo(arch)
@@ -854,204 +1087,254 @@
raise distutils.errors.DistutilsPlatformError(err)
@property
+ def vs_ver(self):
+ """
+ Microsoft Visual Studio.
+
+ Return
+ ------
+ float
+ version
+ """
+ return self.si.vs_ver
+
+ @property
def vc_ver(self):
"""
Microsoft Visual C++ version.
+
+ Return
+ ------
+ float
+ version
"""
return self.si.vc_ver
@property
def VSTools(self):
"""
- Microsoft Visual Studio Tools
+ Microsoft Visual Studio Tools.
+
+ Return
+ ------
+ list of str
+ paths
"""
paths = [r'Common7\IDE', r'Common7\Tools']
- if self.vc_ver >= 14.0:
+ if self.vs_ver >= 14.0:
arch_subdir = self.pi.current_dir(hidex86=True, x64=True)
paths += [r'Common7\IDE\CommonExtensions\Microsoft\TestWindow']
paths += [r'Team Tools\Performance Tools']
paths += [r'Team Tools\Performance Tools%s' % arch_subdir]
- return [os.path.join(self.si.VSInstallDir, path) for path in paths]
+ return [join(self.si.VSInstallDir, path) for path in paths]
@property
def VCIncludes(self):
"""
- Microsoft Visual C++ & Microsoft Foundation Class Includes
+ Microsoft Visual C++ & Microsoft Foundation Class Includes.
+
+ Return
+ ------
+ list of str
+ paths
"""
- return [os.path.join(self.si.VCInstallDir, 'Include'),
- os.path.join(self.si.VCInstallDir, r'ATLMFC\Include')]
+ return [join(self.si.VCInstallDir, 'Include'),
+ join(self.si.VCInstallDir, r'ATLMFC\Include')]
@property
def VCLibraries(self):
"""
- Microsoft Visual C++ & Microsoft Foundation Class Libraries
+ Microsoft Visual C++ & Microsoft Foundation Class Libraries.
+
+ Return
+ ------
+ list of str
+ paths
"""
- if self.vc_ver >= 15.0:
+ if self.vs_ver >= 15.0:
arch_subdir = self.pi.target_dir(x64=True)
else:
arch_subdir = self.pi.target_dir(hidex86=True)
paths = ['Lib%s' % arch_subdir, r'ATLMFC\Lib%s' % arch_subdir]
- if self.vc_ver >= 14.0:
+ if self.vs_ver >= 14.0:
paths += [r'Lib\store%s' % arch_subdir]
- return [os.path.join(self.si.VCInstallDir, path) for path in paths]
+ return [join(self.si.VCInstallDir, path) for path in paths]
@property
def VCStoreRefs(self):
"""
- Microsoft Visual C++ store references Libraries
+ Microsoft Visual C++ store references Libraries.
+
+ Return
+ ------
+ list of str
+ paths
"""
- if self.vc_ver < 14.0:
+ if self.vs_ver < 14.0:
return []
- return [os.path.join(self.si.VCInstallDir, r'Lib\store\references')]
+ return [join(self.si.VCInstallDir, r'Lib\store\references')]
@property
def VCTools(self):
"""
- Microsoft Visual C++ Tools
+ Microsoft Visual C++ Tools.
+
+ Return
+ ------
+ list of str
+ paths
"""
si = self.si
- tools = [os.path.join(si.VCInstallDir, 'VCPackages')]
+ tools = [join(si.VCInstallDir, 'VCPackages')]
- forcex86 = True if self.vc_ver <= 10.0 else False
+ forcex86 = True if self.vs_ver <= 10.0 else False
arch_subdir = self.pi.cross_dir(forcex86)
if arch_subdir:
- tools += [os.path.join(si.VCInstallDir, 'Bin%s' % arch_subdir)]
+ tools += [join(si.VCInstallDir, 'Bin%s' % arch_subdir)]
- if self.vc_ver == 14.0:
+ if self.vs_ver == 14.0:
path = 'Bin%s' % self.pi.current_dir(hidex86=True)
- tools += [os.path.join(si.VCInstallDir, path)]
+ tools += [join(si.VCInstallDir, path)]
- elif self.vc_ver >= 15.0:
+ elif self.vs_ver >= 15.0:
host_dir = (r'bin\HostX86%s' if self.pi.current_is_x86() else
r'bin\HostX64%s')
- tools += [os.path.join(
+ tools += [join(
si.VCInstallDir, host_dir % self.pi.target_dir(x64=True))]
if self.pi.current_cpu != self.pi.target_cpu:
- tools += [os.path.join(
+ tools += [join(
si.VCInstallDir, host_dir % self.pi.current_dir(x64=True))]
else:
- tools += [os.path.join(si.VCInstallDir, 'Bin')]
+ tools += [join(si.VCInstallDir, 'Bin')]
return tools
@property
def OSLibraries(self):
"""
- Microsoft Windows SDK Libraries
+ Microsoft Windows SDK Libraries.
+
+ Return
+ ------
+ list of str
+ paths
"""
- if self.vc_ver <= 10.0:
+ if self.vs_ver <= 10.0:
arch_subdir = self.pi.target_dir(hidex86=True, x64=True)
- return [os.path.join(self.si.WindowsSdkDir, 'Lib%s' % arch_subdir)]
+ return [join(self.si.WindowsSdkDir, 'Lib%s' % arch_subdir)]
else:
arch_subdir = self.pi.target_dir(x64=True)
- lib = os.path.join(self.si.WindowsSdkDir, 'lib')
+ lib = join(self.si.WindowsSdkDir, 'lib')
libver = self._sdk_subdir
- return [os.path.join(lib, '%sum%s' % (libver , arch_subdir))]
+ return [join(lib, '%sum%s' % (libver , arch_subdir))]
@property
def OSIncludes(self):
"""
- Microsoft Windows SDK Include
+ Microsoft Windows SDK Include.
+
+ Return
+ ------
+ list of str
+ paths
"""
- include = os.path.join(self.si.WindowsSdkDir, 'include')
+ include = join(self.si.WindowsSdkDir, 'include')
- if self.vc_ver <= 10.0:
- return [include, os.path.join(include, 'gl')]
+ if self.vs_ver <= 10.0:
+ return [include, join(include, 'gl')]
else:
- if self.vc_ver >= 14.0:
+ if self.vs_ver >= 14.0:
sdkver = self._sdk_subdir
else:
sdkver = ''
- return [os.path.join(include, '%sshared' % sdkver),
- os.path.join(include, '%sum' % sdkver),
- os.path.join(include, '%swinrt' % sdkver)]
+ return [join(include, '%sshared' % sdkver),
+ join(include, '%sum' % sdkver),
+ join(include, '%swinrt' % sdkver)]
@property
def OSLibpath(self):
"""
- Microsoft Windows SDK Libraries Paths
+ Microsoft Windows SDK Libraries Paths.
+
+ Return
+ ------
+ list of str
+ paths
"""
- ref = os.path.join(self.si.WindowsSdkDir, 'References')
+ ref = join(self.si.WindowsSdkDir, 'References')
libpath = []
- if self.vc_ver <= 9.0:
+ if self.vs_ver <= 9.0:
libpath += self.OSLibraries
- if self.vc_ver >= 11.0:
- libpath += [os.path.join(ref, r'CommonConfiguration\Neutral')]
+ if self.vs_ver >= 11.0:
+ libpath += [join(ref, r'CommonConfiguration\Neutral')]
- if self.vc_ver >= 14.0:
+ if self.vs_ver >= 14.0:
libpath += [
ref,
- os.path.join(self.si.WindowsSdkDir, 'UnionMetadata'),
- os.path.join(
- ref,
- 'Windows.Foundation.UniversalApiContract',
- '1.0.0.0',
- ),
- os.path.join(
- ref,
- 'Windows.Foundation.FoundationContract',
- '1.0.0.0',
- ),
- os.path.join(
- ref,
- 'Windows.Networking.Connectivity.WwanContract',
- '1.0.0.0',
- ),
- os.path.join(
- self.si.WindowsSdkDir,
- 'ExtensionSDKs',
- 'Microsoft.VCLibs',
- '%0.1f' % self.vc_ver,
- 'References',
- 'CommonConfiguration',
- 'neutral',
- ),
+ join(self.si.WindowsSdkDir, 'UnionMetadata'),
+ join(ref, 'Windows.Foundation.UniversalApiContract', '1.0.0.0'),
+ join(ref, 'Windows.Foundation.FoundationContract', '1.0.0.0'),
+ join(ref,'Windows.Networking.Connectivity.WwanContract',
+ '1.0.0.0'),
+ join(self.si.WindowsSdkDir, 'ExtensionSDKs', 'Microsoft.VCLibs',
+ '%0.1f' % self.vs_ver, 'References', 'CommonConfiguration',
+ 'neutral'),
]
return libpath
@property
def SdkTools(self):
"""
- Microsoft Windows SDK Tools
+ Microsoft Windows SDK Tools.
+
+ Return
+ ------
+ list of str
+ paths
"""
return list(self._sdk_tools())
def _sdk_tools(self):
"""
- Microsoft Windows SDK Tools paths generator
+ Microsoft Windows SDK Tools paths generator.
+
+ Return
+ ------
+ generator of str
+ paths
"""
- if self.vc_ver < 15.0:
- bin_dir = 'Bin' if self.vc_ver <= 11.0 else r'Bin\x86'
- yield os.path.join(self.si.WindowsSdkDir, bin_dir)
+ if self.vs_ver < 15.0:
+ bin_dir = 'Bin' if self.vs_ver <= 11.0 else r'Bin\x86'
+ yield join(self.si.WindowsSdkDir, bin_dir)
if not self.pi.current_is_x86():
arch_subdir = self.pi.current_dir(x64=True)
path = 'Bin%s' % arch_subdir
- yield os.path.join(self.si.WindowsSdkDir, path)
+ yield join(self.si.WindowsSdkDir, path)
- if self.vc_ver == 10.0 or self.vc_ver == 11.0:
+ if self.vs_ver in (10.0, 11.0):
if self.pi.target_is_x86():
arch_subdir = ''
else:
arch_subdir = self.pi.current_dir(hidex86=True, x64=True)
path = r'Bin\NETFX 4.0 Tools%s' % arch_subdir
- yield os.path.join(self.si.WindowsSdkDir, path)
+ yield join(self.si.WindowsSdkDir, path)
- elif self.vc_ver >= 15.0:
- path = os.path.join(self.si.WindowsSdkDir, 'Bin')
+ elif self.vs_ver >= 15.0:
+ path = join(self.si.WindowsSdkDir, 'Bin')
arch_subdir = self.pi.current_dir(x64=True)
sdkver = self.si.WindowsSdkLastVersion
- yield os.path.join(path, '%s%s' % (sdkver, arch_subdir))
+ yield join(path, '%s%s' % (sdkver, arch_subdir))
if self.si.WindowsSDKExecutablePath:
yield self.si.WindowsSDKExecutablePath
@@ -1059,7 +1342,12 @@
@property
def _sdk_subdir(self):
"""
- Microsoft Windows SDK version subdir
+ Microsoft Windows SDK version subdir.
+
+ Return
+ ------
+ str
+ subdir
"""
ucrtver = self.si.WindowsSdkLastVersion
return ('%s\\' % ucrtver) if ucrtver else ''
@@ -1067,22 +1355,32 @@
@property
def SdkSetup(self):
"""
- Microsoft Windows SDK Setup
+ Microsoft Windows SDK Setup.
+
+ Return
+ ------
+ list of str
+ paths
"""
- if self.vc_ver > 9.0:
+ if self.vs_ver > 9.0:
return []
- return [os.path.join(self.si.WindowsSdkDir, 'Setup')]
+ return [join(self.si.WindowsSdkDir, 'Setup')]
@property
def FxTools(self):
"""
- Microsoft .NET Framework Tools
+ Microsoft .NET Framework Tools.
+
+ Return
+ ------
+ list of str
+ paths
"""
pi = self.pi
si = self.si
- if self.vc_ver <= 10.0:
+ if self.vs_ver <= 10.0:
include32 = True
include64 = not pi.target_is_x86() and not pi.current_is_x86()
else:
@@ -1091,102 +1389,142 @@
tools = []
if include32:
- tools += [os.path.join(si.FrameworkDir32, ver)
+ tools += [join(si.FrameworkDir32, ver)
for ver in si.FrameworkVersion32]
if include64:
- tools += [os.path.join(si.FrameworkDir64, ver)
+ tools += [join(si.FrameworkDir64, ver)
for ver in si.FrameworkVersion64]
return tools
@property
def NetFxSDKLibraries(self):
"""
- Microsoft .Net Framework SDK Libraries
+ Microsoft .Net Framework SDK Libraries.
+
+ Return
+ ------
+ list of str
+ paths
"""
- if self.vc_ver < 14.0 or not self.si.NetFxSdkDir:
+ if self.vs_ver < 14.0 or not self.si.NetFxSdkDir:
return []
arch_subdir = self.pi.target_dir(x64=True)
- return [os.path.join(self.si.NetFxSdkDir, r'lib\um%s' % arch_subdir)]
+ return [join(self.si.NetFxSdkDir, r'lib\um%s' % arch_subdir)]
@property
def NetFxSDKIncludes(self):
"""
- Microsoft .Net Framework SDK Includes
+ Microsoft .Net Framework SDK Includes.
+
+ Return
+ ------
+ list of str
+ paths
"""
- if self.vc_ver < 14.0 or not self.si.NetFxSdkDir:
+ if self.vs_ver < 14.0 or not self.si.NetFxSdkDir:
return []
- return [os.path.join(self.si.NetFxSdkDir, r'include\um')]
+ return [join(self.si.NetFxSdkDir, r'include\um')]
@property
def VsTDb(self):
"""
- Microsoft Visual Studio Team System Database
+ Microsoft Visual Studio Team System Database.
+
+ Return
+ ------
+ list of str
+ paths
"""
- return [os.path.join(self.si.VSInstallDir, r'VSTSDB\Deploy')]
+ return [join(self.si.VSInstallDir, r'VSTSDB\Deploy')]
@property
def MSBuild(self):
"""
- Microsoft Build Engine
+ Microsoft Build Engine.
+
+ Return
+ ------
+ list of str
+ paths
"""
- if self.vc_ver < 12.0:
+ if self.vs_ver < 12.0:
return []
- elif self.vc_ver < 15.0:
+ elif self.vs_ver < 15.0:
base_path = self.si.ProgramFilesx86
arch_subdir = self.pi.current_dir(hidex86=True)
else:
base_path = self.si.VSInstallDir
arch_subdir = ''
- path = r'MSBuild\%0.1f\bin%s' % (self.vc_ver, arch_subdir)
- build = [os.path.join(base_path, path)]
+ path = r'MSBuild\%0.1f\bin%s' % (self.vs_ver, arch_subdir)
+ build = [join(base_path, path)]
- if self.vc_ver >= 15.0:
+ if self.vs_ver >= 15.0:
# Add Roslyn C# & Visual Basic Compiler
- build += [os.path.join(base_path, path, 'Roslyn')]
+ build += [join(base_path, path, 'Roslyn')]
return build
@property
def HTMLHelpWorkshop(self):
"""
- Microsoft HTML Help Workshop
+ Microsoft HTML Help Workshop.
+
+ Return
+ ------
+ list of str
+ paths
"""
- if self.vc_ver < 11.0:
+ if self.vs_ver < 11.0:
return []
- return [os.path.join(self.si.ProgramFilesx86, 'HTML Help Workshop')]
+ return [join(self.si.ProgramFilesx86, 'HTML Help Workshop')]
@property
def UCRTLibraries(self):
"""
- Microsoft Universal C Runtime SDK Libraries
+ Microsoft Universal C Runtime SDK Libraries.
+
+ Return
+ ------
+ list of str
+ paths
"""
- if self.vc_ver < 14.0:
+ if self.vs_ver < 14.0:
return []
arch_subdir = self.pi.target_dir(x64=True)
- lib = os.path.join(self.si.UniversalCRTSdkDir, 'lib')
+ lib = join(self.si.UniversalCRTSdkDir, 'lib')
ucrtver = self._ucrt_subdir
- return [os.path.join(lib, '%sucrt%s' % (ucrtver, arch_subdir))]
+ return [join(lib, '%sucrt%s' % (ucrtver, arch_subdir))]
@property
def UCRTIncludes(self):
"""
- Microsoft Universal C Runtime SDK Include
+ Microsoft Universal C Runtime SDK Include.
+
+ Return
+ ------
+ list of str
+ paths
"""
- if self.vc_ver < 14.0:
+ if self.vs_ver < 14.0:
return []
- include = os.path.join(self.si.UniversalCRTSdkDir, 'include')
- return [os.path.join(include, '%sucrt' % self._ucrt_subdir)]
+ include = join(self.si.UniversalCRTSdkDir, 'include')
+ return [join(include, '%sucrt' % self._ucrt_subdir)]
@property
def _ucrt_subdir(self):
"""
- Microsoft Universal C Runtime SDK version subdir
+ Microsoft Universal C Runtime SDK version subdir.
+
+ Return
+ ------
+ str
+ subdir
"""
ucrtver = self.si.UniversalCRTSdkLastVersion
return ('%s\\' % ucrtver) if ucrtver else ''
@@ -1194,31 +1532,52 @@
@property
def FSharp(self):
"""
- Microsoft Visual F#
+ Microsoft Visual F#.
+
+ Return
+ ------
+ list of str
+ paths
"""
- if self.vc_ver < 11.0 and self.vc_ver > 12.0:
+ if 11.0 > self.vs_ver > 12.0:
return []
- return self.si.FSharpInstallDir
+ return [self.si.FSharpInstallDir]
@property
def VCRuntimeRedist(self):
"""
- Microsoft Visual C++ runtime redistribuable dll
+ Microsoft Visual C++ runtime redistributable dll.
+
+ Return
+ ------
+ str
+ path
"""
- arch_subdir = self.pi.target_dir(x64=True)
- if self.vc_ver < 15:
- redist_path = self.si.VCInstallDir
- vcruntime = 'redist%s\\Microsoft.VC%d0.CRT\\vcruntime%d0.dll'
- else:
- redist_path = self.si.VCInstallDir.replace('\\Tools', '\\Redist')
- vcruntime = 'onecore%s\\Microsoft.VC%d0.CRT\\vcruntime%d0.dll'
+ vcruntime = 'vcruntime%d0.dll' % self.vc_ver
+ arch_subdir = self.pi.target_dir(x64=True).strip('\\')
- # Visual Studio 2017 is still Visual C++ 14.0
- dll_ver = 14.0 if self.vc_ver == 15 else self.vc_ver
+ # Installation prefixes candidates
+ prefixes = []
+ tools_path = self.si.VCInstallDir
+ redist_path = dirname(tools_path.replace(r'\Tools', r'\Redist'))
+ if isdir(redist_path):
+ # Redist version may not be exactly the same as tools
+ redist_path = join(redist_path, listdir(redist_path)[-1])
+ prefixes += [redist_path, join(redist_path, 'onecore')]
- vcruntime = vcruntime % (arch_subdir, self.vc_ver, dll_ver)
- return os.path.join(redist_path, vcruntime)
+ prefixes += [join(tools_path, 'redist')] # VS14 legacy path
+
+ # CRT directory
+ crt_dirs = ('Microsoft.VC%d.CRT' % (self.vc_ver * 10),
+ # Sometime store in directory with VS version instead of VC
+ 'Microsoft.VC%d.CRT' % (int(self.vs_ver) * 10))
+
+ # vcruntime path
+ for prefix, crt_dir in itertools.product(prefixes, crt_dirs):
+ path = join(prefix, arch_subdir, crt_dir, vcruntime)
+ if isfile(path):
+ return path
def return_env(self, exists=True):
"""
@@ -1228,6 +1587,11 @@
----------
exists: bool
It True, only return existing paths.
+
+ Return
+ ------
+ dict
+ environment
"""
env = dict(
include=self._build_paths('include',
@@ -1261,7 +1625,7 @@
self.FSharp],
exists),
)
- if self.vc_ver >= 14 and os.path.isfile(self.VCRuntimeRedist):
+ if self.vs_ver >= 14 and isfile(self.VCRuntimeRedist):
env['py_vcruntime_redist'] = self.VCRuntimeRedist
return env
@@ -1272,20 +1636,35 @@
unique, extant, directories from those paths and from
the environment variable. Raise an error if no paths
are resolved.
+
+ Parameters
+ ----------
+ name: str
+ Environment variable name
+ spec_path_lists: list of str
+ Paths
+ exists: bool
+ It True, only return existing paths.
+
+ Return
+ ------
+ str
+ Pathsep-separated paths
"""
# flatten spec_path_lists
spec_paths = itertools.chain.from_iterable(spec_path_lists)
- env_paths = safe_env.get(name, '').split(os.pathsep)
+ env_paths = environ.get(name, '').split(pathsep)
paths = itertools.chain(spec_paths, env_paths)
- extant_paths = list(filter(os.path.isdir, paths)) if exists else paths
+ extant_paths = list(filter(isdir, paths)) if exists else paths
if not extant_paths:
msg = "%s environment variable is empty" % name.upper()
raise distutils.errors.DistutilsPlatformError(msg)
unique_paths = self._unique_everseen(extant_paths)
- return os.pathsep.join(unique_paths)
+ return pathsep.join(unique_paths)
# from Python docs
- def _unique_everseen(self, iterable, key=None):
+ @staticmethod
+ def _unique_everseen(iterable, key=None):
"""
List unique elements, preserving order.
Remember all elements ever seen.
diff --git a/rpython/translator/platform/windows.py b/rpython/translator/platform/windows.py
--- a/rpython/translator/platform/windows.py
+++ b/rpython/translator/platform/windows.py
@@ -5,6 +5,7 @@
from rpython.translator.platform import CompilationError
from rpython.translator.platform import log, _run_subprocess
from rpython.translator.platform import Platform, posix
+import rpython.tool.setuptools_msvc as msvc
import rpython
rpydir = str(py.path.local(rpython.__file__).join('..'))
@@ -37,96 +38,37 @@
return _get_compiler_type(cc, True)
def _find_vcvarsall(version, x64flag):
- import rpython.tool.setuptools_msvc as msvc
if x64flag:
arch = 'x64'
else:
arch = 'x86'
- if version >= 140:
- return msvc.msvc14_get_vc_env(arch)
- else:
- return msvc.msvc9_query_vcvarsall(version / 10.0, arch)
+ return msvc.EnvironmentInfo(arch, vc_ver=version/10.0).return_env()
-def _get_msvc_env(vsver, x64flag):
+def _get_msvc_env(vcver, x64flag):
vcdict = None
toolsdir = None
+ # use setuptools from python3 to find tools
try:
- toolsdir = os.environ['VS%sCOMNTOOLS' % vsver]
- except KeyError:
- # use setuptools from python3 to find tools
- try:
- vcdict = _find_vcvarsall(vsver, x64flag)
- except ImportError as e:
- if 'setuptools' in str(e):
- log.error('is setuptools installed (perhaps try %s -mensurepip)?' % sys.executable)
- log.error('looking for compiler %s raised exception "%s' % (vsver, str(e)))
- except Exception as e:
- log.error('looking for compiler %s raised exception "%s' % (vsver, str(e)))
+ available = msvc.EnvironmentInfo('x86').si.find_reg_vs_vers()
+ if vcver / 10.0 not in available:
+ log.error('Could not find vcver %i' % vcver)
return None
- else:
- if x64flag:
- vsinstalldir = os.path.abspath(os.path.join(toolsdir, '..', '..'))
- vcinstalldir = os.path.join(vsinstalldir, 'VC')
- vcbindir = os.path.join(vcinstalldir, 'BIN')
- vcvars = os.path.join(vcbindir, 'amd64', 'vcvarsamd64.bat')
- else:
- vcvars = os.path.join(toolsdir, 'vsvars32.bat')
- if not os.path.exists(vcvars):
- # even msdn does not know which to run
- # see https://msdn.microsoft.com/en-us/library/1700bbwd(v=vs.90).aspx
- # which names both
- vcvars = os.path.join(toolsdir, 'vcvars32.bat')
-
- import subprocess
- try:
- popen = subprocess.Popen('"%s" & set' % (vcvars,),
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
-
- stdout, stderr = popen.communicate()
- if popen.wait() != 0 or stdout[:5].lower() == 'error':
- log.msg('Running "%s" errored: \n\nstdout:\n%s\n\nstderr:\n%s' % (
- vcvars, stdout.split()[0], stderr))
- return None
- else:
- log.msg('Running "%s" succeeded' %(vcvars,))
- except Exception as e:
- log.msg('Running "%s" failed: "%s"' % (vcvars, str(e)))
- return None
-
- stdout = stdout.replace("\r\n", "\n")
- vcdict = {}
- for line in stdout.split("\n"):
- if '=' not in line:
- continue
- key, value = line.split('=', 1)
- vcdict[key] = value
- env = {}
- for key, value in vcdict.items():
- if key.upper() in ['PATH', 'INCLUDE', 'LIB']:
- env[key.upper()] = value
- if 'PATH' not in env:
- log.msg('Did not find "PATH" in stdout\n%s' %(stdout))
- if not _find_executable('mt.exe', env['PATH']):
- # For some reason the sdk bin path is missing?
- # put it together from some other env variables that happened to exist
- # on the buildbot where this occurred
- if 'WindowsSDKVersion' in vcdict and 'WindowsSdkDir' in vcdict:
- binpath = vcdict['WindowsSdkDir'] + '\\bin\\' + vcdict['WindowsSDKVersion'] + 'x86'
- env['PATH'] += ';' + binpath
- if not _find_executable('mt.exe', env['PATH']):
- log.msg('Could not find mt.exe on path=%s' % env['PATH'])
- log.msg('Running vsver %s set this env' % vsver)
- for key, value in vcdict.items():
- log.msg('%s=%s' %(key, value))
- log.msg("Updated environment with vsver %d, using x64 %s" % (vsver, x64flag,))
- return env
+ vcdict = _find_vcvarsall(vcver, x64flag)
+ keys = vcdict.keys()
+ for k in keys:
+ if k.upper != k:
+ vcdict[k.upper()] = vcdict[k]
+ del vcdict[k]
+ log.error('Found vcver %i' % vcver)
+ return vcdict
+ except Exception as e:
+ log.error('looking for compiler %s raised exception "%s' % (vcver, str(e)))
+ return None
def find_msvc_env(x64flag=False, ver0=None):
- vcvers = [140, 141, 150, 90, 100]
+ vcvers = [150, 140, 141, 90, 100]
if ver0 in vcvers:
vcvers.insert(0, ver0)
- errs = []
for vsver in vcvers:
env = _get_msvc_env(vsver, x64flag)
if env is not None:
More information about the pypy-commit
mailing list