aboutsummaryrefslogtreecommitdiffstats
path: root/setuptools/msvc.py
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2017-05-30 19:39:58 -0400
committerJason R. Coombs <jaraco@jaraco.com>2017-05-30 19:39:58 -0400
commitfcdf12ee7fdf43c9dded5b68232a0fb3376d4858 (patch)
tree29baaad1490dcce705ccc5f32c6d9d9240e1d10d /setuptools/msvc.py
parent3d0cc355fb5e8012cb8c72f0e25042a5a44f31d6 (diff)
parent4dc2c76b62a5071dfacf434555dfa8ec2be0b433 (diff)
downloadexternal_python_setuptools-fcdf12ee7fdf43c9dded5b68232a0fb3376d4858.tar.gz
external_python_setuptools-fcdf12ee7fdf43c9dded5b68232a0fb3376d4858.tar.bz2
external_python_setuptools-fcdf12ee7fdf43c9dded5b68232a0fb3376d4858.zip
Merge branch 'master' into feature/re-vendor-sadface
Diffstat (limited to 'setuptools/msvc.py')
-rw-r--r--setuptools/msvc.py250
1 files changed, 175 insertions, 75 deletions
diff --git a/setuptools/msvc.py b/setuptools/msvc.py
index 447ddb38..729021ac 100644
--- a/setuptools/msvc.py
+++ b/setuptools/msvc.py
@@ -4,15 +4,17 @@ Improved support for Microsoft Visual C++ compilers.
Known supported compilers:
--------------------------
Microsoft Visual C++ 9.0:
- Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64);
- Microsoft Windows SDK 7.0 (x86, x64, ia64);
+ 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)
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)
"""
import os
@@ -94,7 +96,7 @@ def msvc9_find_vcvarsall(version):
def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs):
"""
- Patched "distutils.msvc9compiler.query_vcvarsall" for support standalones
+ Patched "distutils.msvc9compiler.query_vcvarsall" for support extra
compilers.
Set environment without use of "vcvarsall.bat".
@@ -102,9 +104,9 @@ def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs):
Known supported compilers
-------------------------
Microsoft Visual C++ 9.0:
- Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64);
- Microsoft Windows SDK 7.0 (x86, x64, ia64);
+ 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)
@@ -141,7 +143,7 @@ def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs):
def msvc14_get_vc_env(plat_spec):
"""
- Patched "distutils._msvccompiler._get_vc_env" for support standalones
+ Patched "distutils._msvccompiler._get_vc_env" for support extra
compilers.
Set environment without use of "vcvarsall.bat".
@@ -150,6 +152,8 @@ def msvc14_get_vc_env(plat_spec):
-------------------------
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
----------
@@ -272,7 +276,7 @@ class PlatformInfo:
)
def target_dir(self, hidex86=False, x64=False):
- """
+ r"""
Target platform specific subfolder.
Parameters
@@ -294,7 +298,7 @@ class PlatformInfo:
)
def cross_dir(self, forcex86=False):
- """
+ r"""
Cross platform specific subfolder.
Parameters
@@ -411,7 +415,7 @@ class RegistryInfo:
------
str: value
"""
- node64 = '' if self.pi.current_is_x86() or x86 else r'\Wow6432Node'
+ node64 = '' if self.pi.current_is_x86() or x86 else 'Wow6432Node'
return os.path.join('Software', node64, 'Microsoft', key)
def lookup(self, key, name):
@@ -470,25 +474,26 @@ class SystemInfo:
def __init__(self, registry_info, vc_ver=None):
self.ri = registry_info
self.pi = self.ri.pi
- if vc_ver:
- self.vc_ver = vc_ver
- else:
- try:
- self.vc_ver = self.find_available_vc_vers()[-1]
- except IndexError:
- err = 'No Microsoft Visual C++ version found'
- raise distutils.errors.DistutilsPlatformError(err)
+ 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)
def find_available_vc_vers(self):
"""
Find all available Microsoft Visual C++ versions.
"""
- vckeys = (self.ri.vc, self.ri.vc_for_python)
+ ms = self.ri.microsoft
+ vckeys = (self.ri.vc, self.ri.vc_for_python, self.ri.vs)
vc_vers = []
for hkey in self.ri.HKEYS:
for key in vckeys:
try:
- bkey = winreg.OpenKey(hkey, key, 0, winreg.KEY_READ)
+ bkey = winreg.OpenKey(hkey, ms(key), 0, winreg.KEY_READ)
except (OSError, IOError):
continue
subkeys, values, _ = winreg.QueryInfoKey(bkey)
@@ -525,9 +530,9 @@ class SystemInfo:
"""
Microsoft Visual C++ directory.
"""
- # Default path
- default = r'Microsoft Visual Studio %0.1f\VC' % self.vc_ver
- guess_vc = os.path.join(self.ProgramFilesx86, default)
+ self.VSInstallDir
+
+ 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)
@@ -543,12 +548,34 @@ class SystemInfo:
return path
+ def _guess_vc(self):
+ """
+ Locate Visual C for 2017
+ """
+ if self.vc_ver <= 14.0:
+ return
+
+ default = r'VC\Tools\MSVC'
+ guess_vc = os.path.join(self.VSInstallDir, default)
+ # 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)
+ except (OSError, IOError, IndexError):
+ pass
+
+ def _guess_vc_legacy(self):
+ """
+ Locate Visual C for versions prior to 2017
+ """
+ default = r'Microsoft Visual Studio %0.1f\VC' % self.vc_ver
+ return os.path.join(self.ProgramFilesx86, default)
+
@property
def WindowsSdkVersion(self):
"""
- Microsoft Windows SDK versions.
+ Microsoft Windows SDK versions for specified MSVC++ version.
"""
- # Set Windows SDK versions for specified MSVC++ version
if self.vc_ver <= 9.0:
return ('7.0', '6.1', '6.0a')
elif self.vc_ver == 10.0:
@@ -561,6 +588,14 @@ class SystemInfo:
return ('10.0', '8.1')
@property
+ def WindowsSdkLastVersion(self):
+ """
+ Microsoft Windows SDK last version
+ """
+ return self._use_last_dir_name(os.path.join(
+ self.WindowsSdkDir, 'lib'))
+
+ @property
def WindowsSdkDir(self):
"""
Microsoft Windows SDK directory.
@@ -658,6 +693,14 @@ class SystemInfo:
return sdkdir or ''
@property
+ def UniversalCRTSdkLastVersion(self):
+ """
+ Microsoft Universal C Runtime SDK last version
+ """
+ return self._use_last_dir_name(os.path.join(
+ self.UniversalCRTSdkDir, 'lib'))
+
+ @property
def NetFxSdkVersion(self):
"""
Microsoft .NET Framework SDK versions.
@@ -716,7 +759,7 @@ class SystemInfo:
"""
return self._find_dot_net_versions(64)
- def _find_dot_net_versions(self, bits=32):
+ def _find_dot_net_versions(self, bits):
"""
Find Microsoft .NET Framework versions.
@@ -725,8 +768,10 @@ class SystemInfo:
bits: int
Platform number of bits: 32 or 64.
"""
- # Find actual .NET version
- ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits) or ''
+ # Find actual .NET version in registry
+ reg_ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits)
+ dot_net_dir = getattr(self, 'FrameworkDir%d' % bits)
+ 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:
@@ -740,6 +785,25 @@ class SystemInfo:
frameworkver = ('v3.0', 'v2.0.50727')
return frameworkver
+ def _use_last_dir_name(self, path, prefix=''):
+ """
+ Return name of the last dir in path or '' if no dir found.
+
+ Parameters
+ ----------
+ path: str
+ Use dirs in this path
+ prefix: str
+ Use only dirs startings by this prefix
+ """
+ matching_dirs = (
+ dir_name
+ for dir_name in reversed(os.listdir(path))
+ if os.path.isdir(os.path.join(path, dir_name)) and
+ dir_name.startswith(prefix)
+ )
+ return next(matching_dirs, None) or ''
+
class EnvironmentInfo:
"""
@@ -765,15 +829,14 @@ class EnvironmentInfo:
# Variables and properties in this class use originals CamelCase variables
# names from Microsoft source files for more easy comparaison.
- def __init__(self, arch, vc_ver=None, vc_min_ver=None):
+ def __init__(self, arch, vc_ver=None, vc_min_ver=0):
self.pi = PlatformInfo(arch)
self.ri = RegistryInfo(self.pi)
self.si = SystemInfo(self.ri, vc_ver)
- if vc_min_ver:
- if self.vc_ver < vc_min_ver:
- err = 'No suitable Microsoft Visual C++ version found'
- raise distutils.errors.DistutilsPlatformError(err)
+ if self.vc_ver < vc_min_ver:
+ err = 'No suitable Microsoft Visual C++ version found'
+ raise distutils.errors.DistutilsPlatformError(err)
@property
def vc_ver(self):
@@ -810,7 +873,10 @@ class EnvironmentInfo:
"""
Microsoft Visual C++ & Microsoft Foundation Class Libraries
"""
- arch_subdir = self.pi.target_dir(hidex86=True)
+ if self.vc_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:
@@ -840,10 +906,20 @@ class EnvironmentInfo:
if arch_subdir:
tools += [os.path.join(si.VCInstallDir, 'Bin%s' % arch_subdir)]
- if self.vc_ver >= 14.0:
+ if self.vc_ver == 14.0:
path = 'Bin%s' % self.pi.current_dir(hidex86=True)
tools += [os.path.join(si.VCInstallDir, path)]
+ elif self.vc_ver >= 15.0:
+ host_dir = (r'bin\HostX86%s' if self.pi.current_is_x86() else
+ r'bin\HostX64%s')
+ tools += [os.path.join(
+ si.VCInstallDir, host_dir % self.pi.target_dir(x64=True))]
+
+ if self.pi.current_cpu != self.pi.target_cpu:
+ tools += [os.path.join(
+ si.VCInstallDir, host_dir % self.pi.current_dir(x64=True))]
+
else:
tools += [os.path.join(si.VCInstallDir, 'Bin')]
@@ -861,8 +937,8 @@ class EnvironmentInfo:
else:
arch_subdir = self.pi.target_dir(x64=True)
lib = os.path.join(self.si.WindowsSdkDir, 'lib')
- libver = self._get_content_dirname(lib)
- return [os.path.join(lib, '%sum%s' % (libver, arch_subdir))]
+ libver = self._sdk_subdir
+ return [os.path.join(lib, '%sum%s' % (libver , arch_subdir))]
@property
def OSIncludes(self):
@@ -876,7 +952,7 @@ class EnvironmentInfo:
else:
if self.vc_ver >= 14.0:
- sdkver = self._get_content_dirname(include)
+ sdkver = self._sdk_subdir
else:
sdkver = ''
return [os.path.join(include, '%sshared' % sdkver),
@@ -933,13 +1009,20 @@ class EnvironmentInfo:
"""
Microsoft Windows SDK Tools
"""
- bin_dir = 'Bin' if self.vc_ver <= 11.0 else r'Bin\x86'
- tools = [os.path.join(self.si.WindowsSdkDir, bin_dir)]
+ return list(self._sdk_tools())
+
+ def _sdk_tools(self):
+ """
+ Microsoft Windows SDK Tools paths generator
+ """
+ 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 not self.pi.current_is_x86():
arch_subdir = self.pi.current_dir(x64=True)
path = 'Bin%s' % arch_subdir
- tools += [os.path.join(self.si.WindowsSdkDir, path)]
+ yield os.path.join(self.si.WindowsSdkDir, path)
if self.vc_ver == 10.0 or self.vc_ver == 11.0:
if self.pi.target_is_x86():
@@ -947,12 +1030,24 @@ class EnvironmentInfo:
else:
arch_subdir = self.pi.current_dir(hidex86=True, x64=True)
path = r'Bin\NETFX 4.0 Tools%s' % arch_subdir
- tools += [os.path.join(self.si.WindowsSdkDir, path)]
+ yield os.path.join(self.si.WindowsSdkDir, path)
+
+ elif self.vc_ver >= 15.0:
+ path = os.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))
if self.si.WindowsSDKExecutablePath:
- tools += [self.si.WindowsSDKExecutablePath]
+ yield self.si.WindowsSDKExecutablePath
- return tools
+ @property
+ def _sdk_subdir(self):
+ """
+ Microsoft Windows SDK version subdir
+ """
+ ucrtver = self.si.WindowsSdkLastVersion
+ return ('%s\\' % ucrtver) if ucrtver else ''
@property
def SdkSetup(self):
@@ -1023,10 +1118,21 @@ class EnvironmentInfo:
"""
if self.vc_ver < 12.0:
return []
+ elif self.vc_ver < 15.0:
+ base_path = self.si.ProgramFilesx86
+ arch_subdir = self.pi.current_dir(hidex86=True)
+ else:
+ base_path = self.si.VSInstallDir
+ arch_subdir = ''
- arch_subdir = self.pi.current_dir(hidex86=True)
path = r'MSBuild\%0.1f\bin%s' % (self.vc_ver, arch_subdir)
- return [os.path.join(self.si.ProgramFilesx86, path)]
+ build = [os.path.join(base_path, path)]
+
+ if self.vc_ver >= 15.0:
+ # Add Roslyn C# & Visual Basic Compiler
+ build += [os.path.join(base_path, path, 'Roslyn')]
+
+ return build
@property
def HTMLHelpWorkshop(self):
@@ -1041,27 +1147,34 @@ class EnvironmentInfo:
@property
def UCRTLibraries(self):
"""
- Microsoft Universal CRT Libraries
+ Microsoft Universal C Runtime SDK Libraries
"""
if self.vc_ver < 14.0:
return []
arch_subdir = self.pi.target_dir(x64=True)
lib = os.path.join(self.si.UniversalCRTSdkDir, 'lib')
- ucrtver = self._get_content_dirname(lib)
+ ucrtver = self._ucrt_subdir
return [os.path.join(lib, '%sucrt%s' % (ucrtver, arch_subdir))]
@property
def UCRTIncludes(self):
"""
- Microsoft Universal CRT Include
+ Microsoft Universal C Runtime SDK Include
"""
if self.vc_ver < 14.0:
return []
include = os.path.join(self.si.UniversalCRTSdkDir, 'include')
- ucrtver = self._get_content_dirname(include)
- return [os.path.join(include, '%sucrt' % ucrtver)]
+ return [os.path.join(include, '%sucrt' % self._ucrt_subdir)]
+
+ @property
+ def _ucrt_subdir(self):
+ """
+ Microsoft Universal C Runtime SDK version subdir
+ """
+ ucrtver = self.si.UniversalCRTSdkLastVersion
+ return ('%s\\' % ucrtver) if ucrtver else ''
@property
def FSharp(self):
@@ -1079,9 +1192,18 @@ class EnvironmentInfo:
Microsoft Visual C++ runtime redistribuable dll
"""
arch_subdir = self.pi.target_dir(x64=True)
- vcruntime = 'redist%s\\Microsoft.VC%d0.CRT\\vcruntime%d0.dll'
- vcruntime = vcruntime % (arch_subdir, self.vc_ver, self.vc_ver)
- return os.path.join(self.si.VCInstallDir, vcruntime)
+ 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'
+
+ # Visual Studio 2017 is still Visual C++ 14.0
+ dll_ver = 14.0 if self.vc_ver == 15 else self.vc_ver
+
+ vcruntime = vcruntime % (arch_subdir, self.vc_ver, dll_ver)
+ return os.path.join(redist_path, vcruntime)
def return_env(self, exists=True):
"""
@@ -1169,25 +1291,3 @@ class EnvironmentInfo:
if k not in seen:
seen_add(k)
yield element
-
- def _get_content_dirname(self, path):
- """
- Return name of the first dir in path or '' if no dir found.
-
- Parameters
- ----------
- path: str
- Path where search dir.
-
- Return
- ------
- foldername: str
- "name\" or ""
- """
- try:
- name = os.listdir(path)
- if name:
- return '%s\\' % name[0]
- return ''
- except (OSError, IOError):
- return ''