2
Improved support for Microsoft Visual C++ compilers.
4
Known supported compilers:
5
--------------------------
6
Microsoft Visual C++ 9.0:
7
Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64);
8
Microsoft Windows SDK 7.0 (x86, x64, ia64);
9
Microsoft Windows SDK 6.1 (x86, x64, ia64)
11
Microsoft Visual C++ 10.0:
12
Microsoft Windows SDK 7.1 (x86, x64, ia64)
14
Microsoft Visual C++ 14.0:
15
Microsoft Visual C++ Build Tools 2015 (x86, x64, arm)
22
import distutils.errors
23
from pkg_resources.extern.packaging.version import LegacyVersion
25
from setuptools.extern.six.moves import filterfalse
27
from .monkey import get_unpatched
29
if platform.system() == 'Windows':
30
from setuptools.extern.six.moves import winreg
34
Mock winreg and environ so the module can be imported
40
HKEY_CURRENT_USER = None
41
HKEY_LOCAL_MACHINE = None
42
HKEY_CLASSES_ROOT = None
47
from distutils.msvc9compiler import Reg
52
def msvc9_find_vcvarsall(version):
54
Patched "distutils.msvc9compiler.find_vcvarsall" to use the standalone
55
compiler build for Python (VCForPython). Fall back to original behavior
56
when the standalone compiler is not available.
58
Redirect the path of "vcvarsall.bat".
60
Known supported compilers
61
-------------------------
62
Microsoft Visual C++ 9.0:
63
Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64)
68
Required Microsoft Visual C++ version.
72
vcvarsall.bat path: str
74
VC_BASE = r'Software\%sMicrosoft\DevDiv\VCForPython\%0.1f'
75
key = VC_BASE % ('', version)
77
# Per-user installs register the compiler path here
78
productdir = Reg.get_value(key, "installdir")
81
# All-user installs on a 64-bit system register here
82
key = VC_BASE % ('Wow6432Node\\', version)
83
productdir = Reg.get_value(key, "installdir")
88
vcvarsall = os.path.os.path.join(productdir, "vcvarsall.bat")
89
if os.path.isfile(vcvarsall):
92
return get_unpatched(msvc9_find_vcvarsall)(version)
95
def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs):
97
Patched "distutils.msvc9compiler.query_vcvarsall" for support standalones
100
Set environment without use of "vcvarsall.bat".
102
Known supported compilers
103
-------------------------
104
Microsoft Visual C++ 9.0:
105
Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64);
106
Microsoft Windows SDK 7.0 (x86, x64, ia64);
107
Microsoft Windows SDK 6.1 (x86, x64, ia64)
109
Microsoft Visual C++ 10.0:
110
Microsoft Windows SDK 7.1 (x86, x64, ia64)
115
Required Microsoft Visual C++ version.
123
# Try to get environement from vcvarsall.bat (Classical way)
125
orig = get_unpatched(msvc9_query_vcvarsall)
126
return orig(ver, arch, *args, **kwargs)
127
except distutils.errors.DistutilsPlatformError:
128
# Pass error if Vcvarsall.bat is missing
131
# Pass error if environment not set after executing vcvarsall.bat
134
# If error, try to set environment directly
136
return EnvironmentInfo(arch, ver).return_env()
137
except distutils.errors.DistutilsPlatformError as exc:
138
_augment_exception(exc, ver, arch)
142
def msvc14_get_vc_env(plat_spec):
144
Patched "distutils._msvccompiler._get_vc_env" for support standalones
147
Set environment without use of "vcvarsall.bat".
149
Known supported compilers
150
-------------------------
151
Microsoft Visual C++ 14.0:
152
Microsoft Visual C++ Build Tools 2015 (x86, x64, arm)
163
# Try to get environment from vcvarsall.bat (Classical way)
165
return get_unpatched(msvc14_get_vc_env)(plat_spec)
166
except distutils.errors.DistutilsPlatformError:
167
# Pass error Vcvarsall.bat is missing
170
# If error, try to set environment directly
172
return EnvironmentInfo(plat_spec, vc_min_ver=14.0).return_env()
173
except distutils.errors.DistutilsPlatformError as exc:
174
_augment_exception(exc, 14.0)
178
def msvc14_gen_lib_options(*args, **kwargs):
180
Patched "distutils._msvccompiler.gen_lib_options" for fix
181
compatibility between "numpy.distutils" and "distutils._msvccompiler"
184
if "numpy.distutils" in sys.modules:
186
if LegacyVersion(np.__version__) < LegacyVersion('1.11.2'):
187
return np.distutils.ccompiler.gen_lib_options(*args, **kwargs)
188
return get_unpatched(msvc14_gen_lib_options)(*args, **kwargs)
191
def _augment_exception(exc, version, arch=''):
193
Add details to the exception message to help guide the user
194
as to what action will resolve it.
196
# Error if MSVC++ directory not found or environment not set
197
message = exc.args[0]
199
if "vcvarsall" in message.lower() or "visual c" in message.lower():
200
# Special error message if MSVC++ not installed
201
tmpl = 'Microsoft Visual C++ {version:0.1f} is required.'
202
message = tmpl.format(**locals())
203
msdownload = 'www.microsoft.com/download/details.aspx?id=%d'
205
if arch.lower().find('ia64') > -1:
206
# For VC++ 9.0, if IA64 support is needed, redirect user
208
message += ' Get it with "Microsoft Windows SDK 7.0": '
209
message += msdownload % 3138
211
# For VC++ 9.0 redirect user to Vc++ for Python 2.7 :
212
# This redirection link is maintained by Microsoft.
213
# Contact vspython@microsoft.com if it needs updating.
214
message += ' Get it from http://aka.ms/vcpython27'
215
elif version == 10.0:
216
# For VC++ 10.0 Redirect user to Windows SDK 7.1
217
message += ' Get it with "Microsoft Windows SDK 7.1": '
218
message += msdownload % 8279
219
elif version >= 14.0:
220
# For VC++ 14.0 Redirect user to Visual C++ Build Tools
221
message += (' Get it with "Microsoft Visual C++ Build Tools": '
222
r'http://landinghub.visualstudio.com/'
223
'visual-cpp-build-tools')
225
exc.args = (message, )
230
Current and Target Architectures informations.
237
current_cpu = safe_env.get('processor_architecture', '').lower()
239
def __init__(self, arch):
240
self.arch = arch.lower().replace('x64', 'amd64')
243
def target_cpu(self):
244
return self.arch[self.arch.find('_') + 1:]
246
def target_is_x86(self):
247
return self.target_cpu == 'x86'
249
def current_is_x86(self):
250
return self.current_cpu == 'x86'
252
def current_dir(self, hidex86=False, x64=False):
254
Current platform specific subfolder.
259
return '' and not '\x86' if architecture is x86.
261
return '\x64' and not '\amd64' if architecture is amd64.
266
'\target', or '' (see hidex86 parameter)
269
'' if (self.current_cpu == 'x86' and hidex86) else
270
r'\x64' if (self.current_cpu == 'amd64' and x64) else
271
r'\%s' % self.current_cpu
274
def target_dir(self, hidex86=False, x64=False):
276
Target platform specific subfolder.
281
return '' and not '\x86' if architecture is x86.
283
return '\x64' and not '\amd64' if architecture is amd64.
288
'\current', or '' (see hidex86 parameter)
291
'' if (self.target_cpu == 'x86' and hidex86) else
292
r'\x64' if (self.target_cpu == 'amd64' and x64) else
293
r'\%s' % self.target_cpu
296
def cross_dir(self, forcex86=False):
298
Cross platform specific subfolder.
303
Use 'x86' as current architecture even if current acritecture is
309
'' if target architecture is current architecture,
310
'\current_target' if not.
312
current = 'x86' if forcex86 else self.current_cpu
314
'' if self.target_cpu == current else
315
self.target_dir().replace('\\', '\\%s_' % current)
321
Microsoft Visual Studio related registry informations.
325
platform_info: PlatformInfo
326
"PlatformInfo" instance.
328
HKEYS = (winreg.HKEY_USERS,
329
winreg.HKEY_CURRENT_USER,
330
winreg.HKEY_LOCAL_MACHINE,
331
winreg.HKEY_CLASSES_ROOT)
333
def __init__(self, platform_info):
334
self.pi = platform_info
337
def visualstudio(self):
339
Microsoft Visual Studio root registry key.
341
return 'VisualStudio'
346
Microsoft Visual Studio SxS registry key.
348
return os.path.join(self.visualstudio, 'SxS')
353
Microsoft Visual C++ VC7 registry key.
355
return os.path.join(self.sxs, 'VC7')
360
Microsoft Visual Studio VS7 registry key.
362
return os.path.join(self.sxs, 'VS7')
365
def vc_for_python(self):
367
Microsoft Visual C++ for Python registry key.
369
return r'DevDiv\VCForPython'
372
def microsoft_sdk(self):
374
Microsoft SDK registry key.
376
return 'Microsoft SDKs'
379
def windows_sdk(self):
381
Microsoft Windows/Platform SDK registry key.
383
return os.path.join(self.microsoft_sdk, 'Windows')
388
Microsoft .NET Framework SDK registry key.
390
return os.path.join(self.microsoft_sdk, 'NETFXSDK')
393
def windows_kits_roots(self):
395
Microsoft Windows Kits Roots registry key.
397
return r'Windows Kits\Installed Roots'
399
def microsoft(self, key, x86=False):
401
Return key in Microsoft software registry.
406
Registry key path where look.
408
Force x86 software registry.
414
node64 = '' if self.pi.current_is_x86() or x86 else r'\Wow6432Node'
415
return os.path.join('Software', node64, 'Microsoft', key)
417
def lookup(self, key, name):
419
Look for values in registry in Microsoft software registry.
424
Registry key path where look.
432
KEY_READ = winreg.KEY_READ
433
openkey = winreg.OpenKey
435
for hkey in self.HKEYS:
437
bkey = openkey(hkey, ms(key), 0, KEY_READ)
438
except (OSError, IOError):
439
if not self.pi.current_is_x86():
441
bkey = openkey(hkey, ms(key, True), 0, KEY_READ)
442
except (OSError, IOError):
447
return winreg.QueryValueEx(bkey, name)[0]
448
except (OSError, IOError):
454
Microsoft Windows and Visual Studio related system inormations.
458
registry_info: RegistryInfo
459
"RegistryInfo" instance.
461
Required Microsoft Visual C++ version.
464
# Variables and properties in this class use originals CamelCase variables
465
# names from Microsoft source files for more easy comparaison.
466
WinDir = safe_env.get('WinDir', '')
467
ProgramFiles = safe_env.get('ProgramFiles', '')
468
ProgramFilesx86 = safe_env.get('ProgramFiles(x86)', ProgramFiles)
470
def __init__(self, registry_info, vc_ver=None):
471
self.ri = registry_info
477
self.vc_ver = self.find_available_vc_vers()[-1]
479
err = 'No Microsoft Visual C++ version found'
480
raise distutils.errors.DistutilsPlatformError(err)
482
def find_available_vc_vers(self):
484
Find all available Microsoft Visual C++ versions.
486
vckeys = (self.ri.vc, self.ri.vc_for_python)
488
for hkey in self.ri.HKEYS:
491
bkey = winreg.OpenKey(hkey, key, 0, winreg.KEY_READ)
492
except (OSError, IOError):
494
subkeys, values, _ = winreg.QueryInfoKey(bkey)
495
for i in range(values):
497
ver = float(winreg.EnumValue(bkey, i)[0])
498
if ver not in vc_vers:
502
for i in range(subkeys):
504
ver = float(winreg.EnumKey(bkey, i))
505
if ver not in vc_vers:
509
return sorted(vc_vers)
512
def VSInstallDir(self):
514
Microsoft Visual Studio directory.
517
name = 'Microsoft Visual Studio %0.1f' % self.vc_ver
518
default = os.path.join(self.ProgramFilesx86, name)
520
# Try to get path from registry, if fail use default path
521
return self.ri.lookup(self.ri.vs, '%0.1f' % self.vc_ver) or default
524
def VCInstallDir(self):
526
Microsoft Visual C++ directory.
529
default = r'Microsoft Visual Studio %0.1f\VC' % self.vc_ver
530
guess_vc = os.path.join(self.ProgramFilesx86, default)
532
# Try to get "VC++ for Python" path from registry as default path
533
reg_path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vc_ver)
534
python_vc = self.ri.lookup(reg_path, 'installdir')
535
default_vc = os.path.join(python_vc, 'VC') if python_vc else guess_vc
537
# Try to get path from registry, if fail use default path
538
path = self.ri.lookup(self.ri.vc, '%0.1f' % self.vc_ver) or default_vc
540
if not os.path.isdir(path):
541
msg = 'Microsoft Visual C++ directory not found'
542
raise distutils.errors.DistutilsPlatformError(msg)
547
def WindowsSdkVersion(self):
549
Microsoft Windows SDK versions.
551
# Set Windows SDK versions for specified MSVC++ version
552
if self.vc_ver <= 9.0:
553
return ('7.0', '6.1', '6.0a')
554
elif self.vc_ver == 10.0:
555
return ('7.1', '7.0a')
556
elif self.vc_ver == 11.0:
557
return ('8.0', '8.0a')
558
elif self.vc_ver == 12.0:
559
return ('8.1', '8.1a')
560
elif self.vc_ver >= 14.0:
561
return ('10.0', '8.1')
564
def WindowsSdkDir(self):
566
Microsoft Windows SDK directory.
569
for ver in self.WindowsSdkVersion:
570
# Try to get it from registry
571
loc = os.path.join(self.ri.windows_sdk, 'v%s' % ver)
572
sdkdir = self.ri.lookup(loc, 'installationfolder')
575
if not sdkdir or not os.path.isdir(sdkdir):
576
# Try to get "VC++ for Python" version from registry
577
path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vc_ver)
578
install_base = self.ri.lookup(path, 'installdir')
580
sdkdir = os.path.join(install_base, 'WinSDK')
581
if not sdkdir or not os.path.isdir(sdkdir):
582
# If fail, use default new path
583
for ver in self.WindowsSdkVersion:
584
intver = ver[:ver.rfind('.')]
585
path = r'Microsoft SDKs\Windows Kits\%s' % (intver)
586
d = os.path.join(self.ProgramFiles, path)
589
if not sdkdir or not os.path.isdir(sdkdir):
590
# If fail, use default old path
591
for ver in self.WindowsSdkVersion:
592
path = r'Microsoft SDKs\Windows\v%s' % ver
593
d = os.path.join(self.ProgramFiles, path)
597
# If fail, use Platform SDK
598
sdkdir = os.path.join(self.VCInstallDir, 'PlatformSDK')
602
def WindowsSDKExecutablePath(self):
604
Microsoft Windows SDK executable directory.
606
# Find WinSDK NetFx Tools registry dir name
607
if self.vc_ver <= 11.0:
612
hidex86 = True if self.vc_ver <= 12.0 else False
613
arch = self.pi.current_dir(x64=True, hidex86=hidex86)
614
fx = 'WinSDK-NetFx%dTools%s' % (netfxver, arch.replace('\\', '-'))
616
# liste all possibles registry paths
618
if self.vc_ver >= 14.0:
619
for ver in self.NetFxSdkVersion:
620
regpaths += [os.path.join(self.ri.netfx_sdk, ver, fx)]
622
for ver in self.WindowsSdkVersion:
623
regpaths += [os.path.join(self.ri.windows_sdk, 'v%sA' % ver, fx)]
625
# Return installation folder from the more recent path
626
for path in regpaths:
627
execpath = self.ri.lookup(path, 'installationfolder')
633
def FSharpInstallDir(self):
635
Microsoft Visual F# directory.
637
path = r'%0.1f\Setup\F#' % self.vc_ver
638
path = os.path.join(self.ri.visualstudio, path)
639
return self.ri.lookup(path, 'productdir') or ''
642
def UniversalCRTSdkDir(self):
644
Microsoft Universal CRT SDK directory.
646
# Set Kit Roots versions for specified MSVC++ version
647
if self.vc_ver >= 14.0:
652
# Find path of the more recent Kit
654
sdkdir = self.ri.lookup(self.ri.windows_kits_roots,
661
def NetFxSdkVersion(self):
663
Microsoft .NET Framework SDK versions.
665
# Set FxSdk versions for specified MSVC++ version
666
if self.vc_ver >= 14.0:
667
return ('4.6.1', '4.6')
672
def NetFxSdkDir(self):
674
Microsoft .NET Framework SDK directory.
676
for ver in self.NetFxSdkVersion:
677
loc = os.path.join(self.ri.netfx_sdk, ver)
678
sdkdir = self.ri.lookup(loc, 'kitsinstallationfolder')
684
def FrameworkDir32(self):
686
Microsoft .NET Framework 32bit directory.
689
guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework')
691
# Try to get path from registry, if fail use default path
692
return self.ri.lookup(self.ri.vc, 'frameworkdir32') or guess_fw
695
def FrameworkDir64(self):
697
Microsoft .NET Framework 64bit directory.
700
guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework64')
702
# Try to get path from registry, if fail use default path
703
return self.ri.lookup(self.ri.vc, 'frameworkdir64') or guess_fw
706
def FrameworkVersion32(self):
708
Microsoft .NET Framework 32bit versions.
710
return self._find_dot_net_versions(32)
713
def FrameworkVersion64(self):
715
Microsoft .NET Framework 64bit versions.
717
return self._find_dot_net_versions(64)
719
def _find_dot_net_versions(self, bits=32):
721
Find Microsoft .NET Framework versions.
726
Platform number of bits: 32 or 64.
728
# Find actual .NET version
729
ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits) or ''
731
# Set .NET versions for specified MSVC++ version
732
if self.vc_ver >= 12.0:
733
frameworkver = (ver, 'v4.0')
734
elif self.vc_ver >= 10.0:
735
frameworkver = ('v4.0.30319' if ver.lower()[:2] != 'v4' else ver,
737
elif self.vc_ver == 9.0:
738
frameworkver = ('v3.5', 'v2.0.50727')
739
if self.vc_ver == 8.0:
740
frameworkver = ('v3.0', 'v2.0.50727')
744
class EnvironmentInfo:
746
Return environment variables for specified Microsoft Visual C++ version
747
and platform : Lib, Include, Path and libpath.
749
This function is compatible with Microsoft Visual C++ 9.0 to 14.0.
751
Script created by analysing Microsoft environment configuration files like
752
"vcvars[...].bat", "SetEnv.Cmd", "vcbuildtools.bat", ...
759
Required Microsoft Visual C++ version. If not set, autodetect the last
762
Minimum Microsoft Visual C++ version.
765
# Variables and properties in this class use originals CamelCase variables
766
# names from Microsoft source files for more easy comparaison.
768
def __init__(self, arch, vc_ver=None, vc_min_ver=None):
769
self.pi = PlatformInfo(arch)
770
self.ri = RegistryInfo(self.pi)
771
self.si = SystemInfo(self.ri, vc_ver)
774
if self.vc_ver < vc_min_ver:
775
err = 'No suitable Microsoft Visual C++ version found'
776
raise distutils.errors.DistutilsPlatformError(err)
781
Microsoft Visual C++ version.
783
return self.si.vc_ver
788
Microsoft Visual Studio Tools
790
paths = [r'Common7\IDE', r'Common7\Tools']
792
if self.vc_ver >= 14.0:
793
arch_subdir = self.pi.current_dir(hidex86=True, x64=True)
794
paths += [r'Common7\IDE\CommonExtensions\Microsoft\TestWindow']
795
paths += [r'Team Tools\Performance Tools']
796
paths += [r'Team Tools\Performance Tools%s' % arch_subdir]
798
return [os.path.join(self.si.VSInstallDir, path) for path in paths]
801
def VCIncludes(self):
803
Microsoft Visual C++ & Microsoft Foundation Class Includes
805
return [os.path.join(self.si.VCInstallDir, 'Include'),
806
os.path.join(self.si.VCInstallDir, r'ATLMFC\Include')]
809
def VCLibraries(self):
811
Microsoft Visual C++ & Microsoft Foundation Class Libraries
813
arch_subdir = self.pi.target_dir(hidex86=True)
814
paths = ['Lib%s' % arch_subdir, r'ATLMFC\Lib%s' % arch_subdir]
816
if self.vc_ver >= 14.0:
817
paths += [r'Lib\store%s' % arch_subdir]
819
return [os.path.join(self.si.VCInstallDir, path) for path in paths]
822
def VCStoreRefs(self):
824
Microsoft Visual C++ store references Libraries
826
if self.vc_ver < 14.0:
828
return [os.path.join(self.si.VCInstallDir, r'Lib\store\references')]
833
Microsoft Visual C++ Tools
836
tools = [os.path.join(si.VCInstallDir, 'VCPackages')]
838
forcex86 = True if self.vc_ver <= 10.0 else False
839
arch_subdir = self.pi.cross_dir(forcex86)
841
tools += [os.path.join(si.VCInstallDir, 'Bin%s' % arch_subdir)]
843
if self.vc_ver >= 14.0:
844
path = 'Bin%s' % self.pi.current_dir(hidex86=True)
845
tools += [os.path.join(si.VCInstallDir, path)]
848
tools += [os.path.join(si.VCInstallDir, 'Bin')]
853
def OSLibraries(self):
855
Microsoft Windows SDK Libraries
857
if self.vc_ver <= 10.0:
858
arch_subdir = self.pi.target_dir(hidex86=True, x64=True)
859
return [os.path.join(self.si.WindowsSdkDir, 'Lib%s' % arch_subdir)]
862
arch_subdir = self.pi.target_dir(x64=True)
863
lib = os.path.join(self.si.WindowsSdkDir, 'lib')
864
libver = self._get_content_dirname(lib)
865
return [os.path.join(lib, '%sum%s' % (libver, arch_subdir))]
868
def OSIncludes(self):
870
Microsoft Windows SDK Include
872
include = os.path.join(self.si.WindowsSdkDir, 'include')
874
if self.vc_ver <= 10.0:
875
return [include, os.path.join(include, 'gl')]
878
if self.vc_ver >= 14.0:
879
sdkver = self._get_content_dirname(include)
882
return [os.path.join(include, '%sshared' % sdkver),
883
os.path.join(include, '%sum' % sdkver),
884
os.path.join(include, '%swinrt' % sdkver)]
889
Microsoft Windows SDK Libraries Paths
891
ref = os.path.join(self.si.WindowsSdkDir, 'References')
894
if self.vc_ver <= 9.0:
895
libpath += self.OSLibraries
897
if self.vc_ver >= 11.0:
898
libpath += [os.path.join(ref, r'CommonConfiguration\Neutral')]
900
if self.vc_ver >= 14.0:
903
os.path.join(self.si.WindowsSdkDir, 'UnionMetadata'),
906
'Windows.Foundation.UniversalApiContract',
911
'Windows.Foundation.FoundationContract',
916
'Windows.Networking.Connectivity.WwanContract',
920
self.si.WindowsSdkDir,
923
'%0.1f' % self.vc_ver,
925
'CommonConfiguration',
934
Microsoft Windows SDK Tools
936
bin_dir = 'Bin' if self.vc_ver <= 11.0 else r'Bin\x86'
937
tools = [os.path.join(self.si.WindowsSdkDir, bin_dir)]
939
if not self.pi.current_is_x86():
940
arch_subdir = self.pi.current_dir(x64=True)
941
path = 'Bin%s' % arch_subdir
942
tools += [os.path.join(self.si.WindowsSdkDir, path)]
944
if self.vc_ver == 10.0 or self.vc_ver == 11.0:
945
if self.pi.target_is_x86():
948
arch_subdir = self.pi.current_dir(hidex86=True, x64=True)
949
path = r'Bin\NETFX 4.0 Tools%s' % arch_subdir
950
tools += [os.path.join(self.si.WindowsSdkDir, path)]
952
if self.si.WindowsSDKExecutablePath:
953
tools += [self.si.WindowsSDKExecutablePath]
960
Microsoft Windows SDK Setup
962
if self.vc_ver > 9.0:
965
return [os.path.join(self.si.WindowsSdkDir, 'Setup')]
970
Microsoft .NET Framework Tools
975
if self.vc_ver <= 10.0:
977
include64 = not pi.target_is_x86() and not pi.current_is_x86()
979
include32 = pi.target_is_x86() or pi.current_is_x86()
980
include64 = pi.current_cpu == 'amd64' or pi.target_cpu == 'amd64'
984
tools += [os.path.join(si.FrameworkDir32, ver)
985
for ver in si.FrameworkVersion32]
987
tools += [os.path.join(si.FrameworkDir64, ver)
988
for ver in si.FrameworkVersion64]
992
def NetFxSDKLibraries(self):
994
Microsoft .Net Framework SDK Libraries
996
if self.vc_ver < 14.0 or not self.si.NetFxSdkDir:
999
arch_subdir = self.pi.target_dir(x64=True)
1000
return [os.path.join(self.si.NetFxSdkDir, r'lib\um%s' % arch_subdir)]
1003
def NetFxSDKIncludes(self):
1005
Microsoft .Net Framework SDK Includes
1007
if self.vc_ver < 14.0 or not self.si.NetFxSdkDir:
1010
return [os.path.join(self.si.NetFxSdkDir, r'include\um')]
1015
Microsoft Visual Studio Team System Database
1017
return [os.path.join(self.si.VSInstallDir, r'VSTSDB\Deploy')]
1022
Microsoft Build Engine
1024
if self.vc_ver < 12.0:
1027
arch_subdir = self.pi.current_dir(hidex86=True)
1028
path = r'MSBuild\%0.1f\bin%s' % (self.vc_ver, arch_subdir)
1029
return [os.path.join(self.si.ProgramFilesx86, path)]
1032
def HTMLHelpWorkshop(self):
1034
Microsoft HTML Help Workshop
1036
if self.vc_ver < 11.0:
1039
return [os.path.join(self.si.ProgramFilesx86, 'HTML Help Workshop')]
1042
def UCRTLibraries(self):
1044
Microsoft Universal CRT Libraries
1046
if self.vc_ver < 14.0:
1049
arch_subdir = self.pi.target_dir(x64=True)
1050
lib = os.path.join(self.si.UniversalCRTSdkDir, 'lib')
1051
ucrtver = self._get_content_dirname(lib)
1052
return [os.path.join(lib, '%sucrt%s' % (ucrtver, arch_subdir))]
1055
def UCRTIncludes(self):
1057
Microsoft Universal CRT Include
1059
if self.vc_ver < 14.0:
1062
include = os.path.join(self.si.UniversalCRTSdkDir, 'include')
1063
ucrtver = self._get_content_dirname(include)
1064
return [os.path.join(include, '%sucrt' % ucrtver)]
1071
if self.vc_ver < 11.0 and self.vc_ver > 12.0:
1074
return self.si.FSharpInstallDir
1077
def VCRuntimeRedist(self):
1079
Microsoft Visual C++ runtime redistribuable dll
1081
arch_subdir = self.pi.target_dir(x64=True)
1082
vcruntime = 'redist%s\\Microsoft.VC%d0.CRT\\vcruntime%d0.dll'
1083
vcruntime = vcruntime % (arch_subdir, self.vc_ver, self.vc_ver)
1084
return os.path.join(self.si.VCInstallDir, vcruntime)
1086
def return_env(self, exists=True):
1088
Return environment dict.
1093
It True, only return existing paths.
1096
include=self._build_paths('include',
1100
self.NetFxSDKIncludes],
1102
lib=self._build_paths('lib',
1107
self.NetFxSDKLibraries],
1109
libpath=self._build_paths('libpath',
1115
path=self._build_paths('path',
1123
self.HTMLHelpWorkshop,
1127
if self.vc_ver >= 14 and os.path.isfile(self.VCRuntimeRedist):
1128
env['py_vcruntime_redist'] = self.VCRuntimeRedist
1131
def _build_paths(self, name, spec_path_lists, exists):
1133
Given an environment variable name and specified paths,
1134
return a pathsep-separated string of paths containing
1135
unique, extant, directories from those paths and from
1136
the environment variable. Raise an error if no paths
1139
# flatten spec_path_lists
1140
spec_paths = itertools.chain.from_iterable(spec_path_lists)
1141
env_paths = safe_env.get(name, '').split(os.pathsep)
1142
paths = itertools.chain(spec_paths, env_paths)
1143
extant_paths = list(filter(os.path.isdir, paths)) if exists else paths
1144
if not extant_paths:
1145
msg = "%s environment variable is empty" % name.upper()
1146
raise distutils.errors.DistutilsPlatformError(msg)
1147
unique_paths = self._unique_everseen(extant_paths)
1148
return os.pathsep.join(unique_paths)
1151
def _unique_everseen(self, iterable, key=None):
1153
List unique elements, preserving order.
1154
Remember all elements ever seen.
1156
_unique_everseen('AAAABBBCCDAABBB') --> A B C D
1158
_unique_everseen('ABBCcAD', str.lower) --> A B C D
1163
for element in filterfalse(seen.__contains__, iterable):
1167
for element in iterable:
1173
def _get_content_dirname(self, path):
1175
Return name of the first dir in path or '' if no dir found.
1180
Path where search dir.
1188
name = os.listdir(path)
1190
return '%s\\' % name[0]
1192
except (OSError, IOError):