Christian Heimes added the comment:
Updated compiler and linker args from the project command lines.
Added file: http://bugs.python.org/file8781/py3k_vs2008_3.patch
__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1455>
__________________________________
Index: Lib/distutils/msvccompiler.py
===================================================================
--- Lib/distutils/msvccompiler.py (revision 59043)
+++ Lib/distutils/msvccompiler.py (working copy)
@@ -1,145 +1,152 @@
-"""distutils.msvccompiler
+"""distutils.msvc9compiler
Contains MSVCCompiler, an implementation of the abstract CCompiler class
-for the Microsoft Visual Studio.
+for the Microsoft Visual Studio 2008.
"""
# 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
-try:
- import _winreg
+import _winreg
- _can_read_reg = True
- hkey_mod = _winreg
+RegOpenKeyEx = _winreg.OpenKeyEx
+RegEnumKey = _winreg.EnumKey
+RegEnumValue = _winreg.EnumValue
+RegError = _winreg.error
- RegOpenKeyEx = _winreg.OpenKeyEx
- RegEnumKey = _winreg.EnumKey
- RegEnumValue = _winreg.EnumValue
- RegError = _winreg.error
+HKEYS = (_winreg.HKEY_USERS,
+ _winreg.HKEY_CURRENT_USER,
+ _winreg.HKEY_LOCAL_MACHINE,
+ _winreg.HKEY_CLASSES_ROOT)
-except ImportError:
- try:
- import win32api
- import win32con
- _can_read_reg = True
- hkey_mod = win32con
+VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
+WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
+NET_BASE = r"Software\Microsoft\.NETFramework"
+ARCHS = {'DEFAULT' : 'x86',
+ 'intel' : 'x86', 'x86' : 'x86',
+ 'amd64' : 'x64', 'x64' : 'x64',
+ 'itanium' : 'ia64', 'ia64' : 'ia64',
+ }
- RegOpenKeyEx = win32api.RegOpenKeyEx
- RegEnumKey = win32api.RegEnumKey
- RegEnumValue = win32api.RegEnumValue
- RegError = win32api.error
- except ImportError:
- log.info("Warning: Can't read registry to find the "
- "necessary compiler setting\n"
- "Make sure that Python modules _winreg, "
- "win32api or win32con are installed.")
- pass
+class Reg:
+ """Helper class to read values from the registry
+ """
-if _can_read_reg:
- HKEYS = (hkey_mod.HKEY_USERS,
- hkey_mod.HKEY_CURRENT_USER,
- hkey_mod.HKEY_LOCAL_MACHINE,
- hkey_mod.HKEY_CLASSES_ROOT)
-
-def read_keys(base, key):
- """Return list of registry keys."""
- try:
- handle = RegOpenKeyEx(base, key)
- except RegError:
- return None
- L = []
- i = 0
- while True:
+ @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)
+
+ @classmethod
+ def read_keys(cls, base, key):
+ """Return list of registry keys."""
try:
- k = RegEnumKey(handle, i)
+ handle = RegOpenKeyEx(base, key)
except RegError:
- break
- L.append(k)
- i += 1
- return L
+ return None
+ L = []
+ i = 0
+ while True:
+ try:
+ k = RegEnumKey(handle, i)
+ except RegError:
+ break
+ L.append(k)
+ i += 1
+ return L
-def read_values(base, key):
- """Return dict of registry keys and values.
-
- All names are converted to lowercase.
- """
- try:
- handle = RegOpenKeyEx(base, key)
- except RegError:
- return None
- d = {}
- i = 0
- while True:
+ @classmethod
+ def read_values(cls, base, key):
+ """Return dict of registry keys and values.
+
+ All names are converted to lowercase.
+ """
try:
- name, value, type = RegEnumValue(handle, i)
+ handle = RegOpenKeyEx(base, key)
except RegError:
- break
- name = name.lower()
- d[convert_mbcs(name)] = convert_mbcs(value)
- i += 1
- return d
+ return None
+ d = {}
+ i = 0
+ while True:
+ try:
+ name, value, type = RegEnumValue(handle, i)
+ except RegError:
+ break
+ name = name.lower()
+ d[cls.convert_mbcs(name)] = cls.convert_mbcs(value)
+ i += 1
+ return d
-def convert_mbcs(s):
- dec = getattr(s, "decode", None)
- if dec is not None:
- try:
- s = dec("mbcs")
- except UnicodeError:
- pass
- return s
+ @staticmethod
+ def convert_mbcs(s):
+ dec = getattr(s, "decode", None)
+ if dec is not None:
+ try:
+ s = dec("mbcs")
+ except UnicodeError:
+ pass
+ return s
class MacroExpander:
+
def __init__(self, version):
self.macros = {}
+ self.vsbase = VS_BASE % version
self.load_macros(version)
def set_macro(self, macro, path, key):
- for base in HKEYS:
- d = read_values(base, path)
- if d:
- self.macros["$(%s)" % macro] = d[key]
- break
+ self.macros["$(%s)" % macro] = Reg.get_value(path, 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", NET_BASE, "installroot")
try:
- if version > 7.0:
- self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
+ if version >= 9.0:
+ self.set_macro("FrameworkSDKDir", NET_BASE,
+ "sdkinstallrootv2.0")
+ elif version > 7.0:
+ self.set_macro("FrameworkSDKDir", NET_BASE,
+ "sdkinstallrootv1.1")
else:
- self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
+ self.set_macro("FrameworkSDKDir", NET_BASE,
+ "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 >= 9.0:
+ self.set_macro("FrameworkVersion", self.vsbase, "clr version")
+ self.set_macro("WindowsSdkDir", WINSDK_BASE, "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 = Reg.get_value(base, r"%s\%s" % (p, key))
+ self.macros["$(FrameworkVersion)"] = d["version"]
def sub(self, s):
for k, v in self.macros.items():
@@ -171,15 +178,19 @@
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]
+ sysarch = sys.version[i+len(prefix):j].lower()
+ arch = ARCHS.get(sysarch, None)
+ if arch is None:
+ return ARCHS['DEFAULT']
+ else:
+ return arch
def normalize_and_reduce_paths(paths):
"""Return a list of normalized paths with duplicates removed.
@@ -195,7 +206,78 @@
reduced_paths.append(np)
return reduced_paths
+def find_vcvarsall(version):
+ """Find the vcvarsall.bat file
+ At first it tries to find the productdir of VS 2008 in the registry. If
+ that fails it falls back to the VS90COMNTOOLS env var.
+ """
+ vsbase = VS_BASE % version
+ try:
+ productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
+ "productdir")
+ except KeyError:
+ log.debug("Unable to find productdir in registry")
+ productdir = None
+
+ if not productdir or not os.path.isdir(productdir):
+ toolskey = "VS%0.f0COMNTOOLS" % version
+ toolsdir = os.environ.get(toolskey, None)
+
+ if toolsdir and os.path.isdir(toolsdir):
+ productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
+ productdir = os.path.abspath(productdir)
+ if not os.path.isdir(productdir):
+ log.debug("%s is not a valid directory" % productdir)
+ return None
+ else:
+ log.debug("Env var %s is not set or invalid" % toolskey)
+ if not productdir:
+ log.debug("No productdir found")
+ return None
+ vcvarsall = os.path.join(productdir, "vcvarsall.bat")
+ if os.path.isfile(vcvarsall):
+ return vcvarsall
+ log.debug("Unable to find vcvarsall.bat")
+ return None
+
+def query_vcvarsall(version, arch="x86"):
+ """Launch vcvarsall.bat and read the settings from its environment
+ """
+ vcvarsall = find_vcvarsall(version)
+ interesting = set(("include", "lib", "libpath", "path"))
+ result = {}
+
+ if vcvarsall is None:
+ raise IOError("Unable to find vcvarsall.bat")
+ popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ if popen.wait() != 0:
+ raise IOError(popen.stderr.read())
+
+ for line in popen.stdout:
+ line = Reg.convert_mbcs(line)
+ if '=' not in line:
+ continue
+ line = line.strip()
+ key, value = line.split('=')
+ key = key.lower()
+ if key in interesting:
+ 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(VERSION, ARCH)
+
class MSVCCompiler(CCompiler) :
"""Concrete class that implements an interface to Microsoft Visual C++,
as defined by the CCompiler abstract class."""
@@ -228,24 +310,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 +327,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 +342,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,26 +355,32 @@
os.environ['path'] = ";".join(self.__paths)
self.preprocess_options = None
- if self.__arch == "Intel":
- self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
- '/DNDEBUG']
+ common_defines = ['/D_WINDOWS', '/D_USRDLL', '/D_UNICODE', '/DUNICODE',
+ '/D_CRT_SECURE_NO_DEPRECATED']
+ if self.__arch == "x86":
+ self.compile_options = [ '/nologo', '/Ox', '/Ob1', '/Oi',
+ '/GL', '/GF', '/Gy', '/MD', '/W3',
+ '/DNDEBUG', '/DWIN32'] + common_defines
self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
- '/Z7', '/D_DEBUG']
+ '/Z7', '/D_DEBUG'] + common_defines
else:
# Win64
self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
- '/DNDEBUG']
+ '/DNDEBUG'] + common_defines
self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
- '/Z7', '/D_DEBUG']
+ '/Z7', '/D_DEBUG'] + common_defines
- self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
+ self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO',
+ '/OPT:REF', '/OPT:ICF', '/LTCG', ]
if self.__version >= 7:
self.ldflags_shared_debug = [
- '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
+ '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG',
+ '/DYNAMICBASE:NO',
]
else:
self.ldflags_shared_debug = [
- '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
+ '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG',
+ '/DYNAMICBASE:NO',
]
self.ldflags_static = [ '/nologo']
@@ -582,53 +662,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