Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/setuptools/msvc.py
7763 views
"""1Improved support for Microsoft Visual C++ compilers.23Known supported compilers:4--------------------------5Microsoft Visual C++ 9.0:6Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64)7Microsoft Windows SDK 6.1 (x86, x64, ia64)8Microsoft Windows SDK 7.0 (x86, x64, ia64)910Microsoft Visual C++ 10.0:11Microsoft Windows SDK 7.1 (x86, x64, ia64)1213Microsoft Visual C++ 14.X:14Microsoft Visual C++ Build Tools 2015 (x86, x64, arm)15Microsoft Visual Studio Build Tools 2017 (x86, x64, arm, arm64)16Microsoft Visual Studio Build Tools 2019 (x86, x64, arm, arm64)1718This may also support compilers shipped with compatible Visual Studio versions.19"""2021import json22from io import open23from os import listdir, pathsep24from os.path import join, isfile, isdir, dirname25import sys26import platform27import itertools28import subprocess29import distutils.errors30from setuptools.extern.packaging.version import LegacyVersion3132from setuptools.extern.six.moves import filterfalse3334from .monkey import get_unpatched3536if platform.system() == 'Windows':37from setuptools.extern.six.moves import winreg38from os import environ39else:40# Mock winreg and environ so the module can be imported on this platform.4142class winreg:43HKEY_USERS = None44HKEY_CURRENT_USER = None45HKEY_LOCAL_MACHINE = None46HKEY_CLASSES_ROOT = None4748environ = dict()4950_msvc9_suppress_errors = (51# msvc9compiler isn't available on some platforms52ImportError,5354# msvc9compiler raises DistutilsPlatformError in some55# environments. See #1118.56distutils.errors.DistutilsPlatformError,57)5859try:60from distutils.msvc9compiler import Reg61except _msvc9_suppress_errors:62pass636465def msvc9_find_vcvarsall(version):66"""67Patched "distutils.msvc9compiler.find_vcvarsall" to use the standalone68compiler build for Python69(VCForPython / Microsoft Visual C++ Compiler for Python 2.7).7071Fall back to original behavior when the standalone compiler is not72available.7374Redirect the path of "vcvarsall.bat".7576Parameters77----------78version: float79Required Microsoft Visual C++ version.8081Return82------83str84vcvarsall.bat path85"""86vc_base = r'Software\%sMicrosoft\DevDiv\VCForPython\%0.1f'87key = vc_base % ('', version)88try:89# Per-user installs register the compiler path here90productdir = Reg.get_value(key, "installdir")91except KeyError:92try:93# All-user installs on a 64-bit system register here94key = vc_base % ('Wow6432Node\\', version)95productdir = Reg.get_value(key, "installdir")96except KeyError:97productdir = None9899if productdir:100vcvarsall = join(productdir, "vcvarsall.bat")101if isfile(vcvarsall):102return vcvarsall103104return get_unpatched(msvc9_find_vcvarsall)(version)105106107def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs):108"""109Patched "distutils.msvc9compiler.query_vcvarsall" for support extra110Microsoft Visual C++ 9.0 and 10.0 compilers.111112Set environment without use of "vcvarsall.bat".113114Parameters115----------116ver: float117Required Microsoft Visual C++ version.118arch: str119Target architecture.120121Return122------123dict124environment125"""126# Try to get environment from vcvarsall.bat (Classical way)127try:128orig = get_unpatched(msvc9_query_vcvarsall)129return orig(ver, arch, *args, **kwargs)130except distutils.errors.DistutilsPlatformError:131# Pass error if Vcvarsall.bat is missing132pass133except ValueError:134# Pass error if environment not set after executing vcvarsall.bat135pass136137# If error, try to set environment directly138try:139return EnvironmentInfo(arch, ver).return_env()140except distutils.errors.DistutilsPlatformError as exc:141_augment_exception(exc, ver, arch)142raise143144145def _msvc14_find_vc2015():146"""Python 3.8 "distutils/_msvccompiler.py" backport"""147try:148key = winreg.OpenKey(149winreg.HKEY_LOCAL_MACHINE,150r"Software\Microsoft\VisualStudio\SxS\VC7",1510,152winreg.KEY_READ | winreg.KEY_WOW64_32KEY153)154except OSError:155return None, None156157best_version = 0158best_dir = None159with key:160for i in itertools.count():161try:162v, vc_dir, vt = winreg.EnumValue(key, i)163except OSError:164break165if v and vt == winreg.REG_SZ and isdir(vc_dir):166try:167version = int(float(v))168except (ValueError, TypeError):169continue170if version >= 14 and version > best_version:171best_version, best_dir = version, vc_dir172return best_version, best_dir173174175def _msvc14_find_vc2017():176"""Python 3.8 "distutils/_msvccompiler.py" backport177178Returns "15, path" based on the result of invoking vswhere.exe179If no install is found, returns "None, None"180181The version is returned to avoid unnecessarily changing the function182result. It may be ignored when the path is not None.183184If vswhere.exe is not available, by definition, VS 2017 is not185installed.186"""187root = environ.get("ProgramFiles(x86)") or environ.get("ProgramFiles")188if not root:189return None, None190191try:192path = subprocess.check_output([193join(root, "Microsoft Visual Studio", "Installer", "vswhere.exe"),194"-latest",195"-prerelease",196"-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",197"-property", "installationPath",198"-products", "*",199]).decode(encoding="mbcs", errors="strict").strip()200except (subprocess.CalledProcessError, OSError, UnicodeDecodeError):201return None, None202203path = join(path, "VC", "Auxiliary", "Build")204if isdir(path):205return 15, path206207return None, None208209210PLAT_SPEC_TO_RUNTIME = {211'x86': 'x86',212'x86_amd64': 'x64',213'x86_arm': 'arm',214'x86_arm64': 'arm64'215}216217218def _msvc14_find_vcvarsall(plat_spec):219"""Python 3.8 "distutils/_msvccompiler.py" backport"""220_, best_dir = _msvc14_find_vc2017()221vcruntime = None222223if plat_spec in PLAT_SPEC_TO_RUNTIME:224vcruntime_plat = PLAT_SPEC_TO_RUNTIME[plat_spec]225else:226vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86'227228if best_dir:229vcredist = join(best_dir, "..", "..", "redist", "MSVC", "**",230vcruntime_plat, "Microsoft.VC14*.CRT",231"vcruntime140.dll")232try:233import glob234vcruntime = glob.glob(vcredist, recursive=True)[-1]235except (ImportError, OSError, LookupError):236vcruntime = None237238if not best_dir:239best_version, best_dir = _msvc14_find_vc2015()240if best_version:241vcruntime = join(best_dir, 'redist', vcruntime_plat,242"Microsoft.VC140.CRT", "vcruntime140.dll")243244if not best_dir:245return None, None246247vcvarsall = join(best_dir, "vcvarsall.bat")248if not isfile(vcvarsall):249return None, None250251if not vcruntime or not isfile(vcruntime):252vcruntime = None253254return vcvarsall, vcruntime255256257def _msvc14_get_vc_env(plat_spec):258"""Python 3.8 "distutils/_msvccompiler.py" backport"""259if "DISTUTILS_USE_SDK" in environ:260return {261key.lower(): value262for key, value in environ.items()263}264265vcvarsall, vcruntime = _msvc14_find_vcvarsall(plat_spec)266if not vcvarsall:267raise distutils.errors.DistutilsPlatformError(268"Unable to find vcvarsall.bat"269)270271try:272out = subprocess.check_output(273'cmd /u /c "{}" {} && set'.format(vcvarsall, plat_spec),274stderr=subprocess.STDOUT,275).decode('utf-16le', errors='replace')276except subprocess.CalledProcessError as exc:277raise distutils.errors.DistutilsPlatformError(278"Error executing {}".format(exc.cmd)279) from exc280281env = {282key.lower(): value283for key, _, value in284(line.partition('=') for line in out.splitlines())285if key and value286}287288if vcruntime:289env['py_vcruntime_redist'] = vcruntime290return env291292293def msvc14_get_vc_env(plat_spec):294"""295Patched "distutils._msvccompiler._get_vc_env" for support extra296Microsoft Visual C++ 14.X compilers.297298Set environment without use of "vcvarsall.bat".299300Parameters301----------302plat_spec: str303Target architecture.304305Return306------307dict308environment309"""310311# Always use backport from CPython 3.8312try:313return _msvc14_get_vc_env(plat_spec)314except distutils.errors.DistutilsPlatformError as exc:315_augment_exception(exc, 14.0)316raise317318319def msvc14_gen_lib_options(*args, **kwargs):320"""321Patched "distutils._msvccompiler.gen_lib_options" for fix322compatibility between "numpy.distutils" and "distutils._msvccompiler"323(for Numpy < 1.11.2)324"""325if "numpy.distutils" in sys.modules:326import numpy as np327if LegacyVersion(np.__version__) < LegacyVersion('1.11.2'):328return np.distutils.ccompiler.gen_lib_options(*args, **kwargs)329return get_unpatched(msvc14_gen_lib_options)(*args, **kwargs)330331332def _augment_exception(exc, version, arch=''):333"""334Add details to the exception message to help guide the user335as to what action will resolve it.336"""337# Error if MSVC++ directory not found or environment not set338message = exc.args[0]339340if "vcvarsall" in message.lower() or "visual c" in message.lower():341# Special error message if MSVC++ not installed342tmpl = 'Microsoft Visual C++ {version:0.1f} is required.'343message = tmpl.format(**locals())344msdownload = 'www.microsoft.com/download/details.aspx?id=%d'345if version == 9.0:346if arch.lower().find('ia64') > -1:347# For VC++ 9.0, if IA64 support is needed, redirect user348# to Windows SDK 7.0.349# Note: No download link available from Microsoft.350message += ' Get it with "Microsoft Windows SDK 7.0"'351else:352# For VC++ 9.0 redirect user to Vc++ for Python 2.7 :353# This redirection link is maintained by Microsoft.354# Contact [email protected] if it needs updating.355message += ' Get it from http://aka.ms/vcpython27'356elif version == 10.0:357# For VC++ 10.0 Redirect user to Windows SDK 7.1358message += ' Get it with "Microsoft Windows SDK 7.1": '359message += msdownload % 8279360elif version >= 14.0:361# For VC++ 14.X Redirect user to latest Visual C++ Build Tools362message += (' Get it with "Build Tools for Visual Studio": '363r'https://visualstudio.microsoft.com/downloads/')364365exc.args = (message, )366367368class PlatformInfo:369"""370Current and Target Architectures information.371372Parameters373----------374arch: str375Target architecture.376"""377current_cpu = environ.get('processor_architecture', '').lower()378379def __init__(self, arch):380self.arch = arch.lower().replace('x64', 'amd64')381382@property383def target_cpu(self):384"""385Return Target CPU architecture.386387Return388------389str390Target CPU391"""392return self.arch[self.arch.find('_') + 1:]393394def target_is_x86(self):395"""396Return True if target CPU is x86 32 bits..397398Return399------400bool401CPU is x86 32 bits402"""403return self.target_cpu == 'x86'404405def current_is_x86(self):406"""407Return True if current CPU is x86 32 bits..408409Return410------411bool412CPU is x86 32 bits413"""414return self.current_cpu == 'x86'415416def current_dir(self, hidex86=False, x64=False):417"""418Current platform specific subfolder.419420Parameters421----------422hidex86: bool423return '' and not '\x86' if architecture is x86.424x64: bool425return '\x64' and not '\amd64' if architecture is amd64.426427Return428------429str430subfolder: '\target', or '' (see hidex86 parameter)431"""432return (433'' if (self.current_cpu == 'x86' and hidex86) else434r'\x64' if (self.current_cpu == 'amd64' and x64) else435r'\%s' % self.current_cpu436)437438def target_dir(self, hidex86=False, x64=False):439r"""440Target platform specific subfolder.441442Parameters443----------444hidex86: bool445return '' and not '\x86' if architecture is x86.446x64: bool447return '\x64' and not '\amd64' if architecture is amd64.448449Return450------451str452subfolder: '\current', or '' (see hidex86 parameter)453"""454return (455'' if (self.target_cpu == 'x86' and hidex86) else456r'\x64' if (self.target_cpu == 'amd64' and x64) else457r'\%s' % self.target_cpu458)459460def cross_dir(self, forcex86=False):461r"""462Cross platform specific subfolder.463464Parameters465----------466forcex86: bool467Use 'x86' as current architecture even if current architecture is468not x86.469470Return471------472str473subfolder: '' if target architecture is current architecture,474'\current_target' if not.475"""476current = 'x86' if forcex86 else self.current_cpu477return (478'' if self.target_cpu == current else479self.target_dir().replace('\\', '\\%s_' % current)480)481482483class RegistryInfo:484"""485Microsoft Visual Studio related registry information.486487Parameters488----------489platform_info: PlatformInfo490"PlatformInfo" instance.491"""492HKEYS = (winreg.HKEY_USERS,493winreg.HKEY_CURRENT_USER,494winreg.HKEY_LOCAL_MACHINE,495winreg.HKEY_CLASSES_ROOT)496497def __init__(self, platform_info):498self.pi = platform_info499500@property501def visualstudio(self):502"""503Microsoft Visual Studio root registry key.504505Return506------507str508Registry key509"""510return 'VisualStudio'511512@property513def sxs(self):514"""515Microsoft Visual Studio SxS registry key.516517Return518------519str520Registry key521"""522return join(self.visualstudio, 'SxS')523524@property525def vc(self):526"""527Microsoft Visual C++ VC7 registry key.528529Return530------531str532Registry key533"""534return join(self.sxs, 'VC7')535536@property537def vs(self):538"""539Microsoft Visual Studio VS7 registry key.540541Return542------543str544Registry key545"""546return join(self.sxs, 'VS7')547548@property549def vc_for_python(self):550"""551Microsoft Visual C++ for Python registry key.552553Return554------555str556Registry key557"""558return r'DevDiv\VCForPython'559560@property561def microsoft_sdk(self):562"""563Microsoft SDK registry key.564565Return566------567str568Registry key569"""570return 'Microsoft SDKs'571572@property573def windows_sdk(self):574"""575Microsoft Windows/Platform SDK registry key.576577Return578------579str580Registry key581"""582return join(self.microsoft_sdk, 'Windows')583584@property585def netfx_sdk(self):586"""587Microsoft .NET Framework SDK registry key.588589Return590------591str592Registry key593"""594return join(self.microsoft_sdk, 'NETFXSDK')595596@property597def windows_kits_roots(self):598"""599Microsoft Windows Kits Roots registry key.600601Return602------603str604Registry key605"""606return r'Windows Kits\Installed Roots'607608def microsoft(self, key, x86=False):609"""610Return key in Microsoft software registry.611612Parameters613----------614key: str615Registry key path where look.616x86: str617Force x86 software registry.618619Return620------621str622Registry key623"""624node64 = '' if self.pi.current_is_x86() or x86 else 'Wow6432Node'625return join('Software', node64, 'Microsoft', key)626627def lookup(self, key, name):628"""629Look for values in registry in Microsoft software registry.630631Parameters632----------633key: str634Registry key path where look.635name: str636Value name to find.637638Return639------640str641value642"""643key_read = winreg.KEY_READ644openkey = winreg.OpenKey645closekey = winreg.CloseKey646ms = self.microsoft647for hkey in self.HKEYS:648bkey = None649try:650bkey = openkey(hkey, ms(key), 0, key_read)651except (OSError, IOError):652if not self.pi.current_is_x86():653try:654bkey = openkey(hkey, ms(key, True), 0, key_read)655except (OSError, IOError):656continue657else:658continue659try:660return winreg.QueryValueEx(bkey, name)[0]661except (OSError, IOError):662pass663finally:664if bkey:665closekey(bkey)666667668class SystemInfo:669"""670Microsoft Windows and Visual Studio related system information.671672Parameters673----------674registry_info: RegistryInfo675"RegistryInfo" instance.676vc_ver: float677Required Microsoft Visual C++ version.678"""679680# Variables and properties in this class use originals CamelCase variables681# names from Microsoft source files for more easy comparison.682WinDir = environ.get('WinDir', '')683ProgramFiles = environ.get('ProgramFiles', '')684ProgramFilesx86 = environ.get('ProgramFiles(x86)', ProgramFiles)685686def __init__(self, registry_info, vc_ver=None):687self.ri = registry_info688self.pi = self.ri.pi689690self.known_vs_paths = self.find_programdata_vs_vers()691692# Except for VS15+, VC version is aligned with VS version693self.vs_ver = self.vc_ver = (694vc_ver or self._find_latest_available_vs_ver())695696def _find_latest_available_vs_ver(self):697"""698Find the latest VC version699700Return701------702float703version704"""705reg_vc_vers = self.find_reg_vs_vers()706707if not (reg_vc_vers or self.known_vs_paths):708raise distutils.errors.DistutilsPlatformError(709'No Microsoft Visual C++ version found')710711vc_vers = set(reg_vc_vers)712vc_vers.update(self.known_vs_paths)713return sorted(vc_vers)[-1]714715def find_reg_vs_vers(self):716"""717Find Microsoft Visual Studio versions available in registry.718719Return720------721list of float722Versions723"""724ms = self.ri.microsoft725vckeys = (self.ri.vc, self.ri.vc_for_python, self.ri.vs)726vs_vers = []727for hkey in self.ri.HKEYS:728for key in vckeys:729try:730bkey = winreg.OpenKey(hkey, ms(key), 0, winreg.KEY_READ)731except (OSError, IOError):732continue733with bkey:734subkeys, values, _ = winreg.QueryInfoKey(bkey)735for i in range(values):736try:737ver = float(winreg.EnumValue(bkey, i)[0])738if ver not in vs_vers:739vs_vers.append(ver)740except ValueError:741pass742for i in range(subkeys):743try:744ver = float(winreg.EnumKey(bkey, i))745if ver not in vs_vers:746vs_vers.append(ver)747except ValueError:748pass749return sorted(vs_vers)750751def find_programdata_vs_vers(self):752r"""753Find Visual studio 2017+ versions from information in754"C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances".755756Return757------758dict759float version as key, path as value.760"""761vs_versions = {}762instances_dir = \763r'C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances'764765try:766hashed_names = listdir(instances_dir)767768except (OSError, IOError):769# Directory not exists with all Visual Studio versions770return vs_versions771772for name in hashed_names:773try:774# Get VS installation path from "state.json" file775state_path = join(instances_dir, name, 'state.json')776with open(state_path, 'rt', encoding='utf-8') as state_file:777state = json.load(state_file)778vs_path = state['installationPath']779780# Raises OSError if this VS installation does not contain VC781listdir(join(vs_path, r'VC\Tools\MSVC'))782783# Store version and path784vs_versions[self._as_float_version(785state['installationVersion'])] = vs_path786787except (OSError, IOError, KeyError):788# Skip if "state.json" file is missing or bad format789continue790791return vs_versions792793@staticmethod794def _as_float_version(version):795"""796Return a string version as a simplified float version (major.minor)797798Parameters799----------800version: str801Version.802803Return804------805float806version807"""808return float('.'.join(version.split('.')[:2]))809810@property811def VSInstallDir(self):812"""813Microsoft Visual Studio directory.814815Return816------817str818path819"""820# Default path821default = join(self.ProgramFilesx86,822'Microsoft Visual Studio %0.1f' % self.vs_ver)823824# Try to get path from registry, if fail use default path825return self.ri.lookup(self.ri.vs, '%0.1f' % self.vs_ver) or default826827@property828def VCInstallDir(self):829"""830Microsoft Visual C++ directory.831832Return833------834str835path836"""837path = self._guess_vc() or self._guess_vc_legacy()838839if not isdir(path):840msg = 'Microsoft Visual C++ directory not found'841raise distutils.errors.DistutilsPlatformError(msg)842843return path844845def _guess_vc(self):846"""847Locate Visual C++ for VS2017+.848849Return850------851str852path853"""854if self.vs_ver <= 14.0:855return ''856857try:858# First search in known VS paths859vs_dir = self.known_vs_paths[self.vs_ver]860except KeyError:861# Else, search with path from registry862vs_dir = self.VSInstallDir863864guess_vc = join(vs_dir, r'VC\Tools\MSVC')865866# Subdir with VC exact version as name867try:868# Update the VC version with real one instead of VS version869vc_ver = listdir(guess_vc)[-1]870self.vc_ver = self._as_float_version(vc_ver)871return join(guess_vc, vc_ver)872except (OSError, IOError, IndexError):873return ''874875def _guess_vc_legacy(self):876"""877Locate Visual C++ for versions prior to 2017.878879Return880------881str882path883"""884default = join(self.ProgramFilesx86,885r'Microsoft Visual Studio %0.1f\VC' % self.vs_ver)886887# Try to get "VC++ for Python" path from registry as default path888reg_path = join(self.ri.vc_for_python, '%0.1f' % self.vs_ver)889python_vc = self.ri.lookup(reg_path, 'installdir')890default_vc = join(python_vc, 'VC') if python_vc else default891892# Try to get path from registry, if fail use default path893return self.ri.lookup(self.ri.vc, '%0.1f' % self.vs_ver) or default_vc894895@property896def WindowsSdkVersion(self):897"""898Microsoft Windows SDK versions for specified MSVC++ version.899900Return901------902tuple of str903versions904"""905if self.vs_ver <= 9.0:906return '7.0', '6.1', '6.0a'907elif self.vs_ver == 10.0:908return '7.1', '7.0a'909elif self.vs_ver == 11.0:910return '8.0', '8.0a'911elif self.vs_ver == 12.0:912return '8.1', '8.1a'913elif self.vs_ver >= 14.0:914return '10.0', '8.1'915916@property917def WindowsSdkLastVersion(self):918"""919Microsoft Windows SDK last version.920921Return922------923str924version925"""926return self._use_last_dir_name(join(self.WindowsSdkDir, 'lib'))927928@property929def WindowsSdkDir(self):930"""931Microsoft Windows SDK directory.932933Return934------935str936path937"""938sdkdir = ''939for ver in self.WindowsSdkVersion:940# Try to get it from registry941loc = join(self.ri.windows_sdk, 'v%s' % ver)942sdkdir = self.ri.lookup(loc, 'installationfolder')943if sdkdir:944break945if not sdkdir or not isdir(sdkdir):946# Try to get "VC++ for Python" version from registry947path = join(self.ri.vc_for_python, '%0.1f' % self.vc_ver)948install_base = self.ri.lookup(path, 'installdir')949if install_base:950sdkdir = join(install_base, 'WinSDK')951if not sdkdir or not isdir(sdkdir):952# If fail, use default new path953for ver in self.WindowsSdkVersion:954intver = ver[:ver.rfind('.')]955path = r'Microsoft SDKs\Windows Kits\%s' % intver956d = join(self.ProgramFiles, path)957if isdir(d):958sdkdir = d959if not sdkdir or not isdir(sdkdir):960# If fail, use default old path961for ver in self.WindowsSdkVersion:962path = r'Microsoft SDKs\Windows\v%s' % ver963d = join(self.ProgramFiles, path)964if isdir(d):965sdkdir = d966if not sdkdir:967# If fail, use Platform SDK968sdkdir = join(self.VCInstallDir, 'PlatformSDK')969return sdkdir970971@property972def WindowsSDKExecutablePath(self):973"""974Microsoft Windows SDK executable directory.975976Return977------978str979path980"""981# Find WinSDK NetFx Tools registry dir name982if self.vs_ver <= 11.0:983netfxver = 35984arch = ''985else:986netfxver = 40987hidex86 = True if self.vs_ver <= 12.0 else False988arch = self.pi.current_dir(x64=True, hidex86=hidex86)989fx = 'WinSDK-NetFx%dTools%s' % (netfxver, arch.replace('\\', '-'))990991# list all possibles registry paths992regpaths = []993if self.vs_ver >= 14.0:994for ver in self.NetFxSdkVersion:995regpaths += [join(self.ri.netfx_sdk, ver, fx)]996997for ver in self.WindowsSdkVersion:998regpaths += [join(self.ri.windows_sdk, 'v%sA' % ver, fx)]9991000# Return installation folder from the more recent path1001for path in regpaths:1002execpath = self.ri.lookup(path, 'installationfolder')1003if execpath:1004return execpath10051006@property1007def FSharpInstallDir(self):1008"""1009Microsoft Visual F# directory.10101011Return1012------1013str1014path1015"""1016path = join(self.ri.visualstudio, r'%0.1f\Setup\F#' % self.vs_ver)1017return self.ri.lookup(path, 'productdir') or ''10181019@property1020def UniversalCRTSdkDir(self):1021"""1022Microsoft Universal CRT SDK directory.10231024Return1025------1026str1027path1028"""1029# Set Kit Roots versions for specified MSVC++ version1030vers = ('10', '81') if self.vs_ver >= 14.0 else ()10311032# Find path of the more recent Kit1033for ver in vers:1034sdkdir = self.ri.lookup(self.ri.windows_kits_roots,1035'kitsroot%s' % ver)1036if sdkdir:1037return sdkdir or ''10381039@property1040def UniversalCRTSdkLastVersion(self):1041"""1042Microsoft Universal C Runtime SDK last version.10431044Return1045------1046str1047version1048"""1049return self._use_last_dir_name(join(self.UniversalCRTSdkDir, 'lib'))10501051@property1052def NetFxSdkVersion(self):1053"""1054Microsoft .NET Framework SDK versions.10551056Return1057------1058tuple of str1059versions1060"""1061# Set FxSdk versions for specified VS version1062return (('4.7.2', '4.7.1', '4.7',1063'4.6.2', '4.6.1', '4.6',1064'4.5.2', '4.5.1', '4.5')1065if self.vs_ver >= 14.0 else ())10661067@property1068def NetFxSdkDir(self):1069"""1070Microsoft .NET Framework SDK directory.10711072Return1073------1074str1075path1076"""1077sdkdir = ''1078for ver in self.NetFxSdkVersion:1079loc = join(self.ri.netfx_sdk, ver)1080sdkdir = self.ri.lookup(loc, 'kitsinstallationfolder')1081if sdkdir:1082break1083return sdkdir10841085@property1086def FrameworkDir32(self):1087"""1088Microsoft .NET Framework 32bit directory.10891090Return1091------1092str1093path1094"""1095# Default path1096guess_fw = join(self.WinDir, r'Microsoft.NET\Framework')10971098# Try to get path from registry, if fail use default path1099return self.ri.lookup(self.ri.vc, 'frameworkdir32') or guess_fw11001101@property1102def FrameworkDir64(self):1103"""1104Microsoft .NET Framework 64bit directory.11051106Return1107------1108str1109path1110"""1111# Default path1112guess_fw = join(self.WinDir, r'Microsoft.NET\Framework64')11131114# Try to get path from registry, if fail use default path1115return self.ri.lookup(self.ri.vc, 'frameworkdir64') or guess_fw11161117@property1118def FrameworkVersion32(self):1119"""1120Microsoft .NET Framework 32bit versions.11211122Return1123------1124tuple of str1125versions1126"""1127return self._find_dot_net_versions(32)11281129@property1130def FrameworkVersion64(self):1131"""1132Microsoft .NET Framework 64bit versions.11331134Return1135------1136tuple of str1137versions1138"""1139return self._find_dot_net_versions(64)11401141def _find_dot_net_versions(self, bits):1142"""1143Find Microsoft .NET Framework versions.11441145Parameters1146----------1147bits: int1148Platform number of bits: 32 or 64.11491150Return1151------1152tuple of str1153versions1154"""1155# Find actual .NET version in registry1156reg_ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits)1157dot_net_dir = getattr(self, 'FrameworkDir%d' % bits)1158ver = reg_ver or self._use_last_dir_name(dot_net_dir, 'v') or ''11591160# Set .NET versions for specified MSVC++ version1161if self.vs_ver >= 12.0:1162return ver, 'v4.0'1163elif self.vs_ver >= 10.0:1164return 'v4.0.30319' if ver.lower()[:2] != 'v4' else ver, 'v3.5'1165elif self.vs_ver == 9.0:1166return 'v3.5', 'v2.0.50727'1167elif self.vs_ver == 8.0:1168return 'v3.0', 'v2.0.50727'11691170@staticmethod1171def _use_last_dir_name(path, prefix=''):1172"""1173Return name of the last dir in path or '' if no dir found.11741175Parameters1176----------1177path: str1178Use dirs in this path1179prefix: str1180Use only dirs starting by this prefix11811182Return1183------1184str1185name1186"""1187matching_dirs = (1188dir_name1189for dir_name in reversed(listdir(path))1190if isdir(join(path, dir_name)) and1191dir_name.startswith(prefix)1192)1193return next(matching_dirs, None) or ''119411951196class EnvironmentInfo:1197"""1198Return environment variables for specified Microsoft Visual C++ version1199and platform : Lib, Include, Path and libpath.12001201This function is compatible with Microsoft Visual C++ 9.0 to 14.X.12021203Script created by analysing Microsoft environment configuration files like1204"vcvars[...].bat", "SetEnv.Cmd", "vcbuildtools.bat", ...12051206Parameters1207----------1208arch: str1209Target architecture.1210vc_ver: float1211Required Microsoft Visual C++ version. If not set, autodetect the last1212version.1213vc_min_ver: float1214Minimum Microsoft Visual C++ version.1215"""12161217# Variables and properties in this class use originals CamelCase variables1218# names from Microsoft source files for more easy comparison.12191220def __init__(self, arch, vc_ver=None, vc_min_ver=0):1221self.pi = PlatformInfo(arch)1222self.ri = RegistryInfo(self.pi)1223self.si = SystemInfo(self.ri, vc_ver)12241225if self.vc_ver < vc_min_ver:1226err = 'No suitable Microsoft Visual C++ version found'1227raise distutils.errors.DistutilsPlatformError(err)12281229@property1230def vs_ver(self):1231"""1232Microsoft Visual Studio.12331234Return1235------1236float1237version1238"""1239return self.si.vs_ver12401241@property1242def vc_ver(self):1243"""1244Microsoft Visual C++ version.12451246Return1247------1248float1249version1250"""1251return self.si.vc_ver12521253@property1254def VSTools(self):1255"""1256Microsoft Visual Studio Tools.12571258Return1259------1260list of str1261paths1262"""1263paths = [r'Common7\IDE', r'Common7\Tools']12641265if self.vs_ver >= 14.0:1266arch_subdir = self.pi.current_dir(hidex86=True, x64=True)1267paths += [r'Common7\IDE\CommonExtensions\Microsoft\TestWindow']1268paths += [r'Team Tools\Performance Tools']1269paths += [r'Team Tools\Performance Tools%s' % arch_subdir]12701271return [join(self.si.VSInstallDir, path) for path in paths]12721273@property1274def VCIncludes(self):1275"""1276Microsoft Visual C++ & Microsoft Foundation Class Includes.12771278Return1279------1280list of str1281paths1282"""1283return [join(self.si.VCInstallDir, 'Include'),1284join(self.si.VCInstallDir, r'ATLMFC\Include')]12851286@property1287def VCLibraries(self):1288"""1289Microsoft Visual C++ & Microsoft Foundation Class Libraries.12901291Return1292------1293list of str1294paths1295"""1296if self.vs_ver >= 15.0:1297arch_subdir = self.pi.target_dir(x64=True)1298else:1299arch_subdir = self.pi.target_dir(hidex86=True)1300paths = ['Lib%s' % arch_subdir, r'ATLMFC\Lib%s' % arch_subdir]13011302if self.vs_ver >= 14.0:1303paths += [r'Lib\store%s' % arch_subdir]13041305return [join(self.si.VCInstallDir, path) for path in paths]13061307@property1308def VCStoreRefs(self):1309"""1310Microsoft Visual C++ store references Libraries.13111312Return1313------1314list of str1315paths1316"""1317if self.vs_ver < 14.0:1318return []1319return [join(self.si.VCInstallDir, r'Lib\store\references')]13201321@property1322def VCTools(self):1323"""1324Microsoft Visual C++ Tools.13251326Return1327------1328list of str1329paths1330"""1331si = self.si1332tools = [join(si.VCInstallDir, 'VCPackages')]13331334forcex86 = True if self.vs_ver <= 10.0 else False1335arch_subdir = self.pi.cross_dir(forcex86)1336if arch_subdir:1337tools += [join(si.VCInstallDir, 'Bin%s' % arch_subdir)]13381339if self.vs_ver == 14.0:1340path = 'Bin%s' % self.pi.current_dir(hidex86=True)1341tools += [join(si.VCInstallDir, path)]13421343elif self.vs_ver >= 15.0:1344host_dir = (r'bin\HostX86%s' if self.pi.current_is_x86() else1345r'bin\HostX64%s')1346tools += [join(1347si.VCInstallDir, host_dir % self.pi.target_dir(x64=True))]13481349if self.pi.current_cpu != self.pi.target_cpu:1350tools += [join(1351si.VCInstallDir, host_dir % self.pi.current_dir(x64=True))]13521353else:1354tools += [join(si.VCInstallDir, 'Bin')]13551356return tools13571358@property1359def OSLibraries(self):1360"""1361Microsoft Windows SDK Libraries.13621363Return1364------1365list of str1366paths1367"""1368if self.vs_ver <= 10.0:1369arch_subdir = self.pi.target_dir(hidex86=True, x64=True)1370return [join(self.si.WindowsSdkDir, 'Lib%s' % arch_subdir)]13711372else:1373arch_subdir = self.pi.target_dir(x64=True)1374lib = join(self.si.WindowsSdkDir, 'lib')1375libver = self._sdk_subdir1376return [join(lib, '%sum%s' % (libver, arch_subdir))]13771378@property1379def OSIncludes(self):1380"""1381Microsoft Windows SDK Include.13821383Return1384------1385list of str1386paths1387"""1388include = join(self.si.WindowsSdkDir, 'include')13891390if self.vs_ver <= 10.0:1391return [include, join(include, 'gl')]13921393else:1394if self.vs_ver >= 14.0:1395sdkver = self._sdk_subdir1396else:1397sdkver = ''1398return [join(include, '%sshared' % sdkver),1399join(include, '%sum' % sdkver),1400join(include, '%swinrt' % sdkver)]14011402@property1403def OSLibpath(self):1404"""1405Microsoft Windows SDK Libraries Paths.14061407Return1408------1409list of str1410paths1411"""1412ref = join(self.si.WindowsSdkDir, 'References')1413libpath = []14141415if self.vs_ver <= 9.0:1416libpath += self.OSLibraries14171418if self.vs_ver >= 11.0:1419libpath += [join(ref, r'CommonConfiguration\Neutral')]14201421if self.vs_ver >= 14.0:1422libpath += [1423ref,1424join(self.si.WindowsSdkDir, 'UnionMetadata'),1425join(1426ref, 'Windows.Foundation.UniversalApiContract', '1.0.0.0'),1427join(ref, 'Windows.Foundation.FoundationContract', '1.0.0.0'),1428join(1429ref, 'Windows.Networking.Connectivity.WwanContract',1430'1.0.0.0'),1431join(1432self.si.WindowsSdkDir, 'ExtensionSDKs', 'Microsoft.VCLibs',1433'%0.1f' % self.vs_ver, 'References', 'CommonConfiguration',1434'neutral'),1435]1436return libpath14371438@property1439def SdkTools(self):1440"""1441Microsoft Windows SDK Tools.14421443Return1444------1445list of str1446paths1447"""1448return list(self._sdk_tools())14491450def _sdk_tools(self):1451"""1452Microsoft Windows SDK Tools paths generator.14531454Return1455------1456generator of str1457paths1458"""1459if self.vs_ver < 15.0:1460bin_dir = 'Bin' if self.vs_ver <= 11.0 else r'Bin\x86'1461yield join(self.si.WindowsSdkDir, bin_dir)14621463if not self.pi.current_is_x86():1464arch_subdir = self.pi.current_dir(x64=True)1465path = 'Bin%s' % arch_subdir1466yield join(self.si.WindowsSdkDir, path)14671468if self.vs_ver in (10.0, 11.0):1469if self.pi.target_is_x86():1470arch_subdir = ''1471else:1472arch_subdir = self.pi.current_dir(hidex86=True, x64=True)1473path = r'Bin\NETFX 4.0 Tools%s' % arch_subdir1474yield join(self.si.WindowsSdkDir, path)14751476elif self.vs_ver >= 15.0:1477path = join(self.si.WindowsSdkDir, 'Bin')1478arch_subdir = self.pi.current_dir(x64=True)1479sdkver = self.si.WindowsSdkLastVersion1480yield join(path, '%s%s' % (sdkver, arch_subdir))14811482if self.si.WindowsSDKExecutablePath:1483yield self.si.WindowsSDKExecutablePath14841485@property1486def _sdk_subdir(self):1487"""1488Microsoft Windows SDK version subdir.14891490Return1491------1492str1493subdir1494"""1495ucrtver = self.si.WindowsSdkLastVersion1496return ('%s\\' % ucrtver) if ucrtver else ''14971498@property1499def SdkSetup(self):1500"""1501Microsoft Windows SDK Setup.15021503Return1504------1505list of str1506paths1507"""1508if self.vs_ver > 9.0:1509return []15101511return [join(self.si.WindowsSdkDir, 'Setup')]15121513@property1514def FxTools(self):1515"""1516Microsoft .NET Framework Tools.15171518Return1519------1520list of str1521paths1522"""1523pi = self.pi1524si = self.si15251526if self.vs_ver <= 10.0:1527include32 = True1528include64 = not pi.target_is_x86() and not pi.current_is_x86()1529else:1530include32 = pi.target_is_x86() or pi.current_is_x86()1531include64 = pi.current_cpu == 'amd64' or pi.target_cpu == 'amd64'15321533tools = []1534if include32:1535tools += [join(si.FrameworkDir32, ver)1536for ver in si.FrameworkVersion32]1537if include64:1538tools += [join(si.FrameworkDir64, ver)1539for ver in si.FrameworkVersion64]1540return tools15411542@property1543def NetFxSDKLibraries(self):1544"""1545Microsoft .Net Framework SDK Libraries.15461547Return1548------1549list of str1550paths1551"""1552if self.vs_ver < 14.0 or not self.si.NetFxSdkDir:1553return []15541555arch_subdir = self.pi.target_dir(x64=True)1556return [join(self.si.NetFxSdkDir, r'lib\um%s' % arch_subdir)]15571558@property1559def NetFxSDKIncludes(self):1560"""1561Microsoft .Net Framework SDK Includes.15621563Return1564------1565list of str1566paths1567"""1568if self.vs_ver < 14.0 or not self.si.NetFxSdkDir:1569return []15701571return [join(self.si.NetFxSdkDir, r'include\um')]15721573@property1574def VsTDb(self):1575"""1576Microsoft Visual Studio Team System Database.15771578Return1579------1580list of str1581paths1582"""1583return [join(self.si.VSInstallDir, r'VSTSDB\Deploy')]15841585@property1586def MSBuild(self):1587"""1588Microsoft Build Engine.15891590Return1591------1592list of str1593paths1594"""1595if self.vs_ver < 12.0:1596return []1597elif self.vs_ver < 15.0:1598base_path = self.si.ProgramFilesx861599arch_subdir = self.pi.current_dir(hidex86=True)1600else:1601base_path = self.si.VSInstallDir1602arch_subdir = ''16031604path = r'MSBuild\%0.1f\bin%s' % (self.vs_ver, arch_subdir)1605build = [join(base_path, path)]16061607if self.vs_ver >= 15.0:1608# Add Roslyn C# & Visual Basic Compiler1609build += [join(base_path, path, 'Roslyn')]16101611return build16121613@property1614def HTMLHelpWorkshop(self):1615"""1616Microsoft HTML Help Workshop.16171618Return1619------1620list of str1621paths1622"""1623if self.vs_ver < 11.0:1624return []16251626return [join(self.si.ProgramFilesx86, 'HTML Help Workshop')]16271628@property1629def UCRTLibraries(self):1630"""1631Microsoft Universal C Runtime SDK Libraries.16321633Return1634------1635list of str1636paths1637"""1638if self.vs_ver < 14.0:1639return []16401641arch_subdir = self.pi.target_dir(x64=True)1642lib = join(self.si.UniversalCRTSdkDir, 'lib')1643ucrtver = self._ucrt_subdir1644return [join(lib, '%sucrt%s' % (ucrtver, arch_subdir))]16451646@property1647def UCRTIncludes(self):1648"""1649Microsoft Universal C Runtime SDK Include.16501651Return1652------1653list of str1654paths1655"""1656if self.vs_ver < 14.0:1657return []16581659include = join(self.si.UniversalCRTSdkDir, 'include')1660return [join(include, '%sucrt' % self._ucrt_subdir)]16611662@property1663def _ucrt_subdir(self):1664"""1665Microsoft Universal C Runtime SDK version subdir.16661667Return1668------1669str1670subdir1671"""1672ucrtver = self.si.UniversalCRTSdkLastVersion1673return ('%s\\' % ucrtver) if ucrtver else ''16741675@property1676def FSharp(self):1677"""1678Microsoft Visual F#.16791680Return1681------1682list of str1683paths1684"""1685if 11.0 > self.vs_ver > 12.0:1686return []16871688return [self.si.FSharpInstallDir]16891690@property1691def VCRuntimeRedist(self):1692"""1693Microsoft Visual C++ runtime redistributable dll.16941695Return1696------1697str1698path1699"""1700vcruntime = 'vcruntime%d0.dll' % self.vc_ver1701arch_subdir = self.pi.target_dir(x64=True).strip('\\')17021703# Installation prefixes candidates1704prefixes = []1705tools_path = self.si.VCInstallDir1706redist_path = dirname(tools_path.replace(r'\Tools', r'\Redist'))1707if isdir(redist_path):1708# Redist version may not be exactly the same as tools1709redist_path = join(redist_path, listdir(redist_path)[-1])1710prefixes += [redist_path, join(redist_path, 'onecore')]17111712prefixes += [join(tools_path, 'redist')] # VS14 legacy path17131714# CRT directory1715crt_dirs = ('Microsoft.VC%d.CRT' % (self.vc_ver * 10),1716# Sometime store in directory with VS version instead of VC1717'Microsoft.VC%d.CRT' % (int(self.vs_ver) * 10))17181719# vcruntime path1720for prefix, crt_dir in itertools.product(prefixes, crt_dirs):1721path = join(prefix, arch_subdir, crt_dir, vcruntime)1722if isfile(path):1723return path17241725def return_env(self, exists=True):1726"""1727Return environment dict.17281729Parameters1730----------1731exists: bool1732It True, only return existing paths.17331734Return1735------1736dict1737environment1738"""1739env = dict(1740include=self._build_paths('include',1741[self.VCIncludes,1742self.OSIncludes,1743self.UCRTIncludes,1744self.NetFxSDKIncludes],1745exists),1746lib=self._build_paths('lib',1747[self.VCLibraries,1748self.OSLibraries,1749self.FxTools,1750self.UCRTLibraries,1751self.NetFxSDKLibraries],1752exists),1753libpath=self._build_paths('libpath',1754[self.VCLibraries,1755self.FxTools,1756self.VCStoreRefs,1757self.OSLibpath],1758exists),1759path=self._build_paths('path',1760[self.VCTools,1761self.VSTools,1762self.VsTDb,1763self.SdkTools,1764self.SdkSetup,1765self.FxTools,1766self.MSBuild,1767self.HTMLHelpWorkshop,1768self.FSharp],1769exists),1770)1771if self.vs_ver >= 14 and isfile(self.VCRuntimeRedist):1772env['py_vcruntime_redist'] = self.VCRuntimeRedist1773return env17741775def _build_paths(self, name, spec_path_lists, exists):1776"""1777Given an environment variable name and specified paths,1778return a pathsep-separated string of paths containing1779unique, extant, directories from those paths and from1780the environment variable. Raise an error if no paths1781are resolved.17821783Parameters1784----------1785name: str1786Environment variable name1787spec_path_lists: list of str1788Paths1789exists: bool1790It True, only return existing paths.17911792Return1793------1794str1795Pathsep-separated paths1796"""1797# flatten spec_path_lists1798spec_paths = itertools.chain.from_iterable(spec_path_lists)1799env_paths = environ.get(name, '').split(pathsep)1800paths = itertools.chain(spec_paths, env_paths)1801extant_paths = list(filter(isdir, paths)) if exists else paths1802if not extant_paths:1803msg = "%s environment variable is empty" % name.upper()1804raise distutils.errors.DistutilsPlatformError(msg)1805unique_paths = self._unique_everseen(extant_paths)1806return pathsep.join(unique_paths)18071808# from Python docs1809@staticmethod1810def _unique_everseen(iterable, key=None):1811"""1812List unique elements, preserving order.1813Remember all elements ever seen.18141815_unique_everseen('AAAABBBCCDAABBB') --> A B C D18161817_unique_everseen('ABBCcAD', str.lower) --> A B C D1818"""1819seen = set()1820seen_add = seen.add1821if key is None:1822for element in filterfalse(seen.__contains__, iterable):1823seen_add(element)1824yield element1825else:1826for element in iterable:1827k = key(element)1828if k not in seen:1829seen_add(k)1830yield element183118321833