Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: third_party/google-endpoints/setuptools/msvc.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 """
2 Improved support for Microsoft Visual C++ compilers.
3
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)
10
11 Microsoft Visual C++ 10.0:
12 Microsoft Windows SDK 7.1 (x86, x64, ia64)
13
14 Microsoft Visual C++ 14.0:
15 Microsoft Visual C++ Build Tools 2015 (x86, x64, arm)
16 """
17
18 import os
19 import sys
20 import platform
21 import itertools
22 import distutils.errors
23 from packaging.version import LegacyVersion
24
25 from six.moves import filterfalse
26
27 from .monkey import get_unpatched
28
29 if platform.system() == 'Windows':
30 from six.moves import winreg
31 safe_env = os.environ
32 else:
33 """
34 Mock winreg and environ so the module can be imported
35 on this platform.
36 """
37
38 class winreg:
39 HKEY_USERS = None
40 HKEY_CURRENT_USER = None
41 HKEY_LOCAL_MACHINE = None
42 HKEY_CLASSES_ROOT = None
43
44 safe_env = dict()
45
46 try:
47 from distutils.msvc9compiler import Reg
48 except ImportError:
49 pass
50
51
52 def msvc9_find_vcvarsall(version):
53 """
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.
57
58 Redirect the path of "vcvarsall.bat".
59
60 Known supported compilers
61 -------------------------
62 Microsoft Visual C++ 9.0:
63 Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64)
64
65 Parameters
66 ----------
67 version: float
68 Required Microsoft Visual C++ version.
69
70 Return
71 ------
72 vcvarsall.bat path: str
73 """
74 VC_BASE = r'Software\%sMicrosoft\DevDiv\VCForPython\%0.1f'
75 key = VC_BASE % ('', version)
76 try:
77 # Per-user installs register the compiler path here
78 productdir = Reg.get_value(key, "installdir")
79 except KeyError:
80 try:
81 # All-user installs on a 64-bit system register here
82 key = VC_BASE % ('Wow6432Node\\', version)
83 productdir = Reg.get_value(key, "installdir")
84 except KeyError:
85 productdir = None
86
87 if productdir:
88 vcvarsall = os.path.os.path.join(productdir, "vcvarsall.bat")
89 if os.path.isfile(vcvarsall):
90 return vcvarsall
91
92 return get_unpatched(msvc9_find_vcvarsall)(version)
93
94
95 def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs):
96 """
97 Patched "distutils.msvc9compiler.query_vcvarsall" for support standalones
98 compilers.
99
100 Set environment without use of "vcvarsall.bat".
101
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)
108
109 Microsoft Visual C++ 10.0:
110 Microsoft Windows SDK 7.1 (x86, x64, ia64)
111
112 Parameters
113 ----------
114 ver: float
115 Required Microsoft Visual C++ version.
116 arch: str
117 Target architecture.
118
119 Return
120 ------
121 environment: dict
122 """
123 # Try to get environement from vcvarsall.bat (Classical way)
124 try:
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
129 pass
130 except ValueError:
131 # Pass error if environment not set after executing vcvarsall.bat
132 pass
133
134 # If error, try to set environment directly
135 try:
136 return EnvironmentInfo(arch, ver).return_env()
137 except distutils.errors.DistutilsPlatformError as exc:
138 _augment_exception(exc, ver, arch)
139 raise
140
141
142 def msvc14_get_vc_env(plat_spec):
143 """
144 Patched "distutils._msvccompiler._get_vc_env" for support standalones
145 compilers.
146
147 Set environment without use of "vcvarsall.bat".
148
149 Known supported compilers
150 -------------------------
151 Microsoft Visual C++ 14.0:
152 Microsoft Visual C++ Build Tools 2015 (x86, x64, arm)
153
154 Parameters
155 ----------
156 plat_spec: str
157 Target architecture.
158
159 Return
160 ------
161 environment: dict
162 """
163 # Try to get environment from vcvarsall.bat (Classical way)
164 try:
165 return get_unpatched(msvc14_get_vc_env)(plat_spec)
166 except distutils.errors.DistutilsPlatformError:
167 # Pass error Vcvarsall.bat is missing
168 pass
169
170 # If error, try to set environment directly
171 try:
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)
175 raise
176
177
178 def msvc14_gen_lib_options(*args, **kwargs):
179 """
180 Patched "distutils._msvccompiler.gen_lib_options" for fix
181 compatibility between "numpy.distutils" and "distutils._msvccompiler"
182 (for Numpy < 1.11.2)
183 """
184 if "numpy.distutils" in sys.modules:
185 import numpy as np
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)
189
190
191 def _augment_exception(exc, version, arch=''):
192 """
193 Add details to the exception message to help guide the user
194 as to what action will resolve it.
195 """
196 # Error if MSVC++ directory not found or environment not set
197 message = exc.args[0]
198
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'
204 if version == 9.0:
205 if arch.lower().find('ia64') > -1:
206 # For VC++ 9.0, if IA64 support is needed, redirect user
207 # to Windows SDK 7.0
208 message += ' Get it with "Microsoft Windows SDK 7.0": '
209 message += msdownload % 3138
210 else:
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')
224
225 exc.args = (message, )
226
227
228 class PlatformInfo:
229 """
230 Current and Target Architectures informations.
231
232 Parameters
233 ----------
234 arch: str
235 Target architecture.
236 """
237 current_cpu = safe_env.get('processor_architecture', '').lower()
238
239 def __init__(self, arch):
240 self.arch = arch.lower().replace('x64', 'amd64')
241
242 @property
243 def target_cpu(self):
244 return self.arch[self.arch.find('_') + 1:]
245
246 def target_is_x86(self):
247 return self.target_cpu == 'x86'
248
249 def current_is_x86(self):
250 return self.current_cpu == 'x86'
251
252 def current_dir(self, hidex86=False, x64=False):
253 """
254 Current platform specific subfolder.
255
256 Parameters
257 ----------
258 hidex86: bool
259 return '' and not '\x86' if architecture is x86.
260 x64: bool
261 return '\x64' and not '\amd64' if architecture is amd64.
262
263 Return
264 ------
265 subfolder: str
266 '\target', or '' (see hidex86 parameter)
267 """
268 return (
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
272 )
273
274 def target_dir(self, hidex86=False, x64=False):
275 """
276 Target platform specific subfolder.
277
278 Parameters
279 ----------
280 hidex86: bool
281 return '' and not '\x86' if architecture is x86.
282 x64: bool
283 return '\x64' and not '\amd64' if architecture is amd64.
284
285 Return
286 ------
287 subfolder: str
288 '\current', or '' (see hidex86 parameter)
289 """
290 return (
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
294 )
295
296 def cross_dir(self, forcex86=False):
297 """
298 Cross platform specific subfolder.
299
300 Parameters
301 ----------
302 forcex86: bool
303 Use 'x86' as current architecture even if current acritecture is
304 not x86.
305
306 Return
307 ------
308 subfolder: str
309 '' if target architecture is current architecture,
310 '\current_target' if not.
311 """
312 current = 'x86' if forcex86 else self.current_cpu
313 return (
314 '' if self.target_cpu == current else
315 self.target_dir().replace('\\', '\\%s_' % current)
316 )
317
318
319 class RegistryInfo:
320 """
321 Microsoft Visual Studio related registry informations.
322
323 Parameters
324 ----------
325 platform_info: PlatformInfo
326 "PlatformInfo" instance.
327 """
328 HKEYS = (winreg.HKEY_USERS,
329 winreg.HKEY_CURRENT_USER,
330 winreg.HKEY_LOCAL_MACHINE,
331 winreg.HKEY_CLASSES_ROOT)
332
333 def __init__(self, platform_info):
334 self.pi = platform_info
335
336 @property
337 def visualstudio(self):
338 """
339 Microsoft Visual Studio root registry key.
340 """
341 return 'VisualStudio'
342
343 @property
344 def sxs(self):
345 """
346 Microsoft Visual Studio SxS registry key.
347 """
348 return os.path.join(self.visualstudio, 'SxS')
349
350 @property
351 def vc(self):
352 """
353 Microsoft Visual C++ VC7 registry key.
354 """
355 return os.path.join(self.sxs, 'VC7')
356
357 @property
358 def vs(self):
359 """
360 Microsoft Visual Studio VS7 registry key.
361 """
362 return os.path.join(self.sxs, 'VS7')
363
364 @property
365 def vc_for_python(self):
366 """
367 Microsoft Visual C++ for Python registry key.
368 """
369 return r'DevDiv\VCForPython'
370
371 @property
372 def microsoft_sdk(self):
373 """
374 Microsoft SDK registry key.
375 """
376 return 'Microsoft SDKs'
377
378 @property
379 def windows_sdk(self):
380 """
381 Microsoft Windows/Platform SDK registry key.
382 """
383 return os.path.join(self.microsoft_sdk, 'Windows')
384
385 @property
386 def netfx_sdk(self):
387 """
388 Microsoft .NET Framework SDK registry key.
389 """
390 return os.path.join(self.microsoft_sdk, 'NETFXSDK')
391
392 @property
393 def windows_kits_roots(self):
394 """
395 Microsoft Windows Kits Roots registry key.
396 """
397 return r'Windows Kits\Installed Roots'
398
399 def microsoft(self, key, x86=False):
400 """
401 Return key in Microsoft software registry.
402
403 Parameters
404 ----------
405 key: str
406 Registry key path where look.
407 x86: str
408 Force x86 software registry.
409
410 Return
411 ------
412 str: value
413 """
414 node64 = '' if self.pi.current_is_x86() or x86 else r'\Wow6432Node'
415 return os.path.join('Software', node64, 'Microsoft', key)
416
417 def lookup(self, key, name):
418 """
419 Look for values in registry in Microsoft software registry.
420
421 Parameters
422 ----------
423 key: str
424 Registry key path where look.
425 name: str
426 Value name to find.
427
428 Return
429 ------
430 str: value
431 """
432 KEY_READ = winreg.KEY_READ
433 openkey = winreg.OpenKey
434 ms = self.microsoft
435 for hkey in self.HKEYS:
436 try:
437 bkey = openkey(hkey, ms(key), 0, KEY_READ)
438 except (OSError, IOError):
439 if not self.pi.current_is_x86():
440 try:
441 bkey = openkey(hkey, ms(key, True), 0, KEY_READ)
442 except (OSError, IOError):
443 continue
444 else:
445 continue
446 try:
447 return winreg.QueryValueEx(bkey, name)[0]
448 except (OSError, IOError):
449 pass
450
451
452 class SystemInfo:
453 """
454 Microsoft Windows and Visual Studio related system inormations.
455
456 Parameters
457 ----------
458 registry_info: RegistryInfo
459 "RegistryInfo" instance.
460 vc_ver: float
461 Required Microsoft Visual C++ version.
462 """
463
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)
469
470 def __init__(self, registry_info, vc_ver=None):
471 self.ri = registry_info
472 self.pi = self.ri.pi
473 if vc_ver:
474 self.vc_ver = vc_ver
475 else:
476 try:
477 self.vc_ver = self.find_available_vc_vers()[-1]
478 except IndexError:
479 err = 'No Microsoft Visual C++ version found'
480 raise distutils.errors.DistutilsPlatformError(err)
481
482 def find_available_vc_vers(self):
483 """
484 Find all available Microsoft Visual C++ versions.
485 """
486 vckeys = (self.ri.vc, self.ri.vc_for_python)
487 vc_vers = []
488 for hkey in self.ri.HKEYS:
489 for key in vckeys:
490 try:
491 bkey = winreg.OpenKey(hkey, key, 0, winreg.KEY_READ)
492 except (OSError, IOError):
493 continue
494 subkeys, values, _ = winreg.QueryInfoKey(bkey)
495 for i in range(values):
496 try:
497 ver = float(winreg.EnumValue(bkey, i)[0])
498 if ver not in vc_vers:
499 vc_vers.append(ver)
500 except ValueError:
501 pass
502 for i in range(subkeys):
503 try:
504 ver = float(winreg.EnumKey(bkey, i))
505 if ver not in vc_vers:
506 vc_vers.append(ver)
507 except ValueError:
508 pass
509 return sorted(vc_vers)
510
511 @property
512 def VSInstallDir(self):
513 """
514 Microsoft Visual Studio directory.
515 """
516 # Default path
517 name = 'Microsoft Visual Studio %0.1f' % self.vc_ver
518 default = os.path.join(self.ProgramFilesx86, name)
519
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
522
523 @property
524 def VCInstallDir(self):
525 """
526 Microsoft Visual C++ directory.
527 """
528 # Default path
529 default = r'Microsoft Visual Studio %0.1f\VC' % self.vc_ver
530 guess_vc = os.path.join(self.ProgramFilesx86, default)
531
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
536
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
539
540 if not os.path.isdir(path):
541 msg = 'Microsoft Visual C++ directory not found'
542 raise distutils.errors.DistutilsPlatformError(msg)
543
544 return path
545
546 @property
547 def WindowsSdkVersion(self):
548 """
549 Microsoft Windows SDK versions.
550 """
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')
562
563 @property
564 def WindowsSdkDir(self):
565 """
566 Microsoft Windows SDK directory.
567 """
568 sdkdir = ''
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')
573 if sdkdir:
574 break
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')
579 if install_base:
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)
587 if os.path.isdir(d):
588 sdkdir = d
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)
594 if os.path.isdir(d):
595 sdkdir = d
596 if not sdkdir:
597 # If fail, use Platform SDK
598 sdkdir = os.path.join(self.VCInstallDir, 'PlatformSDK')
599 return sdkdir
600
601 @property
602 def WindowsSDKExecutablePath(self):
603 """
604 Microsoft Windows SDK executable directory.
605 """
606 # Find WinSDK NetFx Tools registry dir name
607 if self.vc_ver <= 11.0:
608 netfxver = 35
609 arch = ''
610 else:
611 netfxver = 40
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('\\', '-'))
615
616 # liste all possibles registry paths
617 regpaths = []
618 if self.vc_ver >= 14.0:
619 for ver in self.NetFxSdkVersion:
620 regpaths += [os.path.join(self.ri.netfx_sdk, ver, fx)]
621
622 for ver in self.WindowsSdkVersion:
623 regpaths += [os.path.join(self.ri.windows_sdk, 'v%sA' % ver, fx)]
624
625 # Return installation folder from the more recent path
626 for path in regpaths:
627 execpath = self.ri.lookup(path, 'installationfolder')
628 if execpath:
629 break
630 return execpath
631
632 @property
633 def FSharpInstallDir(self):
634 """
635 Microsoft Visual F# directory.
636 """
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 ''
640
641 @property
642 def UniversalCRTSdkDir(self):
643 """
644 Microsoft Universal CRT SDK directory.
645 """
646 # Set Kit Roots versions for specified MSVC++ version
647 if self.vc_ver >= 14.0:
648 vers = ('10', '81')
649 else:
650 vers = ()
651
652 # Find path of the more recent Kit
653 for ver in vers:
654 sdkdir = self.ri.lookup(self.ri.windows_kits_roots,
655 'kitsroot%s' % ver)
656 if sdkdir:
657 break
658 return sdkdir or ''
659
660 @property
661 def NetFxSdkVersion(self):
662 """
663 Microsoft .NET Framework SDK versions.
664 """
665 # Set FxSdk versions for specified MSVC++ version
666 if self.vc_ver >= 14.0:
667 return ('4.6.1', '4.6')
668 else:
669 return ()
670
671 @property
672 def NetFxSdkDir(self):
673 """
674 Microsoft .NET Framework SDK directory.
675 """
676 for ver in self.NetFxSdkVersion:
677 loc = os.path.join(self.ri.netfx_sdk, ver)
678 sdkdir = self.ri.lookup(loc, 'kitsinstallationfolder')
679 if sdkdir:
680 break
681 return sdkdir or ''
682
683 @property
684 def FrameworkDir32(self):
685 """
686 Microsoft .NET Framework 32bit directory.
687 """
688 # Default path
689 guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework')
690
691 # Try to get path from registry, if fail use default path
692 return self.ri.lookup(self.ri.vc, 'frameworkdir32') or guess_fw
693
694 @property
695 def FrameworkDir64(self):
696 """
697 Microsoft .NET Framework 64bit directory.
698 """
699 # Default path
700 guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework64')
701
702 # Try to get path from registry, if fail use default path
703 return self.ri.lookup(self.ri.vc, 'frameworkdir64') or guess_fw
704
705 @property
706 def FrameworkVersion32(self):
707 """
708 Microsoft .NET Framework 32bit versions.
709 """
710 return self._find_dot_net_versions(32)
711
712 @property
713 def FrameworkVersion64(self):
714 """
715 Microsoft .NET Framework 64bit versions.
716 """
717 return self._find_dot_net_versions(64)
718
719 def _find_dot_net_versions(self, bits=32):
720 """
721 Find Microsoft .NET Framework versions.
722
723 Parameters
724 ----------
725 bits: int
726 Platform number of bits: 32 or 64.
727 """
728 # Find actual .NET version
729 ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits) or ''
730
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,
736 'v3.5')
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')
741 return frameworkver
742
743
744 class EnvironmentInfo:
745 """
746 Return environment variables for specified Microsoft Visual C++ version
747 and platform : Lib, Include, Path and libpath.
748
749 This function is compatible with Microsoft Visual C++ 9.0 to 14.0.
750
751 Script created by analysing Microsoft environment configuration files like
752 "vcvars[...].bat", "SetEnv.Cmd", "vcbuildtools.bat", ...
753
754 Parameters
755 ----------
756 arch: str
757 Target architecture.
758 vc_ver: float
759 Required Microsoft Visual C++ version. If not set, autodetect the last
760 version.
761 vc_min_ver: float
762 Minimum Microsoft Visual C++ version.
763 """
764
765 # Variables and properties in this class use originals CamelCase variables
766 # names from Microsoft source files for more easy comparaison.
767
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)
772
773 if vc_min_ver:
774 if self.vc_ver < vc_min_ver:
775 err = 'No suitable Microsoft Visual C++ version found'
776 raise distutils.errors.DistutilsPlatformError(err)
777
778 @property
779 def vc_ver(self):
780 """
781 Microsoft Visual C++ version.
782 """
783 return self.si.vc_ver
784
785 @property
786 def VSTools(self):
787 """
788 Microsoft Visual Studio Tools
789 """
790 paths = [r'Common7\IDE', r'Common7\Tools']
791
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]
797
798 return [os.path.join(self.si.VSInstallDir, path) for path in paths]
799
800 @property
801 def VCIncludes(self):
802 """
803 Microsoft Visual C++ & Microsoft Foundation Class Includes
804 """
805 return [os.path.join(self.si.VCInstallDir, 'Include'),
806 os.path.join(self.si.VCInstallDir, r'ATLMFC\Include')]
807
808 @property
809 def VCLibraries(self):
810 """
811 Microsoft Visual C++ & Microsoft Foundation Class Libraries
812 """
813 arch_subdir = self.pi.target_dir(hidex86=True)
814 paths = ['Lib%s' % arch_subdir, r'ATLMFC\Lib%s' % arch_subdir]
815
816 if self.vc_ver >= 14.0:
817 paths += [r'Lib\store%s' % arch_subdir]
818
819 return [os.path.join(self.si.VCInstallDir, path) for path in paths]
820
821 @property
822 def VCStoreRefs(self):
823 """
824 Microsoft Visual C++ store references Libraries
825 """
826 if self.vc_ver < 14.0:
827 return []
828 return [os.path.join(self.si.VCInstallDir, r'Lib\store\references')]
829
830 @property
831 def VCTools(self):
832 """
833 Microsoft Visual C++ Tools
834 """
835 si = self.si
836 tools = [os.path.join(si.VCInstallDir, 'VCPackages')]
837
838 forcex86 = True if self.vc_ver <= 10.0 else False
839 arch_subdir = self.pi.cross_dir(forcex86)
840 if arch_subdir:
841 tools += [os.path.join(si.VCInstallDir, 'Bin%s' % arch_subdir)]
842
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)]
846
847 else:
848 tools += [os.path.join(si.VCInstallDir, 'Bin')]
849
850 return tools
851
852 @property
853 def OSLibraries(self):
854 """
855 Microsoft Windows SDK Libraries
856 """
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)]
860
861 else:
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))]
866
867 @property
868 def OSIncludes(self):
869 """
870 Microsoft Windows SDK Include
871 """
872 include = os.path.join(self.si.WindowsSdkDir, 'include')
873
874 if self.vc_ver <= 10.0:
875 return [include, os.path.join(include, 'gl')]
876
877 else:
878 if self.vc_ver >= 14.0:
879 sdkver = self._get_content_dirname(include)
880 else:
881 sdkver = ''
882 return [os.path.join(include, '%sshared' % sdkver),
883 os.path.join(include, '%sum' % sdkver),
884 os.path.join(include, '%swinrt' % sdkver)]
885
886 @property
887 def OSLibpath(self):
888 """
889 Microsoft Windows SDK Libraries Paths
890 """
891 ref = os.path.join(self.si.WindowsSdkDir, 'References')
892 libpath = []
893
894 if self.vc_ver <= 9.0:
895 libpath += self.OSLibraries
896
897 if self.vc_ver >= 11.0:
898 libpath += [os.path.join(ref, r'CommonConfiguration\Neutral')]
899
900 if self.vc_ver >= 14.0:
901 libpath += [
902 ref,
903 os.path.join(self.si.WindowsSdkDir, 'UnionMetadata'),
904 os.path.join(
905 ref,
906 'Windows.Foundation.UniversalApiContract',
907 '1.0.0.0',
908 ),
909 os.path.join(
910 ref,
911 'Windows.Foundation.FoundationContract',
912 '1.0.0.0',
913 ),
914 os.path.join(
915 ref,
916 'Windows.Networking.Connectivity.WwanContract',
917 '1.0.0.0',
918 ),
919 os.path.join(
920 self.si.WindowsSdkDir,
921 'ExtensionSDKs',
922 'Microsoft.VCLibs',
923 '%0.1f' % self.vc_ver,
924 'References',
925 'CommonConfiguration',
926 'neutral',
927 ),
928 ]
929 return libpath
930
931 @property
932 def SdkTools(self):
933 """
934 Microsoft Windows SDK Tools
935 """
936 bin_dir = 'Bin' if self.vc_ver <= 11.0 else r'Bin\x86'
937 tools = [os.path.join(self.si.WindowsSdkDir, bin_dir)]
938
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)]
943
944 if self.vc_ver == 10.0 or self.vc_ver == 11.0:
945 if self.pi.target_is_x86():
946 arch_subdir = ''
947 else:
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)]
951
952 if self.si.WindowsSDKExecutablePath:
953 tools += [self.si.WindowsSDKExecutablePath]
954
955 return tools
956
957 @property
958 def SdkSetup(self):
959 """
960 Microsoft Windows SDK Setup
961 """
962 if self.vc_ver > 9.0:
963 return []
964
965 return [os.path.join(self.si.WindowsSdkDir, 'Setup')]
966
967 @property
968 def FxTools(self):
969 """
970 Microsoft .NET Framework Tools
971 """
972 pi = self.pi
973 si = self.si
974
975 if self.vc_ver <= 10.0:
976 include32 = True
977 include64 = not pi.target_is_x86() and not pi.current_is_x86()
978 else:
979 include32 = pi.target_is_x86() or pi.current_is_x86()
980 include64 = pi.current_cpu == 'amd64' or pi.target_cpu == 'amd64'
981
982 tools = []
983 if include32:
984 tools += [os.path.join(si.FrameworkDir32, ver)
985 for ver in si.FrameworkVersion32]
986 if include64:
987 tools += [os.path.join(si.FrameworkDir64, ver)
988 for ver in si.FrameworkVersion64]
989 return tools
990
991 @property
992 def NetFxSDKLibraries(self):
993 """
994 Microsoft .Net Framework SDK Libraries
995 """
996 if self.vc_ver < 14.0 or not self.si.NetFxSdkDir:
997 return []
998
999 arch_subdir = self.pi.target_dir(x64=True)
1000 return [os.path.join(self.si.NetFxSdkDir, r'lib\um%s' % arch_subdir)]
1001
1002 @property
1003 def NetFxSDKIncludes(self):
1004 """
1005 Microsoft .Net Framework SDK Includes
1006 """
1007 if self.vc_ver < 14.0 or not self.si.NetFxSdkDir:
1008 return []
1009
1010 return [os.path.join(self.si.NetFxSdkDir, r'include\um')]
1011
1012 @property
1013 def VsTDb(self):
1014 """
1015 Microsoft Visual Studio Team System Database
1016 """
1017 return [os.path.join(self.si.VSInstallDir, r'VSTSDB\Deploy')]
1018
1019 @property
1020 def MSBuild(self):
1021 """
1022 Microsoft Build Engine
1023 """
1024 if self.vc_ver < 12.0:
1025 return []
1026
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)]
1030
1031 @property
1032 def HTMLHelpWorkshop(self):
1033 """
1034 Microsoft HTML Help Workshop
1035 """
1036 if self.vc_ver < 11.0:
1037 return []
1038
1039 return [os.path.join(self.si.ProgramFilesx86, 'HTML Help Workshop')]
1040
1041 @property
1042 def UCRTLibraries(self):
1043 """
1044 Microsoft Universal CRT Libraries
1045 """
1046 if self.vc_ver < 14.0:
1047 return []
1048
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))]
1053
1054 @property
1055 def UCRTIncludes(self):
1056 """
1057 Microsoft Universal CRT Include
1058 """
1059 if self.vc_ver < 14.0:
1060 return []
1061
1062 include = os.path.join(self.si.UniversalCRTSdkDir, 'include')
1063 ucrtver = self._get_content_dirname(include)
1064 return [os.path.join(include, '%sucrt' % ucrtver)]
1065
1066 @property
1067 def FSharp(self):
1068 """
1069 Microsoft Visual F#
1070 """
1071 if self.vc_ver < 11.0 and self.vc_ver > 12.0:
1072 return []
1073
1074 return self.si.FSharpInstallDir
1075
1076 @property
1077 def VCRuntimeRedist(self):
1078 """
1079 Microsoft Visual C++ runtime redistribuable dll
1080 """
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)
1085
1086 def return_env(self, exists=True):
1087 """
1088 Return environment dict.
1089
1090 Parameters
1091 ----------
1092 exists: bool
1093 It True, only return existing paths.
1094 """
1095 env = dict(
1096 include=self._build_paths('include',
1097 [self.VCIncludes,
1098 self.OSIncludes,
1099 self.UCRTIncludes,
1100 self.NetFxSDKIncludes],
1101 exists),
1102 lib=self._build_paths('lib',
1103 [self.VCLibraries,
1104 self.OSLibraries,
1105 self.FxTools,
1106 self.UCRTLibraries,
1107 self.NetFxSDKLibraries],
1108 exists),
1109 libpath=self._build_paths('libpath',
1110 [self.VCLibraries,
1111 self.FxTools,
1112 self.VCStoreRefs,
1113 self.OSLibpath],
1114 exists),
1115 path=self._build_paths('path',
1116 [self.VCTools,
1117 self.VSTools,
1118 self.VsTDb,
1119 self.SdkTools,
1120 self.SdkSetup,
1121 self.FxTools,
1122 self.MSBuild,
1123 self.HTMLHelpWorkshop,
1124 self.FSharp],
1125 exists),
1126 )
1127 if self.vc_ver >= 14 and os.path.isfile(self.VCRuntimeRedist):
1128 env['py_vcruntime_redist'] = self.VCRuntimeRedist
1129 return env
1130
1131 def _build_paths(self, name, spec_path_lists, exists):
1132 """
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
1137 are resolved.
1138 """
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)
1149
1150 # from Python docs
1151 def _unique_everseen(self, iterable, key=None):
1152 """
1153 List unique elements, preserving order.
1154 Remember all elements ever seen.
1155
1156 _unique_everseen('AAAABBBCCDAABBB') --> A B C D
1157
1158 _unique_everseen('ABBCcAD', str.lower) --> A B C D
1159 """
1160 seen = set()
1161 seen_add = seen.add
1162 if key is None:
1163 for element in filterfalse(seen.__contains__, iterable):
1164 seen_add(element)
1165 yield element
1166 else:
1167 for element in iterable:
1168 k = key(element)
1169 if k not in seen:
1170 seen_add(k)
1171 yield element
1172
1173 def _get_content_dirname(self, path):
1174 """
1175 Return name of the first dir in path or '' if no dir found.
1176
1177 Parameters
1178 ----------
1179 path: str
1180 Path where search dir.
1181
1182 Return
1183 ------
1184 foldername: str
1185 "name\" or ""
1186 """
1187 try:
1188 name = os.listdir(path)
1189 if name:
1190 return '%s\\' % name[0]
1191 return ''
1192 except (OSError, IOError):
1193 return ''
OLDNEW
« no previous file with comments | « third_party/google-endpoints/setuptools/monkey.py ('k') | third_party/google-endpoints/setuptools/namespaces.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698