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."""
|
||||
|
||||
modules = []
|
||||
if self.py_modules:
|
||||
modules = self.find_modules()
|
||||
else:
|
||||
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,129 +45,128 @@ 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'
|
||||
try:
|
||||
handle = RegOpenKeyEx(base, key)
|
||||
except RegError:
|
||||
return None
|
||||
L = []
|
||||
for base in (HKEY_CLASSES_ROOT,
|
||||
HKEY_LOCAL_MACHINE,
|
||||
HKEY_CURRENT_USER,
|
||||
HKEY_USERS):
|
||||
i = 0
|
||||
while 1:
|
||||
try:
|
||||
k = RegOpenKeyEx(base,K)
|
||||
i = 0
|
||||
while 1:
|
||||
try:
|
||||
p = RegEnumKey(k,i)
|
||||
if p[0] in '123456789' and p not in L:
|
||||
L.append(p)
|
||||
except RegError:
|
||||
break
|
||||
i = i + 1
|
||||
k = RegEnumKey(handle, i)
|
||||
except RegError:
|
||||
pass
|
||||
L.sort()
|
||||
L.reverse()
|
||||
break
|
||||
L.append(k)
|
||||
i = i + 1
|
||||
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:
|
||||
handle = RegOpenKeyEx(base, key)
|
||||
except RegError:
|
||||
return None
|
||||
d = {}
|
||||
i = 0
|
||||
while 1:
|
||||
try:
|
||||
k = RegOpenKeyEx(base,K)
|
||||
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"):
|
||||
try:
|
||||
v = v.encode("mbcs")
|
||||
except UnicodeError:
|
||||
pass
|
||||
if v == '' or v in L: continue
|
||||
L.append(v)
|
||||
break
|
||||
i = i + 1
|
||||
except RegError:
|
||||
break
|
||||
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:
|
||||
s = enc("mbcs")
|
||||
except UnicodeError:
|
||||
pass
|
||||
return L
|
||||
return s
|
||||
|
||||
# get_msvc_paths()
|
||||
class MacroExpander:
|
||||
|
||||
def __init__(self, version):
|
||||
self.macros = {}
|
||||
self.load_macros(version)
|
||||
|
||||
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'."""
|
||||
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
|
||||
|
||||
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")
|
||||
|
||||
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
|
||||
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"]
|
||||
|
||||
# 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
|
||||
def sub(self, s):
|
||||
for k, v in self.macros.items():
|
||||
s = string.replace(s, k, v)
|
||||
return s
|
||||
|
||||
return exe # last desperate hope
|
||||
def get_build_version():
|
||||
"""Return the version of MSVC that was used to build Python.
|
||||
|
||||
For Python 2.3 and up, the version number is included in
|
||||
sys.version. For earlier versions, assume the compiler is MSVC 6.
|
||||
"""
|
||||
|
||||
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) :
|
||||
"""Concrete class that implements an interface to Microsoft Visual C++,
|
||||
@@ -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 ()
|
||||
|
||||
if versions:
|
||||
version = versions[0] # highest 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)
|
||||
try:
|
||||
for p in string.split(os.environ['path'],';'):
|
||||
path.append(p)
|
||||
except KeyError:
|
||||
pass
|
||||
os.environ['path'] = string.join(path,';')
|
||||
self.__version = get_build_version()
|
||||
if self.__version >= 7:
|
||||
self.__root = r"Software\Microsoft\VisualStudio"
|
||||
self.__macros = MacroExpander(self.__version)
|
||||
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.__root = r"Software\Microsoft\Devstudio"
|
||||
self.__paths = self.get_msvc_paths("path")
|
||||
|
||||
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 = 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'], ';'):
|
||||
self.__paths.append(p)
|
||||
except KeyError:
|
||||
pass
|
||||
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,8 +203,10 @@ 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
|
||||
return "-Wl,-R" + dir
|
||||
else:
|
||||
return "-R" + dir
|
||||
|
||||
|
Reference in New Issue
Block a user