summaryrefslogtreecommitdiff
path: root/Lib/distutils/msvc9compiler.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/distutils/msvc9compiler.py')
-rw-r--r--Lib/distutils/msvc9compiler.py129
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