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
|
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
|
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
|
wxPython builds and to avoid having to make some ugly hacks in local
|
||||||
modules to work around them.
|
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
|
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
|
far it appears that if you have the PATH setup properly (like I
|
||||||
usually do) that distutils works as is.
|
usually do) that distutils works as is.
|
||||||
|
@@ -883,6 +883,51 @@ class CCompiler:
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
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):
|
def find_library_file (self, dirs, lib, debug=0):
|
||||||
"""Search the specified list of directories for a static or shared
|
"""Search the specified list of directories for a static or shared
|
||||||
library file 'lib' and return the full path to that file. If
|
library file 'lib' and return the full path to that file. If
|
||||||
@@ -932,6 +977,8 @@ class CCompiler:
|
|||||||
obj_names = []
|
obj_names = []
|
||||||
for src_name in source_filenames:
|
for src_name in source_filenames:
|
||||||
base, ext = os.path.splitext(src_name)
|
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:
|
if ext not in self.src_extensions:
|
||||||
raise UnknownFileError, \
|
raise UnknownFileError, \
|
||||||
"unknown file type '%s' (from '%s')" % (ext, src_name)
|
"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
|
"""If the current verbosity level is of greater than or equal to
|
||||||
'level' print 'msg' to stdout.
|
'level' print 'msg' to stdout.
|
||||||
"""
|
"""
|
||||||
log.debug(msg)
|
log.log(level, msg)
|
||||||
|
|
||||||
def debug_print (self, msg):
|
def debug_print (self, msg):
|
||||||
"""Print 'msg' to stdout if the global DEBUG (taken from the
|
"""Print 'msg' to stdout if the global DEBUG (taken from the
|
||||||
|
@@ -19,6 +19,7 @@ __all__ = ['build',
|
|||||||
'install_scripts',
|
'install_scripts',
|
||||||
'install_data',
|
'install_data',
|
||||||
'sdist',
|
'sdist',
|
||||||
|
'register',
|
||||||
'bdist',
|
'bdist',
|
||||||
'bdist_dumb',
|
'bdist_dumb',
|
||||||
'bdist_rpm',
|
'bdist_rpm',
|
||||||
|
@@ -100,7 +100,7 @@ class bdist_wininst (Command):
|
|||||||
if not self.skip_build:
|
if not self.skip_build:
|
||||||
self.run_command('build')
|
self.run_command('build')
|
||||||
|
|
||||||
install = self.reinitialize_command('install')
|
install = self.reinitialize_command('install', reinit_subcommands=1)
|
||||||
install.root = self.bdist_dir
|
install.root = self.bdist_dir
|
||||||
install.skip_build = self.skip_build
|
install.skip_build = self.skip_build
|
||||||
install.warn_dir = 0
|
install.warn_dir = 0
|
||||||
|
@@ -86,25 +86,11 @@ class build_py (Command):
|
|||||||
# Two options control which modules will be installed: 'packages'
|
# Two options control which modules will be installed: 'packages'
|
||||||
# and 'py_modules'. The former lets us work with whole packages, not
|
# and 'py_modules'. The former lets us work with whole packages, not
|
||||||
# specifying individual modules at all; the latter is for
|
# specifying individual modules at all; the latter is for
|
||||||
# specifying modules one-at-a-time. Currently they are mutually
|
# specifying modules one-at-a-time.
|
||||||
# exclusive: you can define one or the other (or neither), but not
|
|
||||||
# both. It remains to be seen how limiting this is.
|
|
||||||
|
|
||||||
# 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:
|
if self.py_modules:
|
||||||
self.build_modules()
|
self.build_modules()
|
||||||
else:
|
if self.packages:
|
||||||
self.build_packages()
|
self.build_packages()
|
||||||
|
|
||||||
self.byte_compile(self.get_outputs(include_bytecode=0))
|
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
|
(package, module, module_file), just like 'find_modules()' and
|
||||||
'find_package_modules()' do."""
|
'find_package_modules()' do."""
|
||||||
|
|
||||||
if self.py_modules:
|
|
||||||
modules = self.find_modules()
|
|
||||||
else:
|
|
||||||
modules = []
|
modules = []
|
||||||
|
if self.py_modules:
|
||||||
|
modules.extend(self.find_modules())
|
||||||
|
if self.packages:
|
||||||
for package in self.packages:
|
for package in self.packages:
|
||||||
package_dir = self.get_package_dir(package)
|
package_dir = self.get_package_dir(package)
|
||||||
m = self.find_package_modules(package, package_dir)
|
m = self.find_package_modules(package, package_dir)
|
||||||
|
@@ -15,7 +15,7 @@ from distutils.util import convert_path
|
|||||||
from distutils import log
|
from distutils import log
|
||||||
|
|
||||||
# check if Python is called on the first line with this expression
|
# 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):
|
class build_scripts (Command):
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ class build_scripts (Command):
|
|||||||
(os.path.normpath(sys.executable),
|
(os.path.normpath(sys.executable),
|
||||||
post_interp))
|
post_interp))
|
||||||
else:
|
else:
|
||||||
outf.write("#!%s%s" %
|
outf.write("#!%s%s\n" %
|
||||||
(os.path.join(
|
(os.path.join(
|
||||||
sysconfig.get_config_var("BINDIR"),
|
sysconfig.get_config_var("BINDIR"),
|
||||||
"python" + sysconfig.get_config_var("EXE")),
|
"python" + sysconfig.get_config_var("EXE")),
|
||||||
|
@@ -15,15 +15,13 @@ from distutils.errors import *
|
|||||||
|
|
||||||
class register(Command):
|
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'
|
DEFAULT_REPOSITORY = 'http://www.python.org/pypi'
|
||||||
|
|
||||||
user_options = [
|
user_options = [
|
||||||
('repository=', 'r',
|
('repository=', 'r',
|
||||||
"url of repository [default: %s]"%DEFAULT_REPOSITORY),
|
"url of repository [default: %s]"%DEFAULT_REPOSITORY),
|
||||||
('verify', None,
|
|
||||||
'verify the package metadata for correctness'),
|
|
||||||
('list-classifiers', None,
|
('list-classifiers', None,
|
||||||
'list the valid Trove classifiers'),
|
'list the valid Trove classifiers'),
|
||||||
('show-response', None,
|
('show-response', None,
|
||||||
@@ -33,7 +31,6 @@ class register(Command):
|
|||||||
|
|
||||||
def initialize_options(self):
|
def initialize_options(self):
|
||||||
self.repository = None
|
self.repository = None
|
||||||
self.verify = 0
|
|
||||||
self.show_response = 0
|
self.show_response = 0
|
||||||
self.list_classifiers = 0
|
self.list_classifiers = 0
|
||||||
|
|
||||||
@@ -43,7 +40,7 @@ class register(Command):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.check_metadata()
|
self.check_metadata()
|
||||||
if self.verify:
|
if self.dry_run:
|
||||||
self.verify_metadata()
|
self.verify_metadata()
|
||||||
elif self.list_classifiers:
|
elif self.list_classifiers:
|
||||||
self.classifiers()
|
self.classifiers()
|
||||||
|
@@ -40,6 +40,10 @@ cygwin in no-cygwin mode).
|
|||||||
# this is windows standard and there are normally not the necessary symbols
|
# this is windows standard and there are normally not the necessary symbols
|
||||||
# in the dlls.
|
# in the dlls.
|
||||||
# *** only the version of June 2000 shows these problems
|
# *** 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.
|
# This module should be kept compatible with Python 1.5.2.
|
||||||
|
|
||||||
@@ -83,7 +87,7 @@ class CygwinCCompiler (UnixCCompiler):
|
|||||||
self.ld_version,
|
self.ld_version,
|
||||||
self.dllwrap_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
|
# gcc -mdll instead of dllwrap
|
||||||
# Older dllwraps had own version numbers, newer ones use the
|
# Older dllwraps had own version numbers, newer ones use the
|
||||||
# same as the rest of binutils ( also ld )
|
# same as the rest of binutils ( also ld )
|
||||||
@@ -93,13 +97,20 @@ class CygwinCCompiler (UnixCCompiler):
|
|||||||
else:
|
else:
|
||||||
self.linker_dll = "dllwrap"
|
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.
|
# Hard-code GCC because that's what this is all about.
|
||||||
# XXX optimization, warnings etc. should be customizable.
|
# XXX optimization, warnings etc. should be customizable.
|
||||||
self.set_executables(compiler='gcc -mcygwin -O -Wall',
|
self.set_executables(compiler='gcc -mcygwin -O -Wall',
|
||||||
compiler_so='gcc -mcygwin -mdll -O -Wall',
|
compiler_so='gcc -mcygwin -mdll -O -Wall',
|
||||||
linker_exe='gcc -mcygwin',
|
linker_exe='gcc -mcygwin',
|
||||||
linker_so=('%s -mcygwin -mdll -static' %
|
linker_so=('%s -mcygwin %s' %
|
||||||
self.linker_dll))
|
(self.linker_dll, shared_option)))
|
||||||
|
|
||||||
# cygwin and mingw32 need different sets of libraries
|
# cygwin and mingw32 need different sets of libraries
|
||||||
if self.gcc_version == "2.91.57":
|
if self.gcc_version == "2.91.57":
|
||||||
@@ -268,6 +279,13 @@ class Mingw32CCompiler (CygwinCCompiler):
|
|||||||
|
|
||||||
CygwinCCompiler.__init__ (self, verbose, dry_run, force)
|
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,
|
# A real mingw32 doesn't need to specify a different entry point,
|
||||||
# but cygwin 2.91.57 in no-cygwin-mode needs it.
|
# but cygwin 2.91.57 in no-cygwin-mode needs it.
|
||||||
if self.gcc_version <= "2.91.57":
|
if self.gcc_version <= "2.91.57":
|
||||||
@@ -278,8 +296,9 @@ class Mingw32CCompiler (CygwinCCompiler):
|
|||||||
self.set_executables(compiler='gcc -mno-cygwin -O -Wall',
|
self.set_executables(compiler='gcc -mno-cygwin -O -Wall',
|
||||||
compiler_so='gcc -mno-cygwin -mdll -O -Wall',
|
compiler_so='gcc -mno-cygwin -mdll -O -Wall',
|
||||||
linker_exe='gcc -mno-cygwin',
|
linker_exe='gcc -mno-cygwin',
|
||||||
linker_so='%s -mno-cygwin -mdll -static %s'
|
linker_so='%s -mno-cygwin %s %s'
|
||||||
% (self.linker_dll, entry_point))
|
% (self.linker_dll, shared_option,
|
||||||
|
entry_point))
|
||||||
# Maybe we should also append -mthreads, but then the finished
|
# Maybe we should also append -mthreads, but then the finished
|
||||||
# dlls need another dll (mingwm10.dll see Mingw32 docs)
|
# dlls need another dll (mingwm10.dll see Mingw32 docs)
|
||||||
# (-mthreads: Support thread-safe exception handling on `Mingw32')
|
# (-mthreads: Support thread-safe exception handling on `Mingw32')
|
||||||
@@ -363,7 +382,7 @@ def get_versions():
|
|||||||
out = os.popen(gcc_exe + ' -dumpversion','r')
|
out = os.popen(gcc_exe + ' -dumpversion','r')
|
||||||
out_string = out.read()
|
out_string = out.read()
|
||||||
out.close()
|
out.close()
|
||||||
result = re.search('(\d+\.\d+\.\d+)',out_string)
|
result = re.search('(\d+\.\d+(\.\d+)*)',out_string)
|
||||||
if result:
|
if result:
|
||||||
gcc_version = StrictVersion(result.group(1))
|
gcc_version = StrictVersion(result.group(1))
|
||||||
else:
|
else:
|
||||||
@@ -375,7 +394,7 @@ def get_versions():
|
|||||||
out = os.popen(ld_exe + ' -v','r')
|
out = os.popen(ld_exe + ' -v','r')
|
||||||
out_string = out.read()
|
out_string = out.read()
|
||||||
out.close()
|
out.close()
|
||||||
result = re.search('(\d+\.\d+\.\d+)',out_string)
|
result = re.search('(\d+\.\d+(\.\d+)*)',out_string)
|
||||||
if result:
|
if result:
|
||||||
ld_version = StrictVersion(result.group(1))
|
ld_version = StrictVersion(result.group(1))
|
||||||
else:
|
else:
|
||||||
@@ -387,7 +406,7 @@ def get_versions():
|
|||||||
out = os.popen(dllwrap_exe + ' --version','r')
|
out = os.popen(dllwrap_exe + ' --version','r')
|
||||||
out_string = out.read()
|
out_string = out.read()
|
||||||
out.close()
|
out.close()
|
||||||
result = re.search(' (\d+\.\d+\.\d+)',out_string)
|
result = re.search(' (\d+\.\d+(\.\d+)*)',out_string)
|
||||||
if result:
|
if result:
|
||||||
dllwrap_version = StrictVersion(result.group(1))
|
dllwrap_version = StrictVersion(result.group(1))
|
||||||
else:
|
else:
|
||||||
|
@@ -205,6 +205,15 @@ class Distribution:
|
|||||||
for (opt, val) in cmd_options.items():
|
for (opt, val) in cmd_options.items():
|
||||||
opt_dict[opt] = ("setup script", val)
|
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
|
# Now work on the rest of the attributes. Any attribute that's
|
||||||
# not already defined is invalid!
|
# not already defined is invalid!
|
||||||
for (key,val) in attrs.items():
|
for (key,val) in attrs.items():
|
||||||
@@ -966,7 +975,7 @@ class DistributionMetadata:
|
|||||||
"maintainer", "maintainer_email", "url",
|
"maintainer", "maintainer_email", "url",
|
||||||
"license", "description", "long_description",
|
"license", "description", "long_description",
|
||||||
"keywords", "platforms", "fullname", "contact",
|
"keywords", "platforms", "fullname", "contact",
|
||||||
"contact_email", "licence", "classifiers",
|
"contact_email", "license", "classifiers",
|
||||||
"download_url")
|
"download_url")
|
||||||
|
|
||||||
def __init__ (self):
|
def __init__ (self):
|
||||||
|
@@ -53,9 +53,9 @@ def set_threshold(level):
|
|||||||
_global_log.threshold = level
|
_global_log.threshold = level
|
||||||
|
|
||||||
def set_verbosity(v):
|
def set_verbosity(v):
|
||||||
if v == 0:
|
if v <= 0:
|
||||||
set_threshold(WARN)
|
set_threshold(WARN)
|
||||||
if v == 1:
|
elif v == 1:
|
||||||
set_threshold(INFO)
|
set_threshold(INFO)
|
||||||
if v == 2:
|
elif v >= 2:
|
||||||
set_threshold(DEBUG)
|
set_threshold(DEBUG)
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
"""distutils.msvccompiler
|
"""distutils.msvccompiler
|
||||||
|
|
||||||
Contains MSVCCompiler, an implementation of the abstract CCompiler class
|
Contains MSVCCompiler, an implementation of the abstract CCompiler class
|
||||||
for the Microsoft Visual Studio."""
|
for the Microsoft Visual Studio.
|
||||||
|
"""
|
||||||
|
|
||||||
# Written by Perry Stoll
|
# Written by Perry Stoll
|
||||||
# hacked by Robin Becker and Thomas Heller to do a better job of
|
# hacked by Robin Becker and Thomas Heller to do a better job of
|
||||||
@@ -12,7 +13,6 @@ for the Microsoft Visual Studio."""
|
|||||||
__revision__ = "$Id$"
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
import sys, os, string
|
import sys, os, string
|
||||||
from types import *
|
|
||||||
from distutils.errors import \
|
from distutils.errors import \
|
||||||
DistutilsExecError, DistutilsPlatformError, \
|
DistutilsExecError, DistutilsPlatformError, \
|
||||||
CompileError, LibError, LinkError
|
CompileError, LibError, LinkError
|
||||||
@@ -45,128 +45,127 @@ except ImportError:
|
|||||||
RegError = win32api.error
|
RegError = win32api.error
|
||||||
|
|
||||||
except ImportError:
|
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
|
pass
|
||||||
|
|
||||||
if _can_read_reg:
|
if _can_read_reg:
|
||||||
HKEY_CLASSES_ROOT = hkey_mod.HKEY_CLASSES_ROOT
|
HKEYS = (hkey_mod.HKEY_USERS,
|
||||||
HKEY_LOCAL_MACHINE = hkey_mod.HKEY_LOCAL_MACHINE
|
hkey_mod.HKEY_CURRENT_USER,
|
||||||
HKEY_CURRENT_USER = hkey_mod.HKEY_CURRENT_USER
|
hkey_mod.HKEY_LOCAL_MACHINE,
|
||||||
HKEY_USERS = hkey_mod.HKEY_USERS
|
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:
|
try:
|
||||||
k = RegOpenKeyEx(base,K)
|
handle = RegOpenKeyEx(base, key)
|
||||||
|
except RegError:
|
||||||
|
return None
|
||||||
|
L = []
|
||||||
i = 0
|
i = 0
|
||||||
while 1:
|
while 1:
|
||||||
try:
|
try:
|
||||||
p = RegEnumKey(k,i)
|
k = RegEnumKey(handle, i)
|
||||||
if p[0] in '123456789' and p not in L:
|
|
||||||
L.append(p)
|
|
||||||
except RegError:
|
except RegError:
|
||||||
break
|
break
|
||||||
|
L.append(k)
|
||||||
i = i + 1
|
i = i + 1
|
||||||
except RegError:
|
|
||||||
pass
|
|
||||||
L.sort()
|
|
||||||
L.reverse()
|
|
||||||
return L
|
return L
|
||||||
|
|
||||||
# get_devstudio_versions ()
|
def read_values(base, key):
|
||||||
|
"""Return dict of registry keys and values.
|
||||||
|
|
||||||
|
All names are converted to lowercase.
|
||||||
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):
|
|
||||||
try:
|
try:
|
||||||
k = RegOpenKeyEx(base,K)
|
handle = RegOpenKeyEx(base, key)
|
||||||
|
except RegError:
|
||||||
|
return None
|
||||||
|
d = {}
|
||||||
i = 0
|
i = 0
|
||||||
while 1:
|
while 1:
|
||||||
try:
|
try:
|
||||||
(p,v,t) = RegEnumValue(k,i)
|
name, value, type = RegEnumValue(handle, i)
|
||||||
if string.upper(p) == path:
|
except RegError:
|
||||||
V = string.split(v,';')
|
break
|
||||||
for v in V:
|
name = name.lower()
|
||||||
if hasattr(v, "encode"):
|
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:
|
try:
|
||||||
v = v.encode("mbcs")
|
s = enc("mbcs")
|
||||||
except UnicodeError:
|
except UnicodeError:
|
||||||
pass
|
pass
|
||||||
if v == '' or v in L: continue
|
return s
|
||||||
L.append(v)
|
|
||||||
|
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
|
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:
|
except RegError:
|
||||||
break
|
continue
|
||||||
except RegError:
|
key = RegEnumKey(h, 0)
|
||||||
pass
|
d = read_values(base, r"%s\%s" % (p, key))
|
||||||
return L
|
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):
|
For Python 2.3 and up, the version number is included in
|
||||||
"""Try to find an MSVC executable program 'exe' (from version
|
sys.version. For earlier versions, assume the compiler is MSVC 6.
|
||||||
'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 p in get_msvc_paths ('path', version_number):
|
prefix = "MSC v."
|
||||||
fn = os.path.join (os.path.abspath(p), exe)
|
i = string.find(sys.version, prefix)
|
||||||
if os.path.isfile(fn):
|
if i == -1:
|
||||||
return fn
|
return 6
|
||||||
|
i = i + len(prefix)
|
||||||
# didn't find it; try existing path
|
s, rest = sys.version[i:].split(" ", 1)
|
||||||
for p in string.split (os.environ['Path'],';'):
|
majorVersion = int(s[:-2]) - 6
|
||||||
fn = os.path.join(os.path.abspath(p),exe)
|
minorVersion = int(s[2:3]) / 10.0
|
||||||
if os.path.isfile(fn):
|
# I don't think paths are affected by minor version in version 6
|
||||||
return fn
|
if majorVersion == 6:
|
||||||
|
minorVersion = 0
|
||||||
return exe # last desperate hope
|
if majorVersion >= 6:
|
||||||
|
return majorVersion + minorVersion
|
||||||
|
# else we don't know what version of the compiler this is
|
||||||
def set_path_env_var (name, version_number):
|
return None
|
||||||
"""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,';')
|
|
||||||
|
|
||||||
|
|
||||||
class MSVCCompiler (CCompiler) :
|
class MSVCCompiler (CCompiler) :
|
||||||
@@ -199,39 +198,37 @@ class MSVCCompiler (CCompiler) :
|
|||||||
static_lib_format = shared_lib_format = '%s%s'
|
static_lib_format = shared_lib_format = '%s%s'
|
||||||
exe_extension = '.exe'
|
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)
|
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:
|
if len (self.__paths) == 0:
|
||||||
version = versions[0] # highest version
|
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.cc = self.find_exe("cl.exe")
|
||||||
self.linker = find_exe("link.exe", version)
|
self.linker = self.find_exe("link.exe")
|
||||||
self.lib = find_exe("lib.exe", version)
|
self.lib = self.find_exe("lib.exe")
|
||||||
self.rc = find_exe("rc.exe", version) # resource compiler
|
self.rc = self.find_exe("rc.exe") # resource compiler
|
||||||
self.mc = find_exe("mc.exe", version) # message compiler
|
self.mc = self.find_exe("mc.exe") # message compiler
|
||||||
set_path_env_var ('lib', version)
|
self.set_path_env_var('lib')
|
||||||
set_path_env_var ('include', version)
|
self.set_path_env_var('include')
|
||||||
path=get_msvc_paths('path', version)
|
|
||||||
|
# extend the MSVC path with the current path
|
||||||
try:
|
try:
|
||||||
for p in string.split(os.environ['path'], ';'):
|
for p in string.split(os.environ['path'], ';'):
|
||||||
path.append(p)
|
self.__paths.append(p)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
os.environ['path'] = string.join(path,';')
|
os.environ['path'] = string.join(self.__paths, ';')
|
||||||
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"
|
|
||||||
|
|
||||||
self.preprocess_options = None
|
self.preprocess_options = None
|
||||||
self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
|
self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
|
||||||
@@ -500,4 +497,69 @@ class MSVCCompiler (CCompiler) :
|
|||||||
|
|
||||||
# find_library_file ()
|
# 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"
|
shared_lib_extension = ".so"
|
||||||
dylib_lib_extension = ".dylib"
|
dylib_lib_extension = ".dylib"
|
||||||
static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"
|
static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"
|
||||||
|
if sys.platform == "cygwin":
|
||||||
|
exe_extension = ".exe"
|
||||||
|
|
||||||
def preprocess(self, source,
|
def preprocess(self, source,
|
||||||
output_file=None, macros=None, include_dirs=None,
|
output_file=None, macros=None, include_dirs=None,
|
||||||
@@ -201,6 +203,8 @@ class UnixCCompiler(CCompiler):
|
|||||||
if sys.platform[:6] == "darwin":
|
if sys.platform[:6] == "darwin":
|
||||||
# MacOSX's linker doesn't understand the -R flag at all
|
# MacOSX's linker doesn't understand the -R flag at all
|
||||||
return "-L" + dir
|
return "-L" + dir
|
||||||
|
elif sys.platform[:5] == "hp-ux":
|
||||||
|
return "+s -L" + dir
|
||||||
elif compiler[:3] == "gcc" or compiler[:3] == "g++":
|
elif compiler[:3] == "gcc" or compiler[:3] == "g++":
|
||||||
return "-Wl,-R" + dir
|
return "-Wl,-R" + dir
|
||||||
else:
|
else:
|
||||||
|
Reference in New Issue
Block a user