diff options
Diffstat (limited to 'Lib/distutils/command/build_ext.py')
| -rw-r--r-- | Lib/distutils/command/build_ext.py | 129 |
1 files changed, 60 insertions, 69 deletions
diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py index 923197b..34b61bd 100644 --- a/Lib/distutils/command/build_ext.py +++ b/Lib/distutils/command/build_ext.py @@ -4,13 +4,7 @@ Implements the Distutils 'build_ext' command, for building extension modules (currently limited to C extensions, should accommodate C++ extensions ASAP).""" -# This module should be kept compatible with Python 2.1. - -__revision__ = "$Id$" - -import sys, os, string, re -from types import * -from site import USER_BASE, USER_SITE +import sys, os, re from distutils.core import Command from distutils.errors import * from distutils.sysconfig import customize_compiler, get_python_version @@ -19,6 +13,14 @@ from distutils.extension import Extension from distutils.util import get_platform from distutils import log +# this keeps compatibility from 2.3 to 2.5 +if sys.version < "2.6": + USER_BASE = None + HAS_USER_SITE = False +else: + from site import USER_BASE + HAS_USER_SITE = True + if os.name == 'nt': from distutils.msvccompiler import get_build_version MSVC_VERSION = int(get_build_version()) @@ -34,7 +36,7 @@ def show_compilers (): show_compilers() -class build_ext (Command): +class build_ext(Command): description = "build C/C++ extensions (compile/link to build directory)" @@ -94,18 +96,21 @@ class build_ext (Command): "list of SWIG command line options"), ('swig=', None, "path to the SWIG executable"), - ('user', None, - "add user include, library and rpath"), ] - boolean_options = ['inplace', 'debug', 'force', 'swig-cpp', 'user'] + boolean_options = ['inplace', 'debug', 'force', 'swig-cpp'] + + if HAS_USER_SITE: + user_options.append(('user', None, + "add user include, library and rpath")) + boolean_options.append('user') help_options = [ ('help-compiler', None, "list available compilers", show_compilers), ] - def initialize_options (self): + def initialize_options(self): self.extensions = None self.build_lib = None self.plat_name = None @@ -168,13 +173,13 @@ class build_ext (Command): self.libraries = [] if self.library_dirs is None: self.library_dirs = [] - elif type(self.library_dirs) is StringType: - self.library_dirs = string.split(self.library_dirs, os.pathsep) + elif isinstance(self.library_dirs, str): + self.library_dirs = self.library_dirs.split(os.pathsep) if self.rpath is None: self.rpath = [] - elif type(self.rpath) is StringType: - self.rpath = string.split(self.rpath, os.pathsep) + elif isinstance(self.rpath, str): + self.rpath = self.rpath.split(os.pathsep) # for extensions under windows use different directories # for Release and Debug builds. @@ -251,7 +256,7 @@ class build_ext (Command): if self.define: defines = self.define.split(',') - self.define = map(lambda symbol: (symbol, '1'), defines) + self.define = [(symbol, '1') for symbol in defines] # The option for macros to undefine is also a string from the # option parsing, but has to be a list. Multiple symbols can also @@ -349,8 +354,8 @@ class build_ext (Command): just returns otherwise. """ if not isinstance(extensions, list): - raise DistutilsSetupError, \ - "'ext_modules' option must be a list of Extension instances" + raise DistutilsSetupError( + "'ext_modules' option must be a list of Extension instances") for i, ext in enumerate(extensions): if isinstance(ext, Extension): @@ -358,8 +363,8 @@ class build_ext (Command): # by Extension constructor) if not isinstance(ext, tuple) or len(ext) != 2: - raise DistutilsSetupError, \ - ("each element of 'ext_modules' option must be an " + raise DistutilsSetupError( + "each element of 'ext_modules' option must be an " "Extension instance or 2-tuple") ext_name, build_info = ext @@ -370,13 +375,13 @@ class build_ext (Command): if not (isinstance(ext_name, str) and extension_name_re.match(ext_name)): - raise DistutilsSetupError, \ - ("first element of each tuple in 'ext_modules' " + raise DistutilsSetupError( + "first element of each tuple in 'ext_modules' " "must be the extension name (a string)") if not isinstance(build_info, dict): - raise DistutilsSetupError, \ - ("second element of each tuple in 'ext_modules' " + raise DistutilsSetupError( + "second element of each tuple in 'ext_modules' " "must be a dictionary (build info)") # OK, the (ext_name, build_info) dict is type-safe: convert it @@ -406,9 +411,9 @@ class build_ext (Command): ext.undef_macros = [] for macro in macros: if not (isinstance(macro, tuple) and len(macro) in (1, 2)): - raise DistutilsSetupError, \ - ("'macros' element of build info dict " - "must be 1- or 2-tuple") + raise DistutilsSetupError( + "'macros' element of build info dict " + "must be 1- or 2-tuple") if len(macro) == 1: ext.undef_macros.append(macro[0]) elif len(macro) == 2: @@ -423,7 +428,6 @@ class build_ext (Command): # Wouldn't it be neat if we knew the names of header files too... for ext in self.extensions: filenames.extend(ext.sources) - return filenames def get_outputs(self): @@ -445,15 +449,21 @@ class build_ext (Command): self.check_extensions_list(self.extensions) for ext in self.extensions: - self.build_extension(ext) + try: + self.build_extension(ext) + except (CCompilerError, DistutilsError, CompileError) as e: + if not ext.optional: + raise + self.warn('building extension "%s" failed: %s' % + (ext.name, e)) def build_extension(self, ext): sources = ext.sources - if sources is None or type(sources) not in (ListType, TupleType): - raise DistutilsSetupError, \ - ("in 'ext_modules' option (extension '%s'), " + - "'sources' must be present and must be " + - "a list of source filenames") % ext.name + if sources is None or not isinstance(sources, (list, tuple)): + raise DistutilsSetupError( + "in 'ext_modules' option (extension '%s'), " + "'sources' must be present and must be " + "a list of source filenames" % ext.name) sources = list(sources) ext_path = self.get_ext_fullpath(ext.name) @@ -529,15 +539,12 @@ class build_ext (Command): build_temp=self.build_temp, target_lang=language) - - def swig_sources (self, sources, extension): - + def swig_sources(self, sources, extension): """Walk the list of source files in 'sources', looking for SWIG interface (.i) files. Run SWIG on all that are found, and return a modified 'sources' list with SWIG source files replaced by the generated C (or C++) files. """ - new_sources = [] swig_sources = [] swig_targets = {} @@ -586,18 +593,14 @@ class build_ext (Command): return new_sources - # swig_sources () - - def find_swig (self): + def find_swig(self): """Return the name of the SWIG executable. On Unix, this is just "swig" -- it should be in the PATH. Tries a bit harder on Windows. """ - if os.name == "posix": return "swig" elif os.name == "nt": - # Look for SWIG in its standard installation directory on # Windows (or so I presume!). If we find it there, great; # if not, act like Unix and assume it's in the PATH. @@ -607,17 +610,13 @@ class build_ext (Command): return fn else: return "swig.exe" - elif os.name == "os2": # assume swig available in the PATH. return "swig.exe" - else: - raise DistutilsPlatformError, \ - ("I don't know how to find (much less run) SWIG " - "on platform '%s'") % os.name - - # find_swig () + raise DistutilsPlatformError( + "I don't know how to find (much less run) SWIG " + "on platform '%s'" % os.name) # -- Name generators ----------------------------------------------- # (extension names, filenames, whatever) @@ -627,14 +626,9 @@ class build_ext (Command): The file is located in `build_lib` or directly in the package (inplace option). """ - # makes sure the extension name is only using dots - all_dots = string.maketrans('/'+os.sep, '..') - ext_name = ext_name.translate(all_dots) - fullname = self.get_ext_fullname(ext_name) modpath = fullname.split('.') - filename = self.get_ext_filename(ext_name) - filename = os.path.split(filename)[-1] + filename = self.get_ext_filename(modpath[-1]) if not self.inplace: # no further work needed @@ -668,7 +662,7 @@ class build_ext (Command): "foo\bar.pyd"). """ from distutils.sysconfig import get_config_var - ext_path = string.split(ext_name, '.') + ext_path = ext_name.split('.') # OS/2 has an 8 character module (extension) limit :-( if os.name == "os2": ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8] @@ -678,18 +672,18 @@ class build_ext (Command): return os.path.join(*ext_path) + '_d' + so_ext return os.path.join(*ext_path) + so_ext - def get_export_symbols (self, ext): + def get_export_symbols(self, ext): """Return the list of symbols that a shared extension has to export. This either uses 'ext.export_symbols' or, if it's not - provided, "init" + module_name. Only relevant on Windows, where - the .pyd file (DLL) must export the module "init" function. + provided, "PyInit_" + module_name. Only relevant on Windows, where + the .pyd file (DLL) must export the module "PyInit_" function. """ - initfunc_name = "init" + ext.name.split('.')[-1] + initfunc_name = "PyInit_" + ext.name.split('.')[-1] if initfunc_name not in ext.export_symbols: ext.export_symbols.append(initfunc_name) return ext.export_symbols - def get_libraries (self, ext): + def get_libraries(self, ext): """Return the list of libraries to link against when building a shared extension. On most platforms, this is just 'ext.libraries'; on Windows and OS/2, we add the Python library (eg. python20.dll). @@ -748,7 +742,6 @@ class build_ext (Command): # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib, "m"] + extra - elif sys.platform == 'darwin': # Don't use the default code below return ext.libraries @@ -758,11 +751,9 @@ class build_ext (Command): else: from distutils import sysconfig if sysconfig.get_config_var('Py_ENABLE_SHARED'): - template = "python%d.%d" - pythonlib = (template % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + pythonlib = 'python{}.{}{}'.format( + sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff, + sys.abiflags) return ext.libraries + [pythonlib] else: return ext.libraries - -# class build_ext |
