diff options
Diffstat (limited to 'Lib/distutils/msvc9compiler.py')
-rw-r--r-- | Lib/distutils/msvc9compiler.py | 129 |
1 files changed, 75 insertions, 54 deletions
diff --git a/Lib/distutils/msvc9compiler.py b/Lib/distutils/msvc9compiler.py index 9fe8c744cb..bf85ac75c7 100644 --- a/Lib/distutils/msvc9compiler.py +++ b/Lib/distutils/msvc9compiler.py @@ -18,10 +18,10 @@ import os import subprocess import sys import re + from distutils.errors import (DistutilsExecError, DistutilsPlatformError, - CompileError, LibError, LinkError) -from distutils.ccompiler import (CCompiler, gen_preprocess_options, - gen_lib_options) + CompileError, LibError, LinkError) +from distutils.ccompiler import CCompiler, gen_lib_options from distutils import log from distutils.util import get_platform @@ -43,10 +43,12 @@ if NATIVE_WIN64: # the corresponding registry branch, if we're running a # 64-bit Python on Win64 VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f" + VSEXPRESS_BASE = r"Software\Wow6432Node\Microsoft\VCExpress\%0.1f" WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows" NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework" else: VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f" + VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f" WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows" NET_BASE = r"Software\Microsoft\.NETFramework" @@ -63,15 +65,14 @@ class Reg: """Helper class to read values from the registry """ - @classmethod def get_value(cls, path, key): for base in HKEYS: d = cls.read_values(base, path) if d and key in d: return d[key] raise KeyError(key) + get_value = classmethod(get_value) - @classmethod def read_keys(cls, base, key): """Return list of registry keys.""" try: @@ -88,8 +89,8 @@ class Reg: L.append(k) i += 1 return L + read_keys = classmethod(read_keys) - @classmethod def read_values(cls, base, key): """Return dict of registry keys and values. @@ -110,8 +111,8 @@ class Reg: d[cls.convert_mbcs(name)] = cls.convert_mbcs(value) i += 1 return d + read_values = classmethod(read_values) - @staticmethod def convert_mbcs(s): dec = getattr(s, "decode", None) if dec is not None: @@ -120,6 +121,7 @@ class Reg: except UnicodeError: pass return s + convert_mbcs = staticmethod(convert_mbcs) class MacroExpander: @@ -141,7 +143,7 @@ class MacroExpander: "sdkinstallrootv2.0") else: raise KeyError("sdkinstallrootv2.0") - except KeyError as exc: # + except KeyError: raise DistutilsPlatformError( """Python was built with Visual Studio 2008; extensions must be built with a compiler than can generate compatible binaries. @@ -225,9 +227,18 @@ def find_vcvarsall(version): productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, "productdir") except KeyError: - log.debug("Unable to find productdir in registry") productdir = None + # trying Express edition + if productdir is None: + vsbase = VSEXPRESS_BASE % version + try: + productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, + "productdir") + except KeyError: + productdir = None + log.debug("Unable to find productdir in registry") + if not productdir or not os.path.isdir(productdir): toolskey = "VS%0.f0COMNTOOLS" % version toolsdir = os.environ.get(toolskey, None) @@ -262,23 +273,27 @@ def query_vcvarsall(version, arch="x86"): popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch), stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - stdout, stderr = popen.communicate() - if popen.wait() != 0: - raise DistutilsPlatformError(stderr.decode("mbcs")) - - stdout = stdout.decode("mbcs") - for line in stdout.split("\n"): - line = Reg.convert_mbcs(line) - if '=' not in line: - continue - line = line.strip() - key, value = line.split('=', 1) - key = key.lower() - if key in interesting: - if value.endswith(os.pathsep): - value = value[:-1] - result[key] = removeDuplicates(value) + try: + stdout, stderr = popen.communicate() + if popen.wait() != 0: + raise DistutilsPlatformError(stderr.decode("mbcs")) + + stdout = stdout.decode("mbcs") + for line in stdout.split("\n"): + line = Reg.convert_mbcs(line) + if '=' not in line: + continue + line = line.strip() + key, value = line.split('=', 1) + key = key.lower() + if key in interesting: + if value.endswith(os.pathsep): + value = value[:-1] + result[key] = removeDuplicates(value) + + finally: + popen.stdout.close() + popen.stderr.close() if len(result) != len(interesting): raise ValueError(str(list(result.keys()))) @@ -489,7 +504,7 @@ class MSVCCompiler(CCompiler) : try: self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt]) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) continue elif ext in self._mc_extensions: @@ -516,7 +531,7 @@ class MSVCCompiler(CCompiler) : self.spawn([self.rc] + ["/fo" + obj] + [rc_file]) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) continue else: @@ -529,7 +544,7 @@ class MSVCCompiler(CCompiler) : self.spawn([self.cc] + compile_opts + pp_opts + [input_opt, output_opt] + extra_postargs) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) return objects @@ -554,7 +569,7 @@ class MSVCCompiler(CCompiler) : pass # XXX what goes here? try: self.spawn([self.lib] + lib_args) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise LibError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) @@ -643,7 +658,7 @@ class MSVCCompiler(CCompiler) : self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise LinkError(msg) # embed the manifest @@ -655,37 +670,43 @@ class MSVCCompiler(CCompiler) : mfid = 1 else: mfid = 2 - try: - # Remove references to the Visual C runtime, so they will - # fall through to the Visual C dependency of Python.exe. - # This way, when installed for a restricted user (e.g. - # runtimes are not in WinSxS folder, but in Python's own - # folder), the runtimes do not need to be in every folder - # with .pyd's. - manifest_f = open(temp_manifest, "rb") - manifest_buf = manifest_f.read() - manifest_f.close() - pattern = re.compile( - r"""<assemblyIdentity.*?name=("|')Microsoft\."""\ - r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""", - re.DOTALL) - manifest_buf = re.sub(pattern, "", manifest_buf) - pattern = "<dependentAssembly>\s*</dependentAssembly>" - manifest_buf = re.sub(pattern, "", manifest_buf) - manifest_f = open(temp_manifest, "wb") - manifest_f.write(manifest_buf) - manifest_f.close() - except IOError: - pass + self._remove_visual_c_ref(temp_manifest) out_arg = '-outputresource:%s;%s' % (output_filename, mfid) try: self.spawn(['mt.exe', '-nologo', '-manifest', temp_manifest, out_arg]) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) + def _remove_visual_c_ref(self, manifest_file): + try: + # Remove references to the Visual C runtime, so they will + # fall through to the Visual C dependency of Python.exe. + # This way, when installed for a restricted user (e.g. + # runtimes are not in WinSxS folder, but in Python's own + # folder), the runtimes do not need to be in every folder + # with .pyd's. + manifest_f = open(manifest_file) + try: + manifest_buf = manifest_f.read() + finally: + manifest_f.close() + pattern = re.compile( + r"""<assemblyIdentity.*?name=("|')Microsoft\."""\ + r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""", + re.DOTALL) + manifest_buf = re.sub(pattern, "", manifest_buf) + pattern = "<dependentAssembly>\s*</dependentAssembly>" + manifest_buf = re.sub(pattern, "", manifest_buf) + manifest_f = open(manifest_file, 'w') + try: + manifest_f.write(manifest_buf) + finally: + manifest_f.close() + except IOError: + pass # -- Miscellaneous methods ----------------------------------------- # These are all used by the 'gen_lib_options() function, in |