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)
import os
import itertools
import distutils.errors
import winreg
try:
# Distutil file for MSVC++ 9.0 and upper
......@@ -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
......@@ -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,258 +341,494 @@ 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
sdkdir = os.path.join(self.VCInstallDir, 'PlatformSDK')
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:
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
# Default path
guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework')
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
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
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
guess_fw = os.path.join(self.pi.win_dir, r'Microsoft.NET\Framework64')
return self._find_dot_net_versions(32)
# Try to get path from registry, if fail use default path
return self._lookup(self.vc, 'frameworkdir64') or guess_fw
@property
def FrameworkVersion64(self):
"""
Microsoft .NET Framework 64bit versions.
"""
return self._find_dot_net_versions(64)
def _lookup(self, base, key):
try:
return msvc9compiler.Reg.get_value(base, key)
except KeyError:
pass
def _find_dot_net_versions(self, bits=32):
"""
Find Microsoft .NET Framework versions.
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
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
-----------------------------------------------
9.0, 10.0, 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.
"""
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)
reg = RegistryInfo(pi, version)
Microsoft Visual C++ 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']
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 = []
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]
# 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),
@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 pi.tools_extra() and version >= 14.0:
path = 'Bin' + pi.ccpu_dir(True)
VCTools.append(os.path.join(reg.find_visual_c(), path))
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:
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
path = 'Lib' + pi.tcpu_dir(True, True)
OSLibraries = [os.path.join(reg.find_windows_sdk(), path)]
@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)]
# Set Microsoft Windows SDK Include
OSIncludes = [
os.path.join(reg.find_windows_sdk(), 'Include'),
os.path.join(reg.find_windows_sdk(), r'Include\gl'),
@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'),
]
# 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())
@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
# Set Microsoft Visual Studio Team System Database
VsTDb = [os.path.join(reg.find_visual_studio(), r'VSTSDB\Deploy')]
@property
def VsTDb(self):
"""
Microsoft Visual Studio Team System Database
"""
return [os.path.join(self.si.VSInstallDir, 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)
@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)
]
# 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)
@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')
]
# 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]),
@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(name, spec_path_lists):
def _build_paths(self, name, spec_path_lists):
"""
Given an environment variable name and specified paths,
return a pathsep-separated string of paths containing
......@@ -603,13 +844,15 @@ def _build_paths(name, spec_path_lists):
if not extant_paths:
msg = "%s environment variable is empty" % name.upper()
raise distutils.errors.DistutilsPlatformError(msg)
unique_paths = _unique_everseen(extant_paths)
unique_paths = self._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."
# 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()
......
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