Commit 72db3cf5 authored by JGoutin's avatar JGoutin

* 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.
parent 75282e55
...@@ -4,6 +4,7 @@ This module improve support for Microsoft Visual C++ compilers. (Windows Only) ...@@ -4,6 +4,7 @@ This module improve support for Microsoft Visual C++ compilers. (Windows Only)
import os import os
import itertools import itertools
import distutils.errors import distutils.errors
import winreg
try: try:
# Distutil file for MSVC++ 9.0 and upper # Distutil file for MSVC++ 9.0 and upper
...@@ -138,15 +139,15 @@ def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs): ...@@ -138,15 +139,15 @@ def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs):
try: try:
return unpatched['msvc9_query_vcvarsall'](ver, arch, *args, **kwargs) return unpatched['msvc9_query_vcvarsall'](ver, arch, *args, **kwargs)
except distutils.errors.DistutilsPlatformError: except distutils.errors.DistutilsPlatformError:
# Error if Vcvarsall.bat is missing # Pass error if Vcvarsall.bat is missing
pass pass
except ValueError: except ValueError:
# Error if environment not set after executing vcvarsall.bat # Pass error if environment not set after executing vcvarsall.bat
pass pass
# If vcvarsall.bat fail, try to set environment directly # If error, try to set environment directly
try: try:
return _compute_env(ver, arch) return EnvironmentInfo(arch, ver).return_env()
except distutils.errors.DistutilsPlatformError as exc: except distutils.errors.DistutilsPlatformError as exc:
_augment_exception(exc, ver, arch) _augment_exception(exc, ver, arch)
raise raise
...@@ -171,21 +172,22 @@ def msvc14_get_vc_env(plat_spec): ...@@ -171,21 +172,22 @@ def msvc14_get_vc_env(plat_spec):
------ ------
environment: dict environment: dict
""" """
# Try to get environement from vcvarsall.bat (Classical way)
try: try:
return unpatched['msv14_get_vc_env'](plat_spec) return unpatched['msv14_get_vc_env'](plat_spec)
except distutils.errors.DistutilsPlatformError: except distutils.errors.DistutilsPlatformError:
# Error if Vcvarsall.bat is missing # Pass error Vcvarsall.bat is missing
pass pass
# If vcvarsall.bat fail, try to set environment directly # If error, try to set environment directly
try: try:
return _compute_env(version, plat_spec) return EnvironmentInfo(plat_spec, vcvermin=14.0).return_env()
except distutils.errors.DistutilsPlatformError as exc: except distutils.errors.DistutilsPlatformError as exc:
_augment_exception(exc, version, plat_spec) _augment_exception(exc, 14.0)
raise raise
def _augment_exception(exc, version, arch): def _augment_exception(exc, version, arch=''):
""" """
Add details to the exception message to help guide the user Add details to the exception message to help guide the user
as to what action will resolve it. as to what action will resolve it.
...@@ -193,32 +195,33 @@ def _augment_exception(exc, version, arch): ...@@ -193,32 +195,33 @@ def _augment_exception(exc, version, arch):
# Error if MSVC++ directory not found or environment not set # Error if MSVC++ directory not found or environment not set
message = exc.args[0] 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 # Special error message if MSVC++ not installed
message = 'Microsoft Visual C++ %0.1f is required (%s).' %\ message = 'Microsoft Visual C++ %0.1f is required (%s).' %\
(version, message) (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: if arch.lower().find('ia64') > -1:
# For VC++ 9.0, if IA64 support is needed, redirect user # For VC++ 9.0, if IA64 support is needed, redirect user
# to Windows SDK 7.0 # to Windows SDK 7.0
message += ' Get it with "Microsoft 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: else:
# For VC++ 9.0 redirect user to Vc++ for Python 2.7 : # For VC++ 9.0 redirect user to Vc++ for Python 2.7 :
# This redirection link is maintained by Microsoft. # This redirection link is maintained by Microsoft.
# Contact vspython@microsoft.com if it needs updating. # Contact vspython@microsoft.com if it needs updating.
message += r' Get it from http://aka.ms/vcpython27' 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 # For VC++ 10.0 Redirect user to Windows SDK 7.1
message += ' Get it with "Microsoft 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 exc.args[0] = message
class PlatformInfo: class PlatformInfo:
""" """
Find architecture informations and system paths. Current and Target Architectures informations.
Parameters Parameters
---------- ----------
...@@ -226,9 +229,6 @@ class PlatformInfo: ...@@ -226,9 +229,6 @@ class PlatformInfo:
Target architecture. Target architecture.
""" """
current_cpu = os.environ['processor_architecture'].lower() 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): def __init__(self, arch):
self.arch = arch.lower() self.arch = arch.lower()
...@@ -241,9 +241,9 @@ class PlatformInfo: ...@@ -241,9 +241,9 @@ class PlatformInfo:
return self.target_cpu == 'x86' return self.target_cpu == 'x86'
def current_is_x86(self): 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. Current platform specific subfolder.
...@@ -256,7 +256,8 @@ class PlatformInfo: ...@@ -256,7 +256,8 @@ class PlatformInfo:
Return Return
------ ------
subfolder: str (starting with'\') subfolder: str
"\target"
""" """
return ( return (
'' if (self.current_cpu == 'x86' and hidex86) else '' if (self.current_cpu == 'x86' and hidex86) else
...@@ -264,7 +265,7 @@ class PlatformInfo: ...@@ -264,7 +265,7 @@ class PlatformInfo:
r'\%s' % self.current_cpu 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. Target platform specific subfolder.
...@@ -277,7 +278,8 @@ class PlatformInfo: ...@@ -277,7 +278,8 @@ class PlatformInfo:
Return Return
------ ------
subfolder: str (starting with'\') subfolder: str
"\current"
""" """
return ( return (
'' if (self.target_cpu == 'x86' and hidex86) else '' if (self.target_cpu == 'x86' and hidex86) else
...@@ -285,9 +287,9 @@ class PlatformInfo: ...@@ -285,9 +287,9 @@ class PlatformInfo:
r'\%s' % self.target_cpu 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 Parameters
---------- ----------
...@@ -297,9 +299,11 @@ class PlatformInfo: ...@@ -297,9 +299,11 @@ class PlatformInfo:
Return 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: if self.target_cpu != self.current_cpu:
current = 'x86' if forcex86 else self.current_cpu current = 'x86' if forcex86 else self.current_cpu
path = path.replace('\\', '\\%s_' % current) path = path.replace('\\', '\\%s_' % current)
...@@ -308,24 +312,25 @@ class PlatformInfo: ...@@ -308,24 +312,25 @@ class PlatformInfo:
class RegistryInfo: class RegistryInfo:
""" """
Find Microsoft Visual C++ compiler related paths using registry or Microsoft Visual Studio related registry informations.
default paths.
Parameters Parameters
---------- ----------
platform_info: platform_info platform_info: PlatformInfo
"platform_info" instance. "PlatformInfo" instance.
version: float
Required Microsoft Visual C++ version.
""" """
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.pi = platform_info
self.version = version
@property @property
def microsoft(self): def microsoft(self):
""" """
Microsoft registry path. Microsoft software registry key.
""" """
return os.path.join( return os.path.join(
'Software', 'Software',
...@@ -336,258 +341,494 @@ class RegistryInfo: ...@@ -336,258 +341,494 @@ class RegistryInfo:
@property @property
def sxs(self): def sxs(self):
""" """
Visual Studio SxS registry path. Microsoft Visual Studio SxS registry key.
""" """
return os.path.join(self.microsoft, r'VisualStudio\SxS') return os.path.join(self.microsoft, r'VisualStudio\SxS')
@property @property
def vc(self): def vc(self):
""" """
Visual C++ registry path. Microsoft Visual C++ registry key.
""" """
return os.path.join(self.sxs, 'VC7') return os.path.join(self.sxs, 'VC7')
@property @property
def vs(self): def vs(self):
""" """
Visual Studio registry path. Microsoft Visual Studio registry key.
""" """
return os.path.join(self.sxs, 'VS7') return os.path.join(self.sxs, 'VS7')
@property @property
def vc_for_python(self): 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) return os.path.join(self.microsoft, path)
@property @property
def windows_sdk(self): 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') 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 # Default path
name = 'Microsoft Visual Studio %0.1f' % self.version name = 'Microsoft Visual Studio %0.1f' % self.vcver
default = os.path.join(self.pi.program_files_x86, name) default = os.path.join(self.ProgramFilesx86, name)
# Try to get path from registry, if fail use default path # 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 path
default = r'Microsoft Visual Studio %0.1f\VC' % self.version default = r'Microsoft Visual Studio %0.1f\VC' % self.vcver
guess_vc = os.path.join(self.pi.program_files_x86, default) guess_vc = os.path.join(self.ProgramFilesx86, default)
# Try to get "VC++ for Python" path from registry as default path # 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 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 # 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): 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) raise distutils.errors.DistutilsPlatformError(msg)
return result return result
def find_windows_sdk(self): @property
def WindowsSdkDir(self):
""" """
Find Microsoft Windows SDK directory. Microsoft Windows SDK directory.
""" """
WindowsSdkDir = '' sdkdir = ''
if self.version == 9.0: if self.vcver == 9.0:
WindowsSdkVer = ('7.0', '6.1', '6.0a') sdkver = ('7.0', '6.1', '6.0a')
elif self.version == 10.0: elif self.vcver == 10.0:
WindowsSdkVer = ('7.1', '7.0a') sdkver = ('7.1', '7.0a')
elif self.vcver == 14.0:
sdkver = ('10.0', '8.1', '8.1a')
else: else:
WindowsSdkVer = () sdkver = ()
for ver in WindowsSdkVer: for ver in sdkver:
# Try to get it from registry # Try to get it from registry
loc = os.path.join(self.windows_sdk, 'v%s' % ver) loc = os.path.join(self.ri.windows_sdk, 'v%s' % ver)
WindowsSdkDir = self._lookup(loc, 'installationfolder') sdkdir = self.ri.lookup(loc, 'installationfolder')
if WindowsSdkDir: if sdkdir:
break 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 # 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: if install_base:
WindowsSdkDir = os.path.join(install_base, 'WinSDK') sdkdir = os.path.join(install_base, 'WinSDK')
if not WindowsSdkDir or not os.path.isdir(WindowsSdkDir): if not sdkdir or not os.path.isdir(sdkdir):
# If fail, use default path # If fail, use default new path
for ver in WindowsSdkVer: 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 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): if os.path.isdir(d):
WindowsSdkDir = d sdkdir = d
if not WindowsSdkDir: if not sdkdir:
# If fail, use Platform SDK # If fail, use Platform SDK
WindowsSdkDir = os.path.join(self.find_visual_c(), 'PlatformSDK') sdkdir = os.path.join(self.VCInstallDir, 'PlatformSDK')
return WindowsSdkDir return sdkdir
def find_dot_net_versions(self): @property
def FrameworkDir32(self):
""" """
Find Microsoft .NET Framework Versions. Microsoft .NET Framework 32bit directory.
""" """
if self.version == 10.0: # Default path
v4 = self._lookup(self.vc, 'frameworkver32') or '' guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework')
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
def find_dot_net_32(self): # Try to get path from registry, if fail use default path
return self.ri.lookup(self.ri.vc, 'frameworkdir32') or guess_fw
@property
def FrameworkDir64(self):
""" """
Find Microsoft .NET Framework 32bit directory. Microsoft .NET Framework 64bit directory.
""" """
# Default path # 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\Framework64')
# Try to get path from registry, if fail use default path # 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, 'frameworkdir64') or guess_fw
def find_dot_net_64(self): @property
def FrameworkVersion32(self):
""" """
Find Microsoft .NET Framework 64bit directory. Microsoft .NET Framework 32bit versions.
""" """
# Default path return self._find_dot_net_versions(32)
guess_fw = os.path.join(self.pi.win_dir, r'Microsoft.NET\Framework64')
# Try to get path from registry, if fail use default path @property
return self._lookup(self.vc, 'frameworkdir64') or guess_fw def FrameworkVersion64(self):
"""
Microsoft .NET Framework 64bit versions.
"""
return self._find_dot_net_versions(64)
def _lookup(self, base, key): def _find_dot_net_versions(self, bits=32):
try: """
return msvc9compiler.Reg.get_value(base, key) Find Microsoft .NET Framework versions.
except KeyError:
pass
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 ''
def _compute_env(version, arch): # 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 Return environment variables for specified Microsoft Visual C++ version
and platform. and platform : Lib, Include, Path and libpath.
This function is compatible with Microsoft Visual C++ 9.0 to 14.0.
Microsoft Visual C++ known compatibles versions Parameters
----------------------------------------------- ----------
9.0, 10.0, 14.0 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.
"""
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):
""" """
pi = PlatformInfo(arch) Microsoft Visual C++ version.
reg = RegistryInfo(pi, version) """
return self.si.vcver
# Set Microsoft Visual Studio Tools @property
def VSTools(self):
"""
Microsoft Visual Studio Tools
"""
paths = [r'Common7\IDE', r'Common7\Tools'] paths = [r'Common7\IDE', r'Common7\Tools']
if version >= 14.0: if self.vcver >= 14.0:
paths.append(r'Common7\IDE\CommonExtensions\Microsoft\TestWindow') arch_subdir = self.pi.current_dir(hidex86=True, x64=True)
paths.append(r'Team Tools\Performance Tools') paths += [r'Common7\IDE\CommonExtensions\Microsoft\TestWindow']
paths.append(r'Team Tools\Performance Tools' + pi.ccpu_dir(True, True)) paths += [r'Team Tools\Performance Tools']
VSTools = [os.path.join(reg.find_visual_studio(), path) for path in paths] paths += [r'Team Tools\Performance Tools%s' % arch_subdir]
return [os.path.join(self.si.VSInstallDir, 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 @property
path = 'Bin' + pi.tools_extra(False if version >= 14.0 else True) def VCIncludes(self):
VCTools = [ """
os.path.join(reg.find_visual_c(), 'VCPackages'), Microsoft Visual C++ & Microsoft Foundation Class Includes
os.path.join(reg.find_visual_c(), path), """
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 pi.tools_extra() and version >= 14.0: if self.pi.cross_dir() and self.vcver >= 14.0:
path = 'Bin' + pi.ccpu_dir(True) path = 'Bin%s' % self.pi.current_dir(hidex86=True)
VCTools.append(os.path.join(reg.find_visual_c(), path)) tools += [os.path.join(self.si.VCInstallDir, path)]
else: else:
VCTools.append(os.path.join(reg.find_visual_c(), 'Bin')) tools += [os.path.join(self.si.VCInstallDir, 'Bin')]
return tools
# Set Microsoft Windows SDK Libraries @property
path = 'Lib' + pi.tcpu_dir(True, True) def OSLibraries(self):
OSLibraries = [os.path.join(reg.find_windows_sdk(), path)] """
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)]
# Set Microsoft Windows SDK Include @property
OSIncludes = [ def OSIncludes(self):
os.path.join(reg.find_windows_sdk(), 'Include'), """
os.path.join(reg.find_windows_sdk(), r'Include\gl'), Microsoft Windows SDK Include
"""
return [
os.path.join(self.si.WindowsSdkDir, 'Include'),
os.path.join(self.si.WindowsSdkDir, r'Include\gl'),
] ]
# Set Microsoft Windows SDK Tools @property
SdkTools = [os.path.join(reg.find_windows_sdk(), 'Bin')] def SdkTools(self):
if not pi.target_is_x86(): """
path = 'Bin' + pi.tcpu_dir(True, True) Microsoft Windows SDK Tools
SdkTools.append(os.path.join(reg.find_windows_sdk(), path)) """
if version == 10.0: if self.vcver <= 10:
path = r'Bin\NETFX 4.0 Tools' + pi.tcpu_dir(True, True) arch_subdir = self.pi.target_dir(hidex86=True, x64=True)
SdkTools.append(os.path.join(reg.find_windows_sdk(), path)) else:
arch_subdir = self.pi.target_dir(x64=True)
# Set Microsoft Windows SDK Setup tools = [os.path.join(self.si.WindowsSdkDir, 'Bin')]
SdkSetup = [os.path.join(reg.find_windows_sdk(), 'Setup')] if not self.pi.target_is_x86():
path = 'Bin%s' % arch_subdir
# Set Microsoft .NET Framework Tools tools += [os.path.join(self.si.WindowsSdkDir, path)]
roots = [reg.find_dot_net_32()] if self.vcver == 10.0:
include_64_framework = not pi.target_is_x86() and not pi.current_is_x86() path = r'Bin\NETFX 4.0 Tools%s' % arch_subdir
roots += [reg.find_dot_net_64()] if include_64_framework else [] tools += [os.path.join(self.si.WindowsSdkDir, path)]
return tools
FxTools = [
os.path.join(root, ver) @property
for root, ver in itertools.product(roots, reg.find_dot_net_versions()) 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
# Set Microsoft Visual Studio Team System Database @property
VsTDb = [os.path.join(reg.find_visual_studio(), r'VSTSDB\Deploy')] def VsTDb(self):
"""
Microsoft Visual Studio Team System Database
"""
return [os.path.join(self.si.VSInstallDir, r'VSTSDB\Deploy')]
# Set Microsoft Build Engine @property
path = r'\MSBuild\%0.1f\bin%s' % (version, pi.ccpu_dir(True)) def MSBuild(self):
MSBuild = [ """
os.path.join(pi.program_files_x86, path), Microsoft Build Engine
os.path.join(pi.program_files, path) """
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)
] ]
# Set Microsoft HTML Help Workshop @property
path = 'HTML Help Workshop' def HTMLWs(self):
HTMLWork = [ """
os.path.join(pi.program_files_x86, path), Microsoft HTML Help Workshop
os.path.join(pi.program_files, path) """
return [
os.path.join(self.si.ProgramFilesx86, 'HTML Help Workshop'),
os.path.join(self.si.ProgramFiles, 'HTML Help Workshop')
] ]
# Return environment @property
return dict( def VCRuntimeRedist(self):
include=_build_paths('include', [VCIncludes, OSIncludes]), """
lib=_build_paths('lib', [VCLibraries, OSLibraries, FxTools]), Microsoft Visual C++ runtime redistribuable dll
libpath=_build_paths('libpath', [VCLibraries, FxTools, VCStoreRefs]), """
path=_build_paths('path', [VCTools, VSTools, VsTDb, SdkTools, SdkSetup, arch_subdir = self.pi.target_dir(x64=True)
FxTools, MSBuild, HTMLWork]), 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):
def _build_paths(name, spec_path_lists):
""" """
Given an environment variable name and specified paths, Given an environment variable name and specified paths,
return a pathsep-separated string of paths containing return a pathsep-separated string of paths containing
...@@ -603,13 +844,15 @@ def _build_paths(name, spec_path_lists): ...@@ -603,13 +844,15 @@ def _build_paths(name, spec_path_lists):
if not extant_paths: if not extant_paths:
msg = "%s environment variable is empty" % name.upper() msg = "%s environment variable is empty" % name.upper()
raise distutils.errors.DistutilsPlatformError(msg) raise distutils.errors.DistutilsPlatformError(msg)
unique_paths = _unique_everseen(extant_paths) unique_paths = self._unique_everseen(extant_paths)
return os.pathsep.join(unique_paths) return os.pathsep.join(unique_paths)
# from Python docs
# from Python docs def _unique_everseen(self, iterable, key=None):
def _unique_everseen(iterable, key=None): """
"List unique elements, preserving order. Remember all elements ever seen." List unique elements, preserving order.
Remember all elements ever seen.
"""
# unique_everseen('AAAABBBCCDAABBB') --> A B C D # unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D # unique_everseen('ABBCcAD', str.lower) --> A B C D
seen = set() seen = set()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment