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

Reply via email to