New submission from Christian Heimes:
I've come up with a quick hack to support VS 2008. VS 2008 Standard
Edition doesn't store the include and lib dirs in the registry any more.
However I came up with a nice way to get the env settings from the
vcvarsall.bat. How do you like it?
Do we need support for VS6 and VS7.1 or can I remove the code from the
module?
----------
assignee: loewis
components: Distutils
files: py3k_vs2008_hack.patch
keywords: patch, py3k
messages: 57599
nosy: loewis, tiran
priority: normal
severity: normal
status: open
title: VS2008, quick hack for distutils.msvccompiler
type: rfe
versions: Python 3.0
Added file: http://bugs.python.org/file8766/py3k_vs2008_hack.patch
__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1455>
__________________________________
Index: Lib/distutils/msvccompiler.py
===================================================================
--- Lib/distutils/msvccompiler.py (revision 59036)
+++ Lib/distutils/msvccompiler.py (working copy)
@@ -7,15 +7,17 @@
# Written by Perry Stoll
# hacked by Robin Becker and Thomas Heller to do a better job of
# finding DevStudio (through the registry)
+# ported to VS 2008 by Christian Heimes
__revision__ = "$Id$"
-import sys, os
-from distutils.errors import \
- DistutilsExecError, DistutilsPlatformError, \
- CompileError, LibError, LinkError
-from distutils.ccompiler import \
- CCompiler, gen_preprocess_options, gen_lib_options
+import os
+import subprocess
+import sys
+from distutils.errors import (DistutilsExecError, DistutilsPlatformError,
+ CompileError, LibError, LinkError)
+from distutils.ccompiler import (CCompiler, gen_preprocess_options,
+ gen_lib_options)
from distutils import log
_can_read_reg = False
@@ -102,44 +104,57 @@
return s
class MacroExpander:
+ _vsbase = r"Software\Microsoft\VisualStudio\%0.1f"
+ winsdkbase = r"Software\Microsoft\Microsoft SDKs\Windows"
+ netframework = r"Software\Microsoft\.NETFramework"
+
def __init__(self, version):
self.macros = {}
+ self.vsbase = self._vsbase % version
self.load_macros(version)
def set_macro(self, macro, path, key):
for base in HKEYS:
d = read_values(base, path)
- if d:
+ if d and key in d:
self.macros["$(%s)" % macro] = d[key]
- break
+ return
+ raise KeyError(key)
def load_macros(self, version):
- vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
- self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
- self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
- net = r"Software\Microsoft\.NETFramework"
- self.set_macro("FrameworkDir", net, "installroot")
+ self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir")
+ self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir")
+ self.set_macro("FrameworkDir", self.netframework, "installroot")
try:
- if version > 7.0:
- self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
+ if version >= 9.0:
+ self.set_macro("FrameworkSDKDir", self.netframework,
+ "sdkinstallrootv2.0")
+ elif version > 7.0:
+ self.set_macro("FrameworkSDKDir", self.netframework,
+ "sdkinstallrootv1.1")
else:
- self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
+ self.set_macro("FrameworkSDKDir", self.netframework,
+ "sdkinstallroot")
except KeyError as exc: #
raise DistutilsPlatformError(
- """Python was built with Visual Studio 2003;
+ """Python was built with Visual Studio 2008;
extensions must be built with a compiler than can generate compatible binaries.
-Visual Studio 2003 was not found on this system. If you have Cygwin installed,
+Visual Studio 2008 was not found on this system. If you have Cygwin installed,
you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
- p = r"Software\Microsoft\NET Framework Setup\Product"
- for base in HKEYS:
- try:
- h = RegOpenKeyEx(base, p)
- except RegError:
- continue
- key = RegEnumKey(h, 0)
- d = read_values(base, r"%s\%s" % (p, key))
- self.macros["$(FrameworkVersion)"] = d["version"]
+ if version >= 0.9:
+ self.set_macro("FrameworkVersion", self.vsbase, "clr version")
+ self.set_macro("WindowsSdkDir", self.winsdkbase, "currentinstallfolder")
+ else:
+ p = r"Software\Microsoft\NET Framework Setup\Product"
+ for base in HKEYS:
+ try:
+ h = RegOpenKeyEx(base, p)
+ except RegError:
+ continue
+ key = RegEnumKey(h, 0)
+ d = read_values(base, r"%s\%s" % (p, key))
+ self.macros["$(FrameworkVersion)"] = d["version"]
def sub(self, s):
for k, v in self.macros.items():
@@ -171,15 +186,15 @@
def get_build_architecture():
"""Return the processor architecture.
- Possible results are "Intel", "Itanium", or "AMD64".
+ Possible results are "x86" or "amd64".
"""
prefix = " bit ("
i = sys.version.find(prefix)
if i == -1:
- return "Intel"
+ return "x86"
j = sys.version.find(")", i)
- return sys.version[i+len(prefix):j]
+ return sys.version[i+len(prefix):j].lower()
def normalize_and_reduce_paths(paths):
"""Return a list of normalized paths with duplicates removed.
@@ -195,7 +210,44 @@
reduced_paths.append(np)
return reduced_paths
+def query_vcvarsall(macros, arch="x86"):
+ """Launch vcvarsall.bat and read the settings from its environment
+ """
+ vc = macros.macros["$(VCInstallDir)"]
+ vcvarsall = os.path.join(vc, "vcvarsall.bat")
+ interesting = set(("include", "lib", "libpath", "path"))
+ result = {}
+
+ if not os.path.exists(vcvarsall):
+ raise IOError(vcvarsall)
+ popen = subprocess.Popen('"%s" & set' % vcvarsall, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ if popen.wait() != 0:
+ raise IOError(popen.stderr.read())
+ for line in popen.stdout:
+ if b'=' not in line:
+ continue
+ line = line.strip()
+ key, value = line.split(b'=')
+ key = convert_mbcs(key.lower())
+
+ if key in interesting:
+ value = convert_mbcs(value)
+ if value.endswith(os.pathsep):
+ value = value[:-1]
+ result[key] = value
+
+ if len(result) != len(interesting):
+ raise ValueError(str(list(result.keys())))
+
+ return result
+
+VERSION = get_build_version()
+ARCH = get_build_architecture()
+MACROS = MacroExpander(VERSION)
+VC_ENV = query_vcvarsall(MACROS, ARCH)
+
class MSVCCompiler(CCompiler) :
"""Concrete class that implements an interface to Microsoft Visual C++,
as defined by the CCompiler abstract class."""
@@ -228,24 +280,14 @@
def __init__(self, verbose=0, dry_run=0, force=0):
CCompiler.__init__ (self, verbose, dry_run, force)
- self.__version = get_build_version()
- self.__arch = get_build_architecture()
- if self.__arch == "Intel":
- # x86
- if self.__version >= 7:
- self.__root = r"Software\Microsoft\VisualStudio"
- self.__macros = MacroExpander(self.__version)
- else:
- self.__root = r"Software\Microsoft\Devstudio"
- self.__product = "Visual Studio version %s" % self.__version
- else:
- # Win64. Assume this was built with the platform SDK
- self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
-
+ self.__version = VERSION
+ self.__arch = ARCH
+ self.__root = r"Software\Microsoft\VisualStudio"
+ self.__macros = MACROS
+ self.__path = []
self.initialized = False
def initialize(self):
- self.__paths = []
if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
# Assume that the SDK set up everything alright; don't try to be
# smarter
@@ -255,7 +297,9 @@
self.rc = "rc.exe"
self.mc = "mc.exe"
else:
- self.__paths = self.get_msvc_paths("path")
+ self.__paths = VC_ENV['path'].split(os.pathsep)
+ os.environ['lib'] = VC_ENV['lib']
+ os.environ['include'] = VC_ENV['include']
if len(self.__paths) == 0:
raise DistutilsPlatformError("Python was built with %s, "
@@ -268,8 +312,8 @@
self.lib = self.find_exe("lib.exe")
self.rc = self.find_exe("rc.exe") # resource compiler
self.mc = self.find_exe("mc.exe") # message compiler
- self.set_path_env_var('lib')
- self.set_path_env_var('include')
+ #self.set_path_env_var('lib')
+ #self.set_path_env_var('include')
# extend the MSVC path with the current path
try:
@@ -281,7 +325,7 @@
os.environ['path'] = ";".join(self.__paths)
self.preprocess_options = None
- if self.__arch == "Intel":
+ if self.__arch == "x86":
self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
'/DNDEBUG']
self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
@@ -582,53 +626,3 @@
return fn
return exe
-
- def get_msvc_paths(self, path, platform='x86'):
- """Get a list of devstudio directories (include, lib or path).
-
- Return a list of strings. The list will be empty if unable to
- access the registry or appropriate registry keys not found.
- """
- if not _can_read_reg:
- return []
-
- path = path + " dirs"
- if self.__version >= 7:
- key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories"
- % (self.__root, self.__version))
- else:
- key = (r"%s\6.0\Build System\Components\Platforms"
- r"\Win32 (%s)\Directories" % (self.__root, platform))
-
- for base in HKEYS:
- d = read_values(base, key)
- if d:
- if self.__version >= 7:
- return self.__macros.sub(d[path]).split(";")
- else:
- return d[path].split(";")
- # MSVC 6 seems to create the registry entries we need only when
- # the GUI is run.
- if self.__version == 6:
- for base in HKEYS:
- if read_values(base, r"%s\6.0" % self.__root) is not None:
- self.warn("It seems you have Visual Studio 6 installed, "
- "but the expected registry settings are not present.\n"
- "You must at least run the Visual Studio GUI once "
- "so that these entries are created.")
- break
- return []
-
- def set_path_env_var(self, name):
- """Set environment variable 'name' to an MSVC path type value.
-
- This is equivalent to a SET command prior to execution of spawned
- commands.
- """
-
- if name == "lib":
- p = self.get_msvc_paths("library")
- else:
- p = self.get_msvc_paths(name)
- if p:
- os.environ[name] = ';'.join(p)
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com