Changeset 391 for python/trunk/Lib/distutils/msvc9compiler.py
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Lib/distutils/msvc9compiler.py
r2 r391 13 13 # ported to VS2005 and VS 2008 by Christian Heimes 14 14 15 __revision__ = "$Id : msvc9compiler.py 76652 2009-12-03 20:56:15Z martin.v.loewis$"15 __revision__ = "$Id$" 16 16 17 17 import os … … 19 19 import sys 20 20 import re 21 21 22 from distutils.errors import (DistutilsExecError, DistutilsPlatformError, 22 CompileError, LibError, LinkError) 23 from distutils.ccompiler import (CCompiler, gen_preprocess_options, 24 gen_lib_options) 23 CompileError, LibError, LinkError) 24 from distutils.ccompiler import CCompiler, gen_lib_options 25 25 from distutils import log 26 26 from distutils.util import get_platform … … 38 38 _winreg.HKEY_CLASSES_ROOT) 39 39 40 VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f" 41 WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows" 42 NET_BASE = r"Software\Microsoft\.NETFramework" 40 NATIVE_WIN64 = (sys.platform == 'win32' and sys.maxsize > 2**32) 41 if NATIVE_WIN64: 42 # Visual C++ is a 32-bit application, so we need to look in 43 # the corresponding registry branch, if we're running a 44 # 64-bit Python on Win64 45 VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f" 46 VSEXPRESS_BASE = r"Software\Wow6432Node\Microsoft\VCExpress\%0.1f" 47 WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows" 48 NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework" 49 else: 50 VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f" 51 VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f" 52 WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows" 53 NET_BASE = r"Software\Microsoft\.NETFramework" 43 54 44 55 # A map keyed by get_platform() return values to values accepted by … … 55 66 """ 56 67 57 @classmethod58 68 def get_value(cls, path, key): 59 69 for base in HKEYS: … … 62 72 return d[key] 63 73 raise KeyError(key) 64 65 @classmethod 74 get_value = classmethod(get_value) 75 66 76 def read_keys(cls, base, key): 67 77 """Return list of registry keys.""" … … 80 90 i += 1 81 91 return L 82 83 @classmethod 92 read_keys = classmethod(read_keys) 93 84 94 def read_values(cls, base, key): 85 95 """Return dict of registry keys and values. … … 102 112 i += 1 103 113 return d 104 105 @staticmethod 114 read_values = classmethod(read_values) 115 106 116 def convert_mbcs(s): 107 117 dec = getattr(s, "decode", None) … … 112 122 pass 113 123 return s 124 convert_mbcs = staticmethod(convert_mbcs) 114 125 115 126 class MacroExpander: … … 133 144 else: 134 145 raise KeyError("sdkinstallrootv2.0") 135 except KeyError as exc: #146 except KeyError: 136 147 raise DistutilsPlatformError( 137 148 """Python was built with Visual Studio 2008; … … 217 228 "productdir") 218 229 except KeyError: 219 log.debug("Unable to find productdir in registry")220 230 productdir = None 231 232 # trying Express edition 233 if productdir is None: 234 vsbase = VSEXPRESS_BASE % version 235 try: 236 productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, 237 "productdir") 238 except KeyError: 239 productdir = None 240 log.debug("Unable to find productdir in registry") 221 241 222 242 if not productdir or not os.path.isdir(productdir): … … 254 274 stdout=subprocess.PIPE, 255 275 stderr=subprocess.PIPE) 256 257 stdout, stderr = popen.communicate() 258 if popen.wait() != 0: 259 raise DistutilsPlatformError(stderr.decode("mbcs")) 260 261 stdout = stdout.decode("mbcs") 262 for line in stdout.split("\n"): 263 line = Reg.convert_mbcs(line) 264 if '=' not in line: 265 continue 266 line = line.strip() 267 key, value = line.split('=', 1) 268 key = key.lower() 269 if key in interesting: 270 if value.endswith(os.pathsep): 271 value = value[:-1] 272 result[key] = removeDuplicates(value) 276 try: 277 stdout, stderr = popen.communicate() 278 if popen.wait() != 0: 279 raise DistutilsPlatformError(stderr.decode("mbcs")) 280 281 stdout = stdout.decode("mbcs") 282 for line in stdout.split("\n"): 283 line = Reg.convert_mbcs(line) 284 if '=' not in line: 285 continue 286 line = line.strip() 287 key, value = line.split('=', 1) 288 key = key.lower() 289 if key in interesting: 290 if value.endswith(os.pathsep): 291 value = value[:-1] 292 result[key] = removeDuplicates(value) 293 294 finally: 295 popen.stdout.close() 296 popen.stderr.close() 273 297 274 298 if len(result) != len(interesting): … … 481 505 self.spawn([self.rc] + pp_opts + 482 506 [output_opt] + [input_opt]) 483 except DistutilsExecError asmsg:507 except DistutilsExecError, msg: 484 508 raise CompileError(msg) 485 509 continue … … 508 532 ["/fo" + obj] + [rc_file]) 509 533 510 except DistutilsExecError asmsg:534 except DistutilsExecError, msg: 511 535 raise CompileError(msg) 512 536 continue … … 521 545 [input_opt, output_opt] + 522 546 extra_postargs) 523 except DistutilsExecError asmsg:547 except DistutilsExecError, msg: 524 548 raise CompileError(msg) 525 549 … … 546 570 try: 547 571 self.spawn([self.lib] + lib_args) 548 except DistutilsExecError asmsg:572 except DistutilsExecError, msg: 549 573 raise LibError(msg) 550 574 else: … … 617 641 ld_args.append ('/IMPLIB:' + implib_file) 618 642 619 # Embedded manifests are recommended - see MSDN article titled 620 # "How to: Embed a Manifest Inside a C/C++ Application" 621 # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) 622 # Ask the linker to generate the manifest in the temp dir, so 623 # we can embed it later. 624 temp_manifest = os.path.join( 625 build_temp, 626 os.path.basename(output_filename) + ".manifest") 627 ld_args.append('/MANIFESTFILE:' + temp_manifest) 643 self.manifest_setup_ldargs(output_filename, build_temp, ld_args) 628 644 629 645 if extra_preargs: … … 635 651 try: 636 652 self.spawn([self.linker] + ld_args) 637 except DistutilsExecError asmsg:653 except DistutilsExecError, msg: 638 654 raise LinkError(msg) 639 655 … … 643 659 # manifest. Maybe we should link to a temp file? OTOH, that 644 660 # implies a build environment error that shouldn't go undetected. 645 if target_desc == CCompiler.EXECUTABLE:646 mfid = 1647 else:648 mfid = 2661 mfinfo = self.manifest_get_embed_info(target_desc, ld_args) 662 if mfinfo is not None: 663 mffilename, mfid = mfinfo 664 out_arg = '-outputresource:%s;%s' % (output_filename, mfid) 649 665 try: 650 # Remove references to the Visual C runtime, so they will 651 # fall through to the Visual C dependency of Python.exe. 652 # This way, when installed for a restricted user (e.g. 653 # runtimes are not in WinSxS folder, but in Python's own 654 # folder), the runtimes do not need to be in every folder 655 # with .pyd's. 656 manifest_f = open(temp_manifest, "rb") 657 manifest_buf = manifest_f.read() 658 manifest_f.close() 659 pattern = re.compile( 660 r"""<assemblyIdentity.*?name=("|')Microsoft\."""\ 661 r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""", 662 re.DOTALL) 663 manifest_buf = re.sub(pattern, "", manifest_buf) 664 pattern = "<dependentAssembly>\s*</dependentAssembly>" 665 manifest_buf = re.sub(pattern, "", manifest_buf) 666 manifest_f = open(temp_manifest, "wb") 667 manifest_f.write(manifest_buf) 668 manifest_f.close() 669 except IOError: 670 pass 671 out_arg = '-outputresource:%s;%s' % (output_filename, mfid) 666 self.spawn(['mt.exe', '-nologo', '-manifest', 667 mffilename, out_arg]) 668 except DistutilsExecError, msg: 669 raise LinkError(msg) 670 else: 671 log.debug("skipping %s (up-to-date)", output_filename) 672 673 def manifest_setup_ldargs(self, output_filename, build_temp, ld_args): 674 # If we need a manifest at all, an embedded manifest is recommended. 675 # See MSDN article titled 676 # "How to: Embed a Manifest Inside a C/C++ Application" 677 # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) 678 # Ask the linker to generate the manifest in the temp dir, so 679 # we can check it, and possibly embed it, later. 680 temp_manifest = os.path.join( 681 build_temp, 682 os.path.basename(output_filename) + ".manifest") 683 ld_args.append('/MANIFESTFILE:' + temp_manifest) 684 685 def manifest_get_embed_info(self, target_desc, ld_args): 686 # If a manifest should be embedded, return a tuple of 687 # (manifest_filename, resource_id). Returns None if no manifest 688 # should be embedded. See http://bugs.python.org/issue7833 for why 689 # we want to avoid any manifest for extension modules if we can) 690 for arg in ld_args: 691 if arg.startswith("/MANIFESTFILE:"): 692 temp_manifest = arg.split(":", 1)[1] 693 break 694 else: 695 # no /MANIFESTFILE so nothing to do. 696 return None 697 if target_desc == CCompiler.EXECUTABLE: 698 # by default, executables always get the manifest with the 699 # CRT referenced. 700 mfid = 1 701 else: 702 # Extension modules try and avoid any manifest if possible. 703 mfid = 2 704 temp_manifest = self._remove_visual_c_ref(temp_manifest) 705 if temp_manifest is None: 706 return None 707 return temp_manifest, mfid 708 709 def _remove_visual_c_ref(self, manifest_file): 710 try: 711 # Remove references to the Visual C runtime, so they will 712 # fall through to the Visual C dependency of Python.exe. 713 # This way, when installed for a restricted user (e.g. 714 # runtimes are not in WinSxS folder, but in Python's own 715 # folder), the runtimes do not need to be in every folder 716 # with .pyd's. 717 # Returns either the filename of the modified manifest or 718 # None if no manifest should be embedded. 719 manifest_f = open(manifest_file) 672 720 try: 673 self.spawn(['mt.exe', '-nologo', '-manifest', 674 temp_manifest, out_arg]) 675 except DistutilsExecError as msg: 676 raise LinkError(msg) 677 else: 678 log.debug("skipping %s (up-to-date)", output_filename) 679 721 manifest_buf = manifest_f.read() 722 finally: 723 manifest_f.close() 724 pattern = re.compile( 725 r"""<assemblyIdentity.*?name=("|')Microsoft\."""\ 726 r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""", 727 re.DOTALL) 728 manifest_buf = re.sub(pattern, "", manifest_buf) 729 pattern = "<dependentAssembly>\s*</dependentAssembly>" 730 manifest_buf = re.sub(pattern, "", manifest_buf) 731 # Now see if any other assemblies are referenced - if not, we 732 # don't want a manifest embedded. 733 pattern = re.compile( 734 r"""<assemblyIdentity.*?name=(?:"|')(.+?)(?:"|')""" 735 r""".*?(?:/>|</assemblyIdentity>)""", re.DOTALL) 736 if re.search(pattern, manifest_buf) is None: 737 return None 738 739 manifest_f = open(manifest_file, 'w') 740 try: 741 manifest_f.write(manifest_buf) 742 return manifest_file 743 finally: 744 manifest_f.close() 745 except IOError: 746 pass 680 747 681 748 # -- Miscellaneous methods -----------------------------------------
Note:
See TracChangeset
for help on using the changeset viewer.