Latest distutils
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23252 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
		@@ -1,18 +1,9 @@
 | 
			
		||||
This is a copy of the Distutils package from Python (currently version
 | 
			
		||||
2.3a2.)  This newer copy of distutils is used for all versions of
 | 
			
		||||
2.3.)  This newer copy of distutils is used for all versions of
 | 
			
		||||
Python to avoid some problems in the older versions that show up in
 | 
			
		||||
wxPython builds and to avoid having to make some ugly hacks in local
 | 
			
		||||
modules to work around them.
 | 
			
		||||
 | 
			
		||||
There is one little 1-line customization (hack) in msvccompiler.py
 | 
			
		||||
that allows the CFLAGS to be given on the RC.EXE command line.  This
 | 
			
		||||
is required so the wx.rc files can be found when it is #included. I've
 | 
			
		||||
submitted this patch to the Python project so if it gets into the main
 | 
			
		||||
Distutils distribution I can remove this code.  (However, the newer
 | 
			
		||||
version of distutils should still always be used, at least on Windows,
 | 
			
		||||
so it will need to wait until there it a Distutils distribution that
 | 
			
		||||
can be installed on the older Pythons.)
 | 
			
		||||
 | 
			
		||||
I have not yet applied any patches specifically for MSCV 7 yet.  So
 | 
			
		||||
far it appears that if you have the PATH setup properly (like I
 | 
			
		||||
usually do) that distutils works as is.
 | 
			
		||||
 
 | 
			
		||||
@@ -883,6 +883,51 @@ class CCompiler:
 | 
			
		||||
        """
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    def has_function(self, funcname,
 | 
			
		||||
                     includes=None,
 | 
			
		||||
                     include_dirs=None,
 | 
			
		||||
                     libraries=None,
 | 
			
		||||
                     library_dirs=None):
 | 
			
		||||
        """Return a boolean indicating whether funcname is supported on
 | 
			
		||||
        the current platform.  The optional arguments can be used to
 | 
			
		||||
        augment the compilation environment.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        # this can't be included at module scope because it tries to
 | 
			
		||||
        # import math which might not be available at that point - maybe
 | 
			
		||||
        # the necessary logic should just be inlined?
 | 
			
		||||
        import tempfile
 | 
			
		||||
        if includes is None:
 | 
			
		||||
            includes = []
 | 
			
		||||
        if include_dirs is None:
 | 
			
		||||
            include_dirs = []
 | 
			
		||||
        if libraries is None:
 | 
			
		||||
            libraries = []
 | 
			
		||||
        if library_dirs is None:
 | 
			
		||||
            library_dirs = []
 | 
			
		||||
        fd, fname = tempfile.mkstemp(".c", funcname, text=True)
 | 
			
		||||
        f = os.fdopen(fd, "w")
 | 
			
		||||
        for incl in includes:
 | 
			
		||||
            f.write("""#include "%s"\n""" % incl)
 | 
			
		||||
        f.write("""\
 | 
			
		||||
main (int argc, char **argv) {
 | 
			
		||||
    %s();
 | 
			
		||||
}
 | 
			
		||||
""" % funcname)
 | 
			
		||||
        f.close()
 | 
			
		||||
        try:
 | 
			
		||||
            objects = self.compile([fname], include_dirs=include_dirs)
 | 
			
		||||
        except CompileError:
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.link_executable(objects, "a.out",
 | 
			
		||||
                                 libraries=libraries,
 | 
			
		||||
                                 library_dirs=library_dirs)
 | 
			
		||||
        except (LinkError, TypeError):
 | 
			
		||||
            return False
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def find_library_file (self, dirs, lib, debug=0):
 | 
			
		||||
        """Search the specified list of directories for a static or shared
 | 
			
		||||
        library file 'lib' and return the full path to that file.  If
 | 
			
		||||
@@ -932,6 +977,8 @@ class CCompiler:
 | 
			
		||||
        obj_names = []
 | 
			
		||||
        for src_name in source_filenames:
 | 
			
		||||
            base, ext = os.path.splitext(src_name)
 | 
			
		||||
            base = os.path.splitdrive(base)[1] # Chop off the drive
 | 
			
		||||
            base = base[os.path.isabs(base):]  # If abs, chop off leading /
 | 
			
		||||
            if ext not in self.src_extensions:
 | 
			
		||||
                raise UnknownFileError, \
 | 
			
		||||
                      "unknown file type '%s' (from '%s')" % (ext, src_name)
 | 
			
		||||
 
 | 
			
		||||
@@ -191,7 +191,7 @@ class Command:
 | 
			
		||||
        """If the current verbosity level is of greater than or equal to
 | 
			
		||||
        'level' print 'msg' to stdout.
 | 
			
		||||
        """
 | 
			
		||||
        log.debug(msg)
 | 
			
		||||
        log.log(level, msg)
 | 
			
		||||
 | 
			
		||||
    def debug_print (self, msg):
 | 
			
		||||
        """Print 'msg' to stdout if the global DEBUG (taken from the
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ __all__ = ['build',
 | 
			
		||||
           'install_scripts',
 | 
			
		||||
           'install_data',
 | 
			
		||||
           'sdist',
 | 
			
		||||
           'register',
 | 
			
		||||
           'bdist',
 | 
			
		||||
           'bdist_dumb',
 | 
			
		||||
           'bdist_rpm',
 | 
			
		||||
 
 | 
			
		||||
@@ -100,7 +100,7 @@ class bdist_wininst (Command):
 | 
			
		||||
        if not self.skip_build:
 | 
			
		||||
            self.run_command('build')
 | 
			
		||||
 | 
			
		||||
        install = self.reinitialize_command('install')
 | 
			
		||||
        install = self.reinitialize_command('install', reinit_subcommands=1)
 | 
			
		||||
        install.root = self.bdist_dir
 | 
			
		||||
        install.skip_build = self.skip_build
 | 
			
		||||
        install.warn_dir = 0
 | 
			
		||||
 
 | 
			
		||||
@@ -86,25 +86,11 @@ class build_py (Command):
 | 
			
		||||
        # Two options control which modules will be installed: 'packages'
 | 
			
		||||
        # and 'py_modules'.  The former lets us work with whole packages, not
 | 
			
		||||
        # specifying individual modules at all; the latter is for
 | 
			
		||||
        # specifying modules one-at-a-time.  Currently they are mutually
 | 
			
		||||
        # exclusive: you can define one or the other (or neither), but not
 | 
			
		||||
        # both.  It remains to be seen how limiting this is.
 | 
			
		||||
        # specifying modules one-at-a-time.
 | 
			
		||||
 | 
			
		||||
        # Dispose of the two "unusual" cases first: no pure Python modules
 | 
			
		||||
        # at all (no problem, just return silently), and over-specified
 | 
			
		||||
        # 'packages' and 'py_modules' options.
 | 
			
		||||
 | 
			
		||||
        if not self.py_modules and not self.packages:
 | 
			
		||||
            return
 | 
			
		||||
        if self.py_modules and self.packages:
 | 
			
		||||
            raise DistutilsOptionError, \
 | 
			
		||||
                  "build_py: supplying both 'packages' and 'py_modules' " + \
 | 
			
		||||
                  "options is not allowed"
 | 
			
		||||
 | 
			
		||||
        # Now we're down to two cases: 'py_modules' only and 'packages' only.
 | 
			
		||||
        if self.py_modules:
 | 
			
		||||
            self.build_modules()
 | 
			
		||||
        else:
 | 
			
		||||
        if self.packages:
 | 
			
		||||
            self.build_packages()
 | 
			
		||||
 | 
			
		||||
        self.byte_compile(self.get_outputs(include_bytecode=0))
 | 
			
		||||
@@ -276,10 +262,10 @@ class build_py (Command):
 | 
			
		||||
        (package, module, module_file), just like 'find_modules()' and
 | 
			
		||||
        'find_package_modules()' do."""
 | 
			
		||||
 | 
			
		||||
        if self.py_modules:
 | 
			
		||||
            modules = self.find_modules()
 | 
			
		||||
        else:
 | 
			
		||||
        modules = []
 | 
			
		||||
        if self.py_modules:
 | 
			
		||||
            modules.extend(self.find_modules())
 | 
			
		||||
        if self.packages:
 | 
			
		||||
            for package in self.packages:
 | 
			
		||||
                package_dir = self.get_package_dir(package)
 | 
			
		||||
                m = self.find_package_modules(package, package_dir)
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ from distutils.util import convert_path
 | 
			
		||||
from distutils import log
 | 
			
		||||
 | 
			
		||||
# check if Python is called on the first line with this expression
 | 
			
		||||
first_line_re = re.compile(r'^#!.*python[0-9.]*(\s+.*)?$')
 | 
			
		||||
first_line_re = re.compile('^#!.*python[0-9.]*([ \t].*)?$')
 | 
			
		||||
 | 
			
		||||
class build_scripts (Command):
 | 
			
		||||
 | 
			
		||||
@@ -96,7 +96,7 @@ class build_scripts (Command):
 | 
			
		||||
                                   (os.path.normpath(sys.executable),
 | 
			
		||||
                                    post_interp))
 | 
			
		||||
                    else:
 | 
			
		||||
                        outf.write("#!%s%s" %
 | 
			
		||||
                        outf.write("#!%s%s\n" %
 | 
			
		||||
                                   (os.path.join(
 | 
			
		||||
                            sysconfig.get_config_var("BINDIR"),
 | 
			
		||||
                            "python" + sysconfig.get_config_var("EXE")),
 | 
			
		||||
 
 | 
			
		||||
@@ -15,15 +15,13 @@ from distutils.errors import *
 | 
			
		||||
 | 
			
		||||
class register(Command):
 | 
			
		||||
 | 
			
		||||
    description = "register the distribution with the repository"
 | 
			
		||||
    description = ("register the distribution with the Python package index")
 | 
			
		||||
 | 
			
		||||
    DEFAULT_REPOSITORY = 'http://www.python.org/pypi'
 | 
			
		||||
 | 
			
		||||
    user_options = [
 | 
			
		||||
        ('repository=', 'r',
 | 
			
		||||
         "url of repository [default: %s]"%DEFAULT_REPOSITORY),
 | 
			
		||||
        ('verify', None,
 | 
			
		||||
         'verify the package metadata for correctness'),
 | 
			
		||||
        ('list-classifiers', None,
 | 
			
		||||
         'list the valid Trove classifiers'),
 | 
			
		||||
        ('show-response', None,
 | 
			
		||||
@@ -33,7 +31,6 @@ class register(Command):
 | 
			
		||||
 | 
			
		||||
    def initialize_options(self):
 | 
			
		||||
        self.repository = None
 | 
			
		||||
        self.verify = 0
 | 
			
		||||
        self.show_response = 0
 | 
			
		||||
        self.list_classifiers = 0
 | 
			
		||||
 | 
			
		||||
@@ -43,7 +40,7 @@ class register(Command):
 | 
			
		||||
 | 
			
		||||
    def run(self):
 | 
			
		||||
        self.check_metadata()
 | 
			
		||||
        if self.verify:
 | 
			
		||||
        if self.dry_run:
 | 
			
		||||
            self.verify_metadata()
 | 
			
		||||
        elif self.list_classifiers:
 | 
			
		||||
            self.classifiers()
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,10 @@ cygwin in no-cygwin mode).
 | 
			
		||||
#     this is windows standard and there are normally not the necessary symbols
 | 
			
		||||
#     in the dlls.
 | 
			
		||||
#   *** only the version of June 2000 shows these problems
 | 
			
		||||
# * cygwin gcc 3.2/ld 2.13.90 works
 | 
			
		||||
#   (ld supports -shared)
 | 
			
		||||
# * mingw gcc 3.2/ld 2.13 works
 | 
			
		||||
#   (ld supports -shared)
 | 
			
		||||
 | 
			
		||||
# This module should be kept compatible with Python 1.5.2.
 | 
			
		||||
 | 
			
		||||
@@ -83,7 +87,7 @@ class CygwinCCompiler (UnixCCompiler):
 | 
			
		||||
                          self.ld_version,
 | 
			
		||||
                          self.dllwrap_version) )
 | 
			
		||||
 | 
			
		||||
        # ld_version >= "2.10.90" should also be able to use
 | 
			
		||||
        # ld_version >= "2.10.90" and < "2.13" should also be able to use
 | 
			
		||||
        # gcc -mdll instead of dllwrap
 | 
			
		||||
        # Older dllwraps had own version numbers, newer ones use the
 | 
			
		||||
        # same as the rest of binutils ( also ld )
 | 
			
		||||
@@ -93,13 +97,20 @@ class CygwinCCompiler (UnixCCompiler):
 | 
			
		||||
        else:
 | 
			
		||||
            self.linker_dll = "dllwrap"
 | 
			
		||||
 | 
			
		||||
        # ld_version >= "2.13" support -shared so use it instead of
 | 
			
		||||
        # -mdll -static
 | 
			
		||||
        if self.ld_version >= "2.13":
 | 
			
		||||
            shared_option = "-shared"
 | 
			
		||||
        else:
 | 
			
		||||
            shared_option = "-mdll -static"
 | 
			
		||||
 | 
			
		||||
        # Hard-code GCC because that's what this is all about.
 | 
			
		||||
        # XXX optimization, warnings etc. should be customizable.
 | 
			
		||||
        self.set_executables(compiler='gcc -mcygwin -O -Wall',
 | 
			
		||||
                             compiler_so='gcc -mcygwin -mdll -O -Wall',
 | 
			
		||||
                             linker_exe='gcc -mcygwin',
 | 
			
		||||
                             linker_so=('%s -mcygwin -mdll -static' %
 | 
			
		||||
                                        self.linker_dll))
 | 
			
		||||
                             linker_so=('%s -mcygwin %s' %
 | 
			
		||||
                                        (self.linker_dll, shared_option)))
 | 
			
		||||
 | 
			
		||||
        # cygwin and mingw32 need different sets of libraries
 | 
			
		||||
        if self.gcc_version == "2.91.57":
 | 
			
		||||
@@ -268,6 +279,13 @@ class Mingw32CCompiler (CygwinCCompiler):
 | 
			
		||||
 | 
			
		||||
        CygwinCCompiler.__init__ (self, verbose, dry_run, force)
 | 
			
		||||
 | 
			
		||||
        # ld_version >= "2.13" support -shared so use it instead of
 | 
			
		||||
        # -mdll -static
 | 
			
		||||
        if self.ld_version >= "2.13":
 | 
			
		||||
            shared_option = "-shared"
 | 
			
		||||
        else:
 | 
			
		||||
            shared_option = "-mdll -static"
 | 
			
		||||
 | 
			
		||||
        # A real mingw32 doesn't need to specify a different entry point,
 | 
			
		||||
        # but cygwin 2.91.57 in no-cygwin-mode needs it.
 | 
			
		||||
        if self.gcc_version <= "2.91.57":
 | 
			
		||||
@@ -278,8 +296,9 @@ class Mingw32CCompiler (CygwinCCompiler):
 | 
			
		||||
        self.set_executables(compiler='gcc -mno-cygwin -O -Wall',
 | 
			
		||||
                             compiler_so='gcc -mno-cygwin -mdll -O -Wall',
 | 
			
		||||
                             linker_exe='gcc -mno-cygwin',
 | 
			
		||||
                             linker_so='%s -mno-cygwin -mdll -static %s'
 | 
			
		||||
                                        % (self.linker_dll, entry_point))
 | 
			
		||||
                             linker_so='%s -mno-cygwin %s %s'
 | 
			
		||||
                                        % (self.linker_dll, shared_option,
 | 
			
		||||
                                           entry_point))
 | 
			
		||||
        # Maybe we should also append -mthreads, but then the finished
 | 
			
		||||
        # dlls need another dll (mingwm10.dll see Mingw32 docs)
 | 
			
		||||
        # (-mthreads: Support thread-safe exception handling on `Mingw32')
 | 
			
		||||
@@ -363,7 +382,7 @@ def get_versions():
 | 
			
		||||
        out = os.popen(gcc_exe + ' -dumpversion','r')
 | 
			
		||||
        out_string = out.read()
 | 
			
		||||
        out.close()
 | 
			
		||||
        result = re.search('(\d+\.\d+\.\d+)',out_string)
 | 
			
		||||
        result = re.search('(\d+\.\d+(\.\d+)*)',out_string)
 | 
			
		||||
        if result:
 | 
			
		||||
            gcc_version = StrictVersion(result.group(1))
 | 
			
		||||
        else:
 | 
			
		||||
@@ -375,7 +394,7 @@ def get_versions():
 | 
			
		||||
        out = os.popen(ld_exe + ' -v','r')
 | 
			
		||||
        out_string = out.read()
 | 
			
		||||
        out.close()
 | 
			
		||||
        result = re.search('(\d+\.\d+\.\d+)',out_string)
 | 
			
		||||
        result = re.search('(\d+\.\d+(\.\d+)*)',out_string)
 | 
			
		||||
        if result:
 | 
			
		||||
            ld_version = StrictVersion(result.group(1))
 | 
			
		||||
        else:
 | 
			
		||||
@@ -387,7 +406,7 @@ def get_versions():
 | 
			
		||||
        out = os.popen(dllwrap_exe + ' --version','r')
 | 
			
		||||
        out_string = out.read()
 | 
			
		||||
        out.close()
 | 
			
		||||
        result = re.search(' (\d+\.\d+\.\d+)',out_string)
 | 
			
		||||
        result = re.search(' (\d+\.\d+(\.\d+)*)',out_string)
 | 
			
		||||
        if result:
 | 
			
		||||
            dllwrap_version = StrictVersion(result.group(1))
 | 
			
		||||
        else:
 | 
			
		||||
 
 | 
			
		||||
@@ -205,6 +205,15 @@ class Distribution:
 | 
			
		||||
                    for (opt, val) in cmd_options.items():
 | 
			
		||||
                        opt_dict[opt] = ("setup script", val)
 | 
			
		||||
 | 
			
		||||
            if attrs.has_key('licence'):
 | 
			
		||||
                attrs['license'] = attrs['licence']
 | 
			
		||||
                del attrs['licence']
 | 
			
		||||
                msg = "'licence' distribution option is deprecated; use 'license'"
 | 
			
		||||
                if warnings is not None:
 | 
			
		||||
                    warnings.warn(msg)
 | 
			
		||||
                else:
 | 
			
		||||
                    sys.stderr.write(msg + "\n")
 | 
			
		||||
 | 
			
		||||
            # Now work on the rest of the attributes.  Any attribute that's
 | 
			
		||||
            # not already defined is invalid!
 | 
			
		||||
            for (key,val) in attrs.items():
 | 
			
		||||
@@ -966,7 +975,7 @@ class DistributionMetadata:
 | 
			
		||||
                         "maintainer", "maintainer_email", "url",
 | 
			
		||||
                         "license", "description", "long_description",
 | 
			
		||||
                         "keywords", "platforms", "fullname", "contact",
 | 
			
		||||
                         "contact_email", "licence", "classifiers",
 | 
			
		||||
                         "contact_email", "license", "classifiers",
 | 
			
		||||
                         "download_url")
 | 
			
		||||
 | 
			
		||||
    def __init__ (self):
 | 
			
		||||
 
 | 
			
		||||
@@ -53,9 +53,9 @@ def set_threshold(level):
 | 
			
		||||
    _global_log.threshold = level
 | 
			
		||||
 | 
			
		||||
def set_verbosity(v):
 | 
			
		||||
    if v == 0:
 | 
			
		||||
    if v <= 0:
 | 
			
		||||
        set_threshold(WARN)
 | 
			
		||||
    if v == 1:
 | 
			
		||||
    elif v == 1:
 | 
			
		||||
        set_threshold(INFO)
 | 
			
		||||
    if v == 2:
 | 
			
		||||
    elif v >= 2:
 | 
			
		||||
        set_threshold(DEBUG)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
"""distutils.msvccompiler
 | 
			
		||||
 | 
			
		||||
Contains MSVCCompiler, an implementation of the abstract CCompiler class
 | 
			
		||||
for the Microsoft Visual Studio."""
 | 
			
		||||
for the Microsoft Visual Studio.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
# Written by Perry Stoll
 | 
			
		||||
# hacked by Robin Becker and Thomas Heller to do a better job of
 | 
			
		||||
@@ -12,7 +13,6 @@ for the Microsoft Visual Studio."""
 | 
			
		||||
__revision__ = "$Id$"
 | 
			
		||||
 | 
			
		||||
import sys, os, string
 | 
			
		||||
from types import *
 | 
			
		||||
from distutils.errors import \
 | 
			
		||||
     DistutilsExecError, DistutilsPlatformError, \
 | 
			
		||||
     CompileError, LibError, LinkError
 | 
			
		||||
@@ -45,128 +45,127 @@ except ImportError:
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
if _can_read_reg:
 | 
			
		||||
    HKEY_CLASSES_ROOT = hkey_mod.HKEY_CLASSES_ROOT
 | 
			
		||||
    HKEY_LOCAL_MACHINE = hkey_mod.HKEY_LOCAL_MACHINE
 | 
			
		||||
    HKEY_CURRENT_USER = hkey_mod.HKEY_CURRENT_USER
 | 
			
		||||
    HKEY_USERS = hkey_mod.HKEY_USERS
 | 
			
		||||
    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."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_devstudio_versions ():
 | 
			
		||||
    """Get list of devstudio versions from the Windows registry.  Return a
 | 
			
		||||
       list of strings containing version numbers; the list will be
 | 
			
		||||
       empty if we were unable to access the registry (eg. couldn't import
 | 
			
		||||
       a registry-access module) or the appropriate registry keys weren't
 | 
			
		||||
       found."""
 | 
			
		||||
 | 
			
		||||
    if not _can_read_reg:
 | 
			
		||||
        return []
 | 
			
		||||
 | 
			
		||||
    K = 'Software\\Microsoft\\Devstudio'
 | 
			
		||||
    L = []
 | 
			
		||||
    for base in (HKEY_CLASSES_ROOT,
 | 
			
		||||
                 HKEY_LOCAL_MACHINE,
 | 
			
		||||
                 HKEY_CURRENT_USER,
 | 
			
		||||
                 HKEY_USERS):
 | 
			
		||||
    try:
 | 
			
		||||
            k = RegOpenKeyEx(base,K)
 | 
			
		||||
        handle = RegOpenKeyEx(base, key)
 | 
			
		||||
    except RegError:
 | 
			
		||||
        return None
 | 
			
		||||
    L = []
 | 
			
		||||
    i = 0
 | 
			
		||||
    while 1:
 | 
			
		||||
        try:
 | 
			
		||||
                    p = RegEnumKey(k,i)
 | 
			
		||||
                    if p[0] in '123456789' and p not in L:
 | 
			
		||||
                        L.append(p)
 | 
			
		||||
            k = RegEnumKey(handle, i)
 | 
			
		||||
        except RegError:
 | 
			
		||||
            break
 | 
			
		||||
        L.append(k)
 | 
			
		||||
        i = i + 1
 | 
			
		||||
        except RegError:
 | 
			
		||||
            pass
 | 
			
		||||
    L.sort()
 | 
			
		||||
    L.reverse()
 | 
			
		||||
    return L
 | 
			
		||||
 | 
			
		||||
# get_devstudio_versions ()
 | 
			
		||||
def read_values(base, key):
 | 
			
		||||
    """Return dict of registry keys and values.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_msvc_paths (path, version='6.0', platform='x86'):
 | 
			
		||||
    """Get a list of devstudio directories (include, lib or path).  Return
 | 
			
		||||
       a list of strings; will be empty list if unable to access the
 | 
			
		||||
       registry or appropriate registry keys not found."""
 | 
			
		||||
 | 
			
		||||
    if not _can_read_reg:
 | 
			
		||||
        return []
 | 
			
		||||
 | 
			
		||||
    L = []
 | 
			
		||||
    if path=='lib':
 | 
			
		||||
        path= 'Library'
 | 
			
		||||
    path = string.upper(path + ' Dirs')
 | 
			
		||||
    K = ('Software\\Microsoft\\Devstudio\\%s\\' +
 | 
			
		||||
         'Build System\\Components\\Platforms\\Win32 (%s)\\Directories') % \
 | 
			
		||||
        (version,platform)
 | 
			
		||||
    for base in (HKEY_CLASSES_ROOT,
 | 
			
		||||
                 HKEY_LOCAL_MACHINE,
 | 
			
		||||
                 HKEY_CURRENT_USER,
 | 
			
		||||
                 HKEY_USERS):
 | 
			
		||||
    All names are converted to lowercase.
 | 
			
		||||
    """
 | 
			
		||||
    try:
 | 
			
		||||
            k = RegOpenKeyEx(base,K)
 | 
			
		||||
        handle = RegOpenKeyEx(base, key)
 | 
			
		||||
    except RegError:
 | 
			
		||||
        return None
 | 
			
		||||
    d = {}
 | 
			
		||||
    i = 0
 | 
			
		||||
    while 1:
 | 
			
		||||
        try:
 | 
			
		||||
                    (p,v,t) = RegEnumValue(k,i)
 | 
			
		||||
                    if string.upper(p) == path:
 | 
			
		||||
                        V = string.split(v,';')
 | 
			
		||||
                        for v in V:
 | 
			
		||||
                            if hasattr(v, "encode"):
 | 
			
		||||
            name, value, type = RegEnumValue(handle, i)
 | 
			
		||||
        except RegError:
 | 
			
		||||
            break
 | 
			
		||||
        name = name.lower()
 | 
			
		||||
        d[convert_mbcs(name)] = convert_mbcs(value)
 | 
			
		||||
        i = i + 1
 | 
			
		||||
    return d
 | 
			
		||||
 | 
			
		||||
def convert_mbcs(s):
 | 
			
		||||
    enc = getattr(s, "encode", None)
 | 
			
		||||
    if enc is not None:
 | 
			
		||||
        try:
 | 
			
		||||
                                    v = v.encode("mbcs")
 | 
			
		||||
            s = enc("mbcs")
 | 
			
		||||
        except UnicodeError:
 | 
			
		||||
            pass
 | 
			
		||||
                            if v == '' or v in L: continue
 | 
			
		||||
                            L.append(v)
 | 
			
		||||
    return s
 | 
			
		||||
 | 
			
		||||
class MacroExpander:
 | 
			
		||||
 | 
			
		||||
    def __init__(self, version):
 | 
			
		||||
        self.macros = {}
 | 
			
		||||
        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
 | 
			
		||||
                    i = i + 1
 | 
			
		||||
              
 | 
			
		||||
    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")
 | 
			
		||||
        if version > 7.0:
 | 
			
		||||
            self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
 | 
			
		||||
        else:
 | 
			
		||||
            self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
 | 
			
		||||
 | 
			
		||||
        p = r"Software\Microsoft\NET Framework Setup\Product"
 | 
			
		||||
        for base in HKEYS:
 | 
			
		||||
            try:
 | 
			
		||||
                h = RegOpenKeyEx(base, p)
 | 
			
		||||
            except RegError:
 | 
			
		||||
                    break
 | 
			
		||||
        except RegError:
 | 
			
		||||
            pass
 | 
			
		||||
    return L
 | 
			
		||||
                continue
 | 
			
		||||
            key = RegEnumKey(h, 0)
 | 
			
		||||
            d = read_values(base, r"%s\%s" % (p, key))
 | 
			
		||||
            self.macros["$(FrameworkVersion)"] = d["version"]
 | 
			
		||||
 | 
			
		||||
# get_msvc_paths()
 | 
			
		||||
    def sub(self, s):
 | 
			
		||||
        for k, v in self.macros.items():
 | 
			
		||||
            s = string.replace(s, k, v)
 | 
			
		||||
        return s
 | 
			
		||||
 | 
			
		||||
def get_build_version():
 | 
			
		||||
    """Return the version of MSVC that was used to build Python.
 | 
			
		||||
 | 
			
		||||
def find_exe (exe, version_number):
 | 
			
		||||
    """Try to find an MSVC executable program 'exe' (from version
 | 
			
		||||
       'version_number' of MSVC) in several places: first, one of the MSVC
 | 
			
		||||
       program search paths from the registry; next, the directories in the
 | 
			
		||||
       PATH environment variable.  If any of those work, return an absolute
 | 
			
		||||
       path that is known to exist.  If none of them work, just return the
 | 
			
		||||
       original program name, 'exe'."""
 | 
			
		||||
    For Python 2.3 and up, the version number is included in
 | 
			
		||||
    sys.version.  For earlier versions, assume the compiler is MSVC 6.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    for p in get_msvc_paths ('path', version_number):
 | 
			
		||||
        fn = os.path.join (os.path.abspath(p), exe)
 | 
			
		||||
        if os.path.isfile(fn):
 | 
			
		||||
            return fn
 | 
			
		||||
 | 
			
		||||
    # didn't find it; try existing path
 | 
			
		||||
    for p in string.split (os.environ['Path'],';'):
 | 
			
		||||
        fn = os.path.join(os.path.abspath(p),exe)
 | 
			
		||||
        if os.path.isfile(fn):
 | 
			
		||||
            return fn
 | 
			
		||||
 | 
			
		||||
    return exe                          # last desperate hope
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def set_path_env_var (name, version_number):
 | 
			
		||||
    """Set environment variable 'name' to an MSVC path type value obtained
 | 
			
		||||
       from 'get_msvc_paths()'.  This is equivalent to a SET command prior
 | 
			
		||||
       to execution of spawned commands."""
 | 
			
		||||
 | 
			
		||||
    p = get_msvc_paths (name, version_number)
 | 
			
		||||
    if p:
 | 
			
		||||
        os.environ[name] = string.join (p,';')
 | 
			
		||||
    prefix = "MSC v."
 | 
			
		||||
    i = string.find(sys.version, prefix)
 | 
			
		||||
    if i == -1:
 | 
			
		||||
        return 6
 | 
			
		||||
    i = i + len(prefix)
 | 
			
		||||
    s, rest = sys.version[i:].split(" ", 1)
 | 
			
		||||
    majorVersion = int(s[:-2]) - 6
 | 
			
		||||
    minorVersion = int(s[2:3]) / 10.0
 | 
			
		||||
    # I don't think paths are affected by minor version in version 6
 | 
			
		||||
    if majorVersion == 6:
 | 
			
		||||
        minorVersion = 0
 | 
			
		||||
    if majorVersion >= 6:
 | 
			
		||||
        return majorVersion + minorVersion
 | 
			
		||||
    # else we don't know what version of the compiler this is
 | 
			
		||||
    return None
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
class MSVCCompiler (CCompiler) :
 | 
			
		||||
@@ -199,39 +198,37 @@ class MSVCCompiler (CCompiler) :
 | 
			
		||||
    static_lib_format = shared_lib_format = '%s%s'
 | 
			
		||||
    exe_extension = '.exe'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def __init__ (self,
 | 
			
		||||
                  verbose=0,
 | 
			
		||||
                  dry_run=0,
 | 
			
		||||
                  force=0):
 | 
			
		||||
 | 
			
		||||
    def __init__ (self, verbose=0, dry_run=0, force=0):
 | 
			
		||||
        CCompiler.__init__ (self, verbose, dry_run, force)
 | 
			
		||||
        versions = get_devstudio_versions ()
 | 
			
		||||
        self.__version = get_build_version()
 | 
			
		||||
        if self.__version >= 7:
 | 
			
		||||
            self.__root = r"Software\Microsoft\VisualStudio"
 | 
			
		||||
            self.__macros = MacroExpander(self.__version)
 | 
			
		||||
        else:
 | 
			
		||||
            self.__root = r"Software\Microsoft\Devstudio"
 | 
			
		||||
        self.__paths = self.get_msvc_paths("path")
 | 
			
		||||
 | 
			
		||||
        if versions:
 | 
			
		||||
            version = versions[0]  # highest version
 | 
			
		||||
        if len (self.__paths) == 0:
 | 
			
		||||
            raise DistutilsPlatformError, \
 | 
			
		||||
                  ("Python was built with version %s of Visual Studio, "
 | 
			
		||||
                   "and extensions need to be built with the same "
 | 
			
		||||
                   "version of the compiler, but it isn't installed." % self.__version)
 | 
			
		||||
 | 
			
		||||
            self.cc   = find_exe("cl.exe", version)
 | 
			
		||||
            self.linker = find_exe("link.exe", version)
 | 
			
		||||
            self.lib  = find_exe("lib.exe", version)
 | 
			
		||||
            self.rc   = find_exe("rc.exe", version)     # resource compiler
 | 
			
		||||
            self.mc   = find_exe("mc.exe", version)     # message compiler
 | 
			
		||||
            set_path_env_var ('lib', version)
 | 
			
		||||
            set_path_env_var ('include', version)
 | 
			
		||||
            path=get_msvc_paths('path', version)
 | 
			
		||||
        self.cc = self.find_exe("cl.exe")
 | 
			
		||||
        self.linker = self.find_exe("link.exe")
 | 
			
		||||
        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')
 | 
			
		||||
 | 
			
		||||
        # extend the MSVC path with the current path
 | 
			
		||||
        try:
 | 
			
		||||
                for p in string.split(os.environ['path'],';'):
 | 
			
		||||
                    path.append(p)
 | 
			
		||||
            for p in string.split(os.environ['path'], ';'):
 | 
			
		||||
                self.__paths.append(p)
 | 
			
		||||
        except KeyError:
 | 
			
		||||
            pass
 | 
			
		||||
            os.environ['path'] = string.join(path,';')
 | 
			
		||||
        else:
 | 
			
		||||
            # devstudio not found in the registry
 | 
			
		||||
            self.cc = "cl.exe"
 | 
			
		||||
            self.linker = "link.exe"
 | 
			
		||||
            self.lib = "lib.exe"
 | 
			
		||||
            self.rc = "rc.exe"
 | 
			
		||||
            self.mc = "mc.exe"
 | 
			
		||||
        os.environ['path'] = string.join(self.__paths, ';')
 | 
			
		||||
 | 
			
		||||
        self.preprocess_options = None
 | 
			
		||||
        self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
 | 
			
		||||
@@ -500,4 +497,69 @@ class MSVCCompiler (CCompiler) :
 | 
			
		||||
 | 
			
		||||
    # find_library_file ()
 | 
			
		||||
 | 
			
		||||
# class MSVCCompiler
 | 
			
		||||
    # Helper methods for using the MSVC registry settings
 | 
			
		||||
 | 
			
		||||
    def find_exe(self, exe):
 | 
			
		||||
        """Return path to an MSVC executable program.
 | 
			
		||||
 | 
			
		||||
        Tries to find the program in several places: first, one of the
 | 
			
		||||
        MSVC program search paths from the registry; next, the directories
 | 
			
		||||
        in the PATH environment variable.  If any of those work, return an
 | 
			
		||||
        absolute path that is known to exist.  If none of them work, just
 | 
			
		||||
        return the original program name, 'exe'.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        for p in self.__paths:
 | 
			
		||||
            fn = os.path.join(os.path.abspath(p), exe)
 | 
			
		||||
            if os.path.isfile(fn):
 | 
			
		||||
                return fn
 | 
			
		||||
 | 
			
		||||
        # didn't find it; try existing path
 | 
			
		||||
        for p in string.split(os.environ['Path'],';'):
 | 
			
		||||
            fn = os.path.join(os.path.abspath(p),exe)
 | 
			
		||||
            if os.path.isfile(fn):
 | 
			
		||||
                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 string.split(self.__macros.sub(d[path]), ";")
 | 
			
		||||
                else:
 | 
			
		||||
                    return string.split(d[path], ";")
 | 
			
		||||
        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] = string.join(p, ';')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -77,6 +77,8 @@ class UnixCCompiler(CCompiler):
 | 
			
		||||
    shared_lib_extension = ".so"
 | 
			
		||||
    dylib_lib_extension = ".dylib"
 | 
			
		||||
    static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"
 | 
			
		||||
    if sys.platform == "cygwin":
 | 
			
		||||
        exe_extension = ".exe"
 | 
			
		||||
 | 
			
		||||
    def preprocess(self, source,
 | 
			
		||||
                   output_file=None, macros=None, include_dirs=None,
 | 
			
		||||
@@ -201,6 +203,8 @@ class UnixCCompiler(CCompiler):
 | 
			
		||||
        if sys.platform[:6] == "darwin":
 | 
			
		||||
            # MacOSX's linker doesn't understand the -R flag at all
 | 
			
		||||
            return "-L" + dir
 | 
			
		||||
        elif sys.platform[:5] == "hp-ux":
 | 
			
		||||
            return "+s -L" + dir
 | 
			
		||||
        elif compiler[:3] == "gcc" or compiler[:3] == "g++":
 | 
			
		||||
          return "-Wl,-R" + dir
 | 
			
		||||
        else:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user