summaryrefslogtreecommitdiff
path: root/setuptools
diff options
context:
space:
mode:
authorJGoutin <ginnungagap@free.fr>2016-03-03 18:00:58 +0000
committerJGoutin <ginnungagap@free.fr>2016-03-03 18:00:58 +0000
commit72db3cf5ff66ddab3f6e14880f5545d759938ae6 (patch)
tree9db0e76b41891a6d19e060ff44c8466e8ef8ffbf /setuptools
parent75282e5568039e3dae52ee41ada35baf56f0567c (diff)
downloadpython-setuptools-git-72db3cf5ff66ddab3f6e14880f5545d759938ae6.tar.gz
* Move non registry parts from RegistryInfo to SystemInfo.
* Rename many variable to use the same names as in MSVC .bat files. This really help to compare the Python script with original sources. * Split compute_env to EnvironmentInfo class. * Continue to add support for MSVC14. * Some more little fixes.
Diffstat (limited to 'setuptools')
-rw-r--r--setuptools/msvc9_support.py775
1 files changed, 509 insertions, 266 deletions
diff --git a/setuptools/msvc9_support.py b/setuptools/msvc9_support.py
index a956a5b0..8835c22d 100644
--- a/setuptools/msvc9_support.py
+++ b/setuptools/msvc9_support.py
@@ -4,6 +4,7 @@ This module improve support for Microsoft Visual C++ compilers. (Windows Only)
import os
import itertools
import distutils.errors
+import winreg
try:
# Distutil file for MSVC++ 9.0 and upper
@@ -30,16 +31,16 @@ def patch_for_specialized_compiler():
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 Windows SDK 6.1 (x86, x64, ia64)
+ Microsoft Visual C++ 9.0:
+ Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64);
+ Microsoft Windows SDK 7.0 (x86, x64, ia64);
+ Microsoft Windows SDK 6.1 (x86, x64, ia64)
- Microsoft Visual C++ 10.0:
- Microsoft Windows SDK 7.1 (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 C++ 14.0:
+ Microsoft Visual C++ Build Tools 2015 (x86, x64, arm)
"""
if 'distutils' not in globals():
# The module isn't available to be patched
@@ -74,8 +75,8 @@ def msvc9_find_vcvarsall(version):
Known supported compilers
-------------------------
- Microsoft Visual C++ 9.0:
- Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64)
+ Microsoft Visual C++ 9.0:
+ Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64)
Parameters
----------
@@ -115,13 +116,13 @@ 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 Windows SDK 6.1 (x86, x64, ia64)
+ Microsoft Visual C++ 9.0:
+ Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64);
+ Microsoft Windows SDK 7.0 (x86, x64, ia64);
+ Microsoft Windows SDK 6.1 (x86, x64, ia64)
- Microsoft Visual C++ 10.0:
- Microsoft Windows SDK 7.1 (x86, x64, ia64)
+ Microsoft Visual C++ 10.0:
+ Microsoft Windows SDK 7.1 (x86, x64, ia64)
Parameters
----------
@@ -138,15 +139,15 @@ def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs):
try:
return unpatched['msvc9_query_vcvarsall'](ver, arch, *args, **kwargs)
except distutils.errors.DistutilsPlatformError:
- # Error if Vcvarsall.bat is missing
+ # Pass error if Vcvarsall.bat is missing
pass
except ValueError:
- # Error if environment not set after executing vcvarsall.bat
+ # Pass error if environment not set after executing vcvarsall.bat
pass
- # If vcvarsall.bat fail, try to set environment directly
+ # If error, try to set environment directly
try:
- return _compute_env(ver, arch)
+ return EnvironmentInfo(arch, ver).return_env()
except distutils.errors.DistutilsPlatformError as exc:
_augment_exception(exc, ver, arch)
raise
@@ -159,8 +160,8 @@ def msvc14_get_vc_env(plat_spec):
Known supported compilers
-------------------------
- Microsoft Visual C++ 14.0:
- Microsoft Visual C++ Build Tools 2015 (x86, x64, arm)
+ Microsoft Visual C++ 14.0:
+ Microsoft Visual C++ Build Tools 2015 (x86, x64, arm)
Parameters
----------
@@ -171,21 +172,22 @@ def msvc14_get_vc_env(plat_spec):
------
environment: dict
"""
+ # Try to get environement from vcvarsall.bat (Classical way)
try:
return unpatched['msv14_get_vc_env'](plat_spec)
except distutils.errors.DistutilsPlatformError:
- # Error if Vcvarsall.bat is missing
+ # Pass error Vcvarsall.bat is missing
pass
- # If vcvarsall.bat fail, try to set environment directly
+ # If error, try to set environment directly
try:
- return _compute_env(version, plat_spec)
+ return EnvironmentInfo(plat_spec, vcvermin=14.0).return_env()
except distutils.errors.DistutilsPlatformError as exc:
- _augment_exception(exc, version, plat_spec)
+ _augment_exception(exc, 14.0)
raise
-def _augment_exception(exc, version, arch):
+def _augment_exception(exc, version, arch=''):
"""
Add details to the exception message to help guide the user
as to what action will resolve it.
@@ -193,32 +195,33 @@ def _augment_exception(exc, version, arch):
# Error if MSVC++ directory not found or environment not set
message = exc.args[0]
- if "vcvarsall.bat" in message:
+ if "vcvarsall" in message.lower() or "visual c" in message.lower():
# Special error message if MSVC++ not installed
message = 'Microsoft Visual C++ %0.1f is required (%s).' %\
(version, message)
- if int(version) == 9:
+ msdownload = r'www.microsoft.com/download/details.aspx?id=%d'
+ 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 += r'www.microsoft.com/download/details.aspx?id=3138'
+ message += msdownload % 3138
else:
# For VC++ 9.0 redirect user to Vc++ for Python 2.7 :
# This redirection link is maintained by Microsoft.
# Contact vspython@microsoft.com if it needs updating.
message += r' Get it from http://aka.ms/vcpython27'
- elif int(version) == 10:
+ elif version == 10.0:
# For VC++ 10.0 Redirect user to Windows SDK 7.1
message += ' Get it with "Microsoft Windows SDK 7.1": '
- message += r'www.microsoft.com/download/details.aspx?id=8279'
+ message += msdownload % 8279
exc.args[0] = message
class PlatformInfo:
"""
- Find architecture informations and system paths.
+ Current and Target Architectures informations.
Parameters
----------
@@ -226,9 +229,6 @@ class PlatformInfo:
Target architecture.
"""
current_cpu = os.environ['processor_architecture'].lower()
- win_dir = os.environ['WinDir']
- program_files = os.environ['ProgramFiles']
- program_files_x86 = os.environ.get('ProgramFiles(x86)', program_files)
def __init__(self, arch):
self.arch = arch.lower()
@@ -241,9 +241,9 @@ class PlatformInfo:
return self.target_cpu == 'x86'
def current_is_x86(self):
- return self.current_cpu != 'x86'
+ return self.current_cpu == 'x86'
- def ccpu_dir(self, hidex86=False, x64=False):
+ def current_dir(self, hidex86=False, x64=False):
"""
Current platform specific subfolder.
@@ -256,7 +256,8 @@ class PlatformInfo:
Return
------
- subfolder: str (starting with'\')
+ subfolder: str
+ "\target"
"""
return (
'' if (self.current_cpu == 'x86' and hidex86) else
@@ -264,7 +265,7 @@ class PlatformInfo:
r'\%s' % self.current_cpu
)
- def tcpu_dir(self, hidex86=False, x64=False):
+ def target_dir(self, hidex86=False, x64=False):
"""
Target platform specific subfolder.
@@ -277,7 +278,8 @@ class PlatformInfo:
Return
------
- subfolder: str (starting with'\')
+ subfolder: str
+ "\current"
"""
return (
'' if (self.target_cpu == 'x86' and hidex86) else
@@ -285,9 +287,9 @@ class PlatformInfo:
r'\%s' % self.target_cpu
)
- def tools_extra(self, forcex86=False):
+ def cross_dir(self, forcex86=False):
"""
- Platform specific subfolder for Visual C++ Tools.
+ Cross platform specific subfolder.
Parameters
----------
@@ -297,9 +299,11 @@ class PlatformInfo:
Return
------
- subfolder: str (starting with'\')
+ subfolder: str
+ "\current" if target architecture is current architecture,
+ "\current_target" if not.
"""
- path = self.tcpu_dir(True)
+ path = self.target_dir(True)
if self.target_cpu != self.current_cpu:
current = 'x86' if forcex86 else self.current_cpu
path = path.replace('\\', '\\%s_' % current)
@@ -308,24 +312,25 @@ class PlatformInfo:
class RegistryInfo:
"""
- Find Microsoft Visual C++ compiler related paths using registry or
- default paths.
+ Microsoft Visual Studio related registry informations.
Parameters
----------
- platform_info: platform_info
- "platform_info" instance.
- version: float
- Required Microsoft Visual C++ version.
+ platform_info: PlatformInfo
+ "PlatformInfo" instance.
"""
- def __init__(self, platform_info, version):
+ HKEYS = (winreg.HKEY_USERS,
+ winreg.HKEY_CURRENT_USER,
+ winreg.HKEY_LOCAL_MACHINE,
+ winreg.HKEY_CLASSES_ROOT)
+
+ def __init__(self, platform_info):
self.pi = platform_info
- self.version = version
@property
def microsoft(self):
"""
- Microsoft registry path.
+ Microsoft software registry key.
"""
return os.path.join(
'Software',
@@ -336,292 +341,530 @@ class RegistryInfo:
@property
def sxs(self):
"""
- Visual Studio SxS registry path.
+ Microsoft Visual Studio SxS registry key.
"""
return os.path.join(self.microsoft, r'VisualStudio\SxS')
@property
def vc(self):
"""
- Visual C++ registry path.
+ Microsoft Visual C++ registry key.
"""
return os.path.join(self.sxs, 'VC7')
@property
def vs(self):
"""
- Visual Studio registry path.
+ Microsoft Visual Studio registry key.
"""
return os.path.join(self.sxs, 'VS7')
@property
def vc_for_python(self):
"""
- Visual C++ for Python.
+ Microsoft Visual C++ for Python registry key.
"""
- path = r'DevDiv\VCForPython\%0.1f' % self.version
+ path = r'DevDiv\VCForPython'
return os.path.join(self.microsoft, path)
@property
def windows_sdk(self):
"""
- Windows/Platform SDK registry path.
+ Microsoft Windows/Platform SDK registry key.
"""
return os.path.join(self.microsoft, r'Microsoft SDKs\Windows')
- def find_visual_studio(self):
+ def lookup(self, key, name):
+ """
+ Look for values in registry.
+
+ Parameters
+ ----------
+ key: str
+ Registry key path where look.
+ name: str
+ Value name to find.
+
+ Return
+ ------
+ str: value
+ """
+ for hkey in self.HKEYS:
+ try:
+ bkey = winreg.OpenKey(hkey, key, 0, winreg.KEY_READ)
+ except FileNotFoundError:
+ continue
+ try:
+ return winreg.QueryValueEx(bkey, name)[0]
+ except FileNotFoundError:
+ pass
+
+
+class SystemInfo:
+ """
+ Microsoft Windows and Visual Studio related system inormations.
+
+ Parameters
+ ----------
+ registry_info: RegistryInfo
+ "RegistryInfo" instance.
+ vcver: float
+ Required Microsoft Visual C++ version.
+ """
+ WinDir = os.environ['WinDir']
+ ProgramFiles = os.environ['ProgramFiles']
+ ProgramFilesx86 = os.environ.get('ProgramFiles(x86)', ProgramFiles)
+
+ def __init__(self, registry_info, vcver=None):
+ self.ri = registry_info
+ if vcver:
+ self.vcver = vcver
+ else:
+ try:
+ self.vcver = self.find_availables_vcver()[-1]
+ except IndexError:
+ err = 'No Microsoft Visual C++ version found'
+ raise distutils.errors.DistutilsPlatformError(err)
+
+ def find_availables_vcver(self):
+ """
+ Find all availables Microsoft Visual C++ versions.
+ """
+ vckeys = (self.ri.vc, self.ri.vc_for_python)
+ vsvers = []
+ for hkey in self.ri.HKEYS:
+ for key in vckeys:
+ try:
+ bkey = winreg.OpenKey(hkey, key, 0, winreg.KEY_READ)
+ except FileNotFoundError:
+ continue
+ subkeys, values, _ = winreg.QueryInfoKey(bkey)
+ for i in range(values):
+ try:
+ ver = float(winreg.EnumValue(bkey, i)[0])
+ if ver not in vsvers:
+ vsvers.append(ver)
+ except ValueError:
+ pass
+ for i in range(subkeys):
+ try:
+ ver = float(winreg.EnumKey(bkey, i))
+ if ver not in vsvers:
+ vsvers.append(ver)
+ except ValueError:
+ pass
+ return sorted(vsvers)
+
+ @property
+ def VSInstallDir(self):
"""
- Find Microsoft Visual Studio directory.
+ Microsoft Visual Studio directory.
"""
# Default path
- name = 'Microsoft Visual Studio %0.1f' % self.version
- default = os.path.join(self.pi.program_files_x86, name)
+ name = 'Microsoft Visual Studio %0.1f' % self.vcver
+ default = os.path.join(self.ProgramFilesx86, name)
# Try to get path from registry, if fail use default path
- return self._lookup(self.vs, '%0.1f' % self.version) or default
+ return self.ri.lookup(self.ri.vs, '%0.1f' % self.vcver) or default
- def find_visual_c(self):
+ @property
+ def VCInstallDir(self):
"""
- Find Microsoft Visual C++ directory.
+ Microsoft Visual C++ directory.
"""
# Default path
- default = r'Microsoft Visual Studio %0.1f\VC' % self.version
- guess_vc = os.path.join(self.pi.program_files_x86, default)
+ default = r'Microsoft Visual Studio %0.1f\VC' % self.vcver
+ guess_vc = os.path.join(self.ProgramFilesx86, default)
# Try to get "VC++ for Python" path from registry as default path
- python_vc = self._lookup(self.vc_for_python, 'installdir')
+ path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vcver)
+ python_vc = self.ri.lookup(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
- result = self._lookup(self.vc, '%0.1f' % self.version) or default_vc
+ result = self.ri.lookup(self.ri.vc, '%0.1f' % self.vcver) or default_vc
if not os.path.isdir(result):
- msg = 'vcvarsall.bat and Visual C++ directory not found'
+ msg = 'Microsoft Visual C++ directory not found'
raise distutils.errors.DistutilsPlatformError(msg)
return result
- def find_windows_sdk(self):
+ @property
+ def WindowsSdkDir(self):
"""
- Find Microsoft Windows SDK directory.
+ Microsoft Windows SDK directory.
"""
- WindowsSdkDir = ''
- if self.version == 9.0:
- WindowsSdkVer = ('7.0', '6.1', '6.0a')
- elif self.version == 10.0:
- WindowsSdkVer = ('7.1', '7.0a')
+ sdkdir = ''
+ if self.vcver == 9.0:
+ sdkver = ('7.0', '6.1', '6.0a')
+ elif self.vcver == 10.0:
+ sdkver = ('7.1', '7.0a')
+ elif self.vcver == 14.0:
+ sdkver = ('10.0', '8.1', '8.1a')
else:
- WindowsSdkVer = ()
- for ver in WindowsSdkVer:
+ sdkver = ()
+ for ver in sdkver:
# Try to get it from registry
- loc = os.path.join(self.windows_sdk, 'v%s' % ver)
- WindowsSdkDir = self._lookup(loc, 'installationfolder')
- if WindowsSdkDir:
+ loc = os.path.join(self.ri.windows_sdk, 'v%s' % ver)
+ sdkdir = self.ri.lookup(loc, 'installationfolder')
+ if sdkdir:
break
- if not WindowsSdkDir or not os.path.isdir(WindowsSdkDir):
+ if not sdkdir or not os.path.isdir(sdkdir):
# Try to get "VC++ for Python" version from registry
- install_base = self._lookup(self.vc_for_python, 'installdir')
+ path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vcver)
+ install_base = self.ri.lookup(path, 'installdir')
if install_base:
- WindowsSdkDir = os.path.join(install_base, 'WinSDK')
- if not WindowsSdkDir or not os.path.isdir(WindowsSdkDir):
- # If fail, use default path
- for ver in WindowsSdkVer:
+ sdkdir = os.path.join(install_base, 'WinSDK')
+ if not sdkdir or not os.path.isdir(sdkdir):
+ # If fail, use default new path
+ for ver in sdkver:
+ intver = ver[:ver.rfind('.')]
+ path = r'Microsoft SDKs\Windows Kits\%s' % (intver)
+ d = os.path.join(self.ProgramFiles, path)
+ if os.path.isdir(d):
+ sdkdir = d
+ if not sdkdir or not os.path.isdir(sdkdir):
+ # If fail, use default old path
+ for ver in sdkver:
path = r'Microsoft SDKs\Windows\v%s' % ver
- d = os.path.join(self.pi.program_files, path)
+ d = os.path.join(self.ProgramFiles, path)
if os.path.isdir(d):
- WindowsSdkDir = d
- if not WindowsSdkDir:
+ sdkdir = d
+ if not sdkdir:
# If fail, use Platform SDK
- WindowsSdkDir = os.path.join(self.find_visual_c(), 'PlatformSDK')
- return WindowsSdkDir
-
- def find_dot_net_versions(self):
- """
- Find Microsoft .NET Framework Versions.
- """
- if self.version == 10.0:
- v4 = self._lookup(self.vc, 'frameworkver32') or ''
- if v4.lower()[:2] != 'v4':
- v4 = None
- # default to last v4 version
- v4 = v4 or 'v4.0.30319'
- FrameworkVer = (v4, 'v3.5')
- elif self.version == 9.0:
- FrameworkVer = ('v3.5', 'v2.0.50727')
- elif self.version == 8.0:
- FrameworkVer = ('v3.0', 'v2.0.50727')
- return FrameworkVer
+ sdkdir = os.path.join(self.VCInstallDir, 'PlatformSDK')
+ return sdkdir
- def find_dot_net_32(self):
+ @property
+ def FrameworkDir32(self):
"""
- Find Microsoft .NET Framework 32bit directory.
+ Microsoft .NET Framework 32bit directory.
"""
# Default path
- guess_fw = os.path.join(self.pi.win_dir, r'Microsoft.NET\Framework')
+ guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework')
# Try to get path from registry, if fail use default path
- return self._lookup(self.vc, 'frameworkdir32') or guess_fw
+ return self.ri.lookup(self.ri.vc, 'frameworkdir32') or guess_fw
- def find_dot_net_64(self):
+ @property
+ def FrameworkDir64(self):
"""
- Find Microsoft .NET Framework 64bit directory.
+ Microsoft .NET Framework 64bit directory.
"""
# Default path
- guess_fw = os.path.join(self.pi.win_dir, r'Microsoft.NET\Framework64')
+ guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework64')
# Try to get path from registry, if fail use default path
- return self._lookup(self.vc, 'frameworkdir64') or guess_fw
+ return self.ri.lookup(self.ri.vc, 'frameworkdir64') or guess_fw
- def _lookup(self, base, key):
- try:
- return msvc9compiler.Reg.get_value(base, key)
- except KeyError:
- pass
+ @property
+ def FrameworkVersion32(self):
+ """
+ Microsoft .NET Framework 32bit versions.
+ """
+ return self._find_dot_net_versions(32)
+
+ @property
+ def FrameworkVersion64(self):
+ """
+ Microsoft .NET Framework 64bit versions.
+ """
+ return self._find_dot_net_versions(64)
+ def _find_dot_net_versions(self, bits=32):
+ """
+ Find Microsoft .NET Framework versions.
-def _compute_env(version, arch):
+ Parameters
+ ----------
+ bits: int
+ Platform number of bits: 32 or 64.
+ """
+ # Find actual .NET version
+ ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits) or ''
+
+ # Set .NET versions for specified MSVC++ version
+ if self.vcver >= 14.0:
+ frameworkver = (ver, 'v4.0')
+ elif self.vcver == 10.0:
+ if ver.lower()[:2] != 'v4':
+ ver = ''
+ ver = ver or 'v4.0.30319'
+ frameworkver = (ver, 'v3.5')
+ elif self.vcver == 9.0:
+ frameworkver = ('v3.5', 'v2.0.50727')
+ elif self.vcver == 8.0:
+ frameworkver = ('v3.0', 'v2.0.50727')
+ return frameworkver
+
+
+class EnvironmentInfo:
"""
Return environment variables for specified Microsoft Visual C++ version
- and platform.
+ and platform : Lib, Include, Path and libpath.
- Microsoft Visual C++ known compatibles versions
- -----------------------------------------------
- 9.0, 10.0, 14.0
- """
- pi = PlatformInfo(arch)
- reg = RegistryInfo(pi, version)
-
- # Set Microsoft Visual Studio Tools
- paths = [r'Common7\IDE', r'Common7\Tools']
- if version >= 14.0:
- paths.append(r'Common7\IDE\CommonExtensions\Microsoft\TestWindow')
- paths.append(r'Team Tools\Performance Tools')
- paths.append(r'Team Tools\Performance Tools' + pi.ccpu_dir(True, True))
- VSTools = [os.path.join(reg.find_visual_studio(), path) for path in paths]
-
- # Set Microsoft Visual C++ & Microsoft Foundation Class Includes
- VCIncludes = [os.path.join(reg.find_visual_c(), 'Include'),
- os.path.join(reg.find_visual_c(), 'ATLMFC\Include')]
-
- # Set Microsoft Visual C++ & Microsoft Foundation Class Libraries
- paths = ['Lib' + pi.tcpu_dir(True), r'ATLMFC\Lib' + pi.tcpu_dir(True)]
- if version >= 14.0:
- paths.append(r'Lib\store' + pi.tcpu_dir(True))
- VCLibraries = [os.path.join(reg.find_visual_c(), path) for path in paths]
-
- # Set Microsoft Visual C++ store references Libraries
- if version >= 14.0:
- path = r'Lib\store\references'
- VCStoreRefs = [os.path.join(reg.find_visual_c(), path)]
- else:
- VCStoreRefs = []
-
- # Set Microsoft Visual C++ Tools
- path = 'Bin' + pi.tools_extra(False if version >= 14.0 else True)
- VCTools = [
- os.path.join(reg.find_visual_c(), 'VCPackages'),
- os.path.join(reg.find_visual_c(), path),
- ]
- if pi.tools_extra() and version >= 14.0:
- path = 'Bin' + pi.ccpu_dir(True)
- VCTools.append(os.path.join(reg.find_visual_c(), path))
- else:
- VCTools.append(os.path.join(reg.find_visual_c(), 'Bin'))
-
- # Set Microsoft Windows SDK Libraries
- path = 'Lib' + pi.tcpu_dir(True, True)
- OSLibraries = [os.path.join(reg.find_windows_sdk(), path)]
-
- # Set Microsoft Windows SDK Include
- OSIncludes = [
- os.path.join(reg.find_windows_sdk(), 'Include'),
- os.path.join(reg.find_windows_sdk(), r'Include\gl'),
- ]
-
- # Set Microsoft Windows SDK Tools
- SdkTools = [os.path.join(reg.find_windows_sdk(), 'Bin')]
- if not pi.target_is_x86():
- path = 'Bin' + pi.tcpu_dir(True, True)
- SdkTools.append(os.path.join(reg.find_windows_sdk(), path))
- if version == 10.0:
- path = r'Bin\NETFX 4.0 Tools' + pi.tcpu_dir(True, True)
- SdkTools.append(os.path.join(reg.find_windows_sdk(), path))
-
- # Set Microsoft Windows SDK Setup
- SdkSetup = [os.path.join(reg.find_windows_sdk(), 'Setup')]
-
- # Set Microsoft .NET Framework Tools
- roots = [reg.find_dot_net_32()]
- include_64_framework = not pi.target_is_x86() and not pi.current_is_x86()
- roots += [reg.find_dot_net_64()] if include_64_framework else []
-
- FxTools = [
- os.path.join(root, ver)
- for root, ver in itertools.product(roots, reg.find_dot_net_versions())
- ]
-
- # Set Microsoft Visual Studio Team System Database
- VsTDb = [os.path.join(reg.find_visual_studio(), r'VSTSDB\Deploy')]
-
- # Set Microsoft Build Engine
- path = r'\MSBuild\%0.1f\bin%s' % (version, pi.ccpu_dir(True))
- MSBuild = [
- os.path.join(pi.program_files_x86, path),
- os.path.join(pi.program_files, path)
- ]
-
- # Set Microsoft HTML Help Workshop
- path = 'HTML Help Workshop'
- HTMLWork = [
- os.path.join(pi.program_files_x86, path),
- os.path.join(pi.program_files, path)
- ]
-
- # Return environment
- return dict(
- include=_build_paths('include', [VCIncludes, OSIncludes]),
- lib=_build_paths('lib', [VCLibraries, OSLibraries, FxTools]),
- libpath=_build_paths('libpath', [VCLibraries, FxTools, VCStoreRefs]),
- path=_build_paths('path', [VCTools, VSTools, VsTDb, SdkTools, SdkSetup,
- FxTools, MSBuild, HTMLWork]),
- )
-
-
-def _build_paths(name, spec_path_lists):
- """
- Given an environment variable name and specified paths,
- return a pathsep-separated string of paths containing
- unique, extant, directories from those paths and from
- the environment variable. Raise an error if no paths
- are resolved.
+ This function is compatible with Microsoft Visual C++ 9.0 to 14.0.
+
+ Parameters
+ ----------
+ arch: str
+ Target architecture.
+ vcver: float
+ Required Microsoft Visual C++ version. If not set, autodetect the last
+ version.
+ vcvermin: float
+ Minimum Microsoft Visual C++ version.
"""
- # flatten spec_path_lists
- spec_paths = itertools.chain.from_iterable(spec_path_lists)
- env_paths = os.environ.get(name, '').split(os.pathsep)
- paths = itertools.chain(spec_paths, env_paths)
- extant_paths = list(filter(os.path.isdir, paths))
- if not extant_paths:
- msg = "%s environment variable is empty" % name.upper()
- raise distutils.errors.DistutilsPlatformError(msg)
- unique_paths = _unique_everseen(extant_paths)
- return os.pathsep.join(unique_paths)
-
-
-# from Python docs
-def _unique_everseen(iterable, key=None):
- "List unique elements, preserving order. Remember all elements ever seen."
- # unique_everseen('AAAABBBCCDAABBB') --> A B C D
- # unique_everseen('ABBCcAD', str.lower) --> A B C D
- seen = set()
- seen_add = seen.add
- filterfalse = six.moves.filterfalse
- if key is None:
- for element in filterfalse(seen.__contains__, iterable):
- seen_add(element)
- yield element
- else:
- for element in iterable:
- k = key(element)
- if k not in seen:
- seen_add(k)
+ def __init__(self, arch, vcver=None, vcvermin=None):
+ self.pi = PlatformInfo(arch)
+ self.ri = RegistryInfo(self.pi)
+ self.si = SystemInfo(self.ri, vcver)
+
+ if self.vcver < vcvermin:
+ err = 'No suitable Microsoft Visual C++ version found'
+ raise distutils.errors.DistutilsPlatformError(err)
+
+ @property
+ def vcver(self):
+ """
+ Microsoft Visual C++ version.
+ """
+ return self.si.vcver
+
+ @property
+ def VSTools(self):
+ """
+ Microsoft Visual Studio Tools
+ """
+ paths = [r'Common7\IDE', r'Common7\Tools']
+ if self.vcver >= 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]
+
+ @property
+ def VCIncludes(self):
+ """
+ Microsoft Visual C++ & Microsoft Foundation Class Includes
+ """
+ return [os.path.join(self.si.VCInstallDir, 'Include'),
+ os.path.join(self.si.VCInstallDir, 'ATLMFC\Include')]
+
+ @property
+ def VCLibraries(self):
+ """
+ Microsoft Visual C++ & Microsoft Foundation Class Libraries
+ """
+ arch_subdir = self.pi.target_dir(hidex86=True)
+ paths = ['Lib%s' % arch_subdir, r'ATLMFC\Lib%s' % arch_subdir]
+ if self.vcver >= 14.0:
+ paths += [r'Lib\store%s' % arch_subdir]
+ return [os.path.join(self.si.VCInstallDir, path) for path in paths]
+
+ @property
+ def VCStoreRefs(self):
+ """
+ Microsoft Visual C++ store references Libraries
+ """
+ path = os.path.join(self.si.VCInstallDir, r'Lib\store\references')
+ return [path] if self.vcver >= 14.0 else []
+
+ @property
+ def VCTools(self):
+ """
+ Microsoft Visual C++ Tools
+ """
+ forcex86 = True if self.vcver <= 10.0 else False
+ arch_subdir = self.pi.cross_dir(forcex86)
+ tools = [
+ os.path.join(self.si.VCInstallDir, 'VCPackages'),
+ os.path.join(self.si.VCInstallDir, 'Bin%s' % arch_subdir),
+ ]
+ if self.pi.cross_dir() and self.vcver >= 14.0:
+ path = 'Bin%s' % self.pi.current_dir(hidex86=True)
+ tools += [os.path.join(self.si.VCInstallDir, path)]
+ else:
+ tools += [os.path.join(self.si.VCInstallDir, 'Bin')]
+ return tools
+
+ @property
+ def OSLibraries(self):
+ """
+ Microsoft Windows SDK Libraries
+ """
+ arch_subdir = self.pi.target_dir(hidex86=True, x64=True)
+ return [os.path.join(self.si.WindowsSdkDir, 'Bin%s' % arch_subdir)]
+
+ @property
+ def OSIncludes(self):
+ """
+ Microsoft Windows SDK Include
+ """
+ return [
+ os.path.join(self.si.WindowsSdkDir, 'Include'),
+ os.path.join(self.si.WindowsSdkDir, r'Include\gl'),
+ ]
+
+ @property
+ def SdkTools(self):
+ """
+ Microsoft Windows SDK Tools
+ """
+ if self.vcver <= 10:
+ arch_subdir = self.pi.target_dir(hidex86=True, x64=True)
+ else:
+ arch_subdir = self.pi.target_dir(x64=True)
+ tools = [os.path.join(self.si.WindowsSdkDir, 'Bin')]
+ if not self.pi.target_is_x86():
+ path = 'Bin%s' % arch_subdir
+ tools += [os.path.join(self.si.WindowsSdkDir, path)]
+ if self.vcver == 10.0:
+ path = r'Bin\NETFX 4.0 Tools%s' % arch_subdir
+ tools += [os.path.join(self.si.WindowsSdkDir, path)]
+ return tools
+
+ @property
+ def SdkSetup(self):
+ """
+ Microsoft Windows SDK Setup
+ """
+ return [os.path.join(self.si.WindowsSdkDir, 'Setup')]
+
+ @property
+ def FxTools(self):
+ """
+ Microsoft .NET Framework Tools
+ """
+ pi = self.pi
+ si = self.si
+ if self.vcver <= 10.0:
+ include32 = True
+ include64 = not pi.target_is_x86() and not pi.current_is_x86()
+ else:
+ include32 = pi.target_is_x86() or pi.current_is_x86()
+ include64 = pi.current_cpu == 'amd64' or pi.target_cpu == 'amd64'
+ tools = []
+ if include32:
+ tools += [
+ os.path.join(si.FrameworkDir32, ver)
+ for ver in si.FrameworkVersion32
+ ]
+ if include64:
+ tools += [
+ os.path.join(si.FrameworkDir64, ver)
+ for ver in si.FrameworkVersion64
+ ]
+ return tools
+
+ @property
+ def VsTDb(self):
+ """
+ Microsoft Visual Studio Team System Database
+ """
+ return [os.path.join(self.si.VSInstallDir, r'VSTSDB\Deploy')]
+
+ @property
+ def MSBuild(self):
+ """
+ Microsoft Build Engine
+ """
+ arch_subdir = self.pi.current_dir(hidex86=True)
+ path = r'\MSBuild\%0.1f\bin%s' % (self.vcver, arch_subdir)
+ return [
+ os.path.join(self.si.ProgramFilesx86, path),
+ os.path.join(self.si.ProgramFiles, path)
+ ]
+
+ @property
+ def HTMLWs(self):
+ """
+ Microsoft HTML Help Workshop
+ """
+ return [
+ os.path.join(self.si.ProgramFilesx86, 'HTML Help Workshop'),
+ os.path.join(self.si.ProgramFiles, 'HTML Help Workshop')
+ ]
+
+ @property
+ def VCRuntimeRedist(self):
+ """
+ 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.vcver, self.vcver)
+ return os.path.join(self.si.VCInstallDir, vcruntime)
+
+ def return_env(self):
+ """
+ Return environment dict.
+ """
+ env = dict(
+ include=self._build_paths('include',
+ [self.VCIncludes,
+ self.OSIncludes]),
+ lib=self._build_paths('lib',
+ [self.VCLibraries,
+ self.OSLibraries,
+ self.FxTools]),
+ libpath=self._build_paths('libpath',
+ [self.VCLibraries,
+ self.FxTools,
+ self.VCStoreRefs]),
+ path=self._build_paths('path',
+ [self.VCTools,
+ self.VSTools,
+ self.VsTDb,
+ self.SdkTools,
+ self.SdkSetup,
+ self.FxTools,
+ self.MSBuild,
+ self.HTMLWs]),
+ )
+ if self.vcver >= 14 and os.path.isfile(self.VCRuntimeRedist):
+ env['py_vcruntime_redist'] = self.VCRuntimeRedist
+ return env
+
+ def _build_paths(self, name, spec_path_lists):
+ """
+ Given an environment variable name and specified paths,
+ return a pathsep-separated string of paths containing
+ unique, extant, directories from those paths and from
+ the environment variable. Raise an error if no paths
+ are resolved.
+ """
+ # flatten spec_path_lists
+ spec_paths = itertools.chain.from_iterable(spec_path_lists)
+ env_paths = os.environ.get(name, '').split(os.pathsep)
+ paths = itertools.chain(spec_paths, env_paths)
+ extant_paths = list(filter(os.path.isdir, 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)
+
+ # from Python docs
+ def _unique_everseen(self, iterable, key=None):
+ """
+ List unique elements, preserving order.
+ Remember all elements ever seen.
+ """
+ # unique_everseen('AAAABBBCCDAABBB') --> A B C D
+ # unique_everseen('ABBCcAD', str.lower) --> A B C D
+ seen = set()
+ seen_add = seen.add
+ filterfalse = six.moves.filterfalse
+ if key is None:
+ for element in filterfalse(seen.__contains__, iterable):
+ seen_add(element)
yield element
+ else:
+ for element in iterable:
+ k = key(element)
+ if k not in seen:
+ seen_add(k)
+ yield element