2000-05-30 22:05:35 -03:00
|
|
|
"""distutils.extension
|
|
|
|
|
|
|
|
Provides the Extension class, used to describe C/C++ extension
|
|
|
|
modules in setup scripts."""
|
|
|
|
|
|
|
|
__revision__ = "$Id$"
|
|
|
|
|
2002-11-20 12:10:29 -04:00
|
|
|
import os, string, sys
|
2000-05-30 22:05:35 -03:00
|
|
|
from types import *
|
|
|
|
|
2002-11-13 16:54:21 -04:00
|
|
|
try:
|
|
|
|
import warnings
|
|
|
|
except ImportError:
|
|
|
|
warnings = None
|
2000-05-30 22:05:35 -03:00
|
|
|
|
|
|
|
# This class is really only used by the "build_ext" command, so it might
|
|
|
|
# make sense to put it in distutils.command.build_ext. However, that
|
|
|
|
# module is already big enough, and I want to make this class a bit more
|
|
|
|
# complex to simplify some common cases ("foo" module in "foo.c") and do
|
|
|
|
# better error-checking ("foo.c" actually exists).
|
2001-12-06 16:51:35 -04:00
|
|
|
#
|
2000-05-30 22:05:35 -03:00
|
|
|
# Also, putting this in build_ext.py means every setup script would have to
|
|
|
|
# import that large-ish module (indirectly, through distutils.core) in
|
|
|
|
# order to do anything.
|
|
|
|
|
|
|
|
class Extension:
|
|
|
|
"""Just a collection of attributes that describes an extension
|
|
|
|
module and everything needed to build it (hopefully in a portable
|
2000-08-12 21:38:58 -03:00
|
|
|
way, but there are hooks that let you be as unportable as you need).
|
2000-05-30 22:05:35 -03:00
|
|
|
|
|
|
|
Instance attributes:
|
|
|
|
name : string
|
|
|
|
the full name of the extension, including any packages -- ie.
|
|
|
|
*not* a filename or pathname, but Python dotted name
|
|
|
|
sources : [string]
|
2000-06-23 21:18:24 -03:00
|
|
|
list of source filenames, relative to the distribution root
|
|
|
|
(where the setup script lives), in Unix form (slash-separated)
|
|
|
|
for portability. Source files may be C, C++, SWIG (.i),
|
|
|
|
platform-specific resource files, or whatever else is recognized
|
|
|
|
by the "build_ext" command as source for a Python extension.
|
2000-05-30 22:05:35 -03:00
|
|
|
include_dirs : [string]
|
|
|
|
list of directories to search for C/C++ header files (in Unix
|
|
|
|
form for portability)
|
|
|
|
define_macros : [(name : string, value : string|None)]
|
|
|
|
list of macros to define; each macro is defined using a 2-tuple,
|
|
|
|
where 'value' is either the string to define it to or None to
|
|
|
|
define it without a particular value (equivalent of "#define
|
|
|
|
FOO" in source or -DFOO on Unix C compiler command line)
|
|
|
|
undef_macros : [string]
|
|
|
|
list of macros to undefine explicitly
|
|
|
|
library_dirs : [string]
|
|
|
|
list of directories to search for C/C++ libraries at link time
|
|
|
|
libraries : [string]
|
|
|
|
list of library names (not filenames or paths) to link against
|
|
|
|
runtime_library_dirs : [string]
|
|
|
|
list of directories to search for C/C++ libraries at run time
|
|
|
|
(for shared extensions, this is when the extension is loaded)
|
|
|
|
extra_objects : [string]
|
|
|
|
list of extra files to link with (eg. object files not implied
|
|
|
|
by 'sources', static library that must be explicitly specified,
|
|
|
|
binary resource files, etc.)
|
|
|
|
extra_compile_args : [string]
|
|
|
|
any extra platform- and compiler-specific information to use
|
|
|
|
when compiling the source files in 'sources'. For platforms and
|
|
|
|
compilers where "command line" makes sense, this is typically a
|
|
|
|
list of command-line arguments, but for other platforms it could
|
|
|
|
be anything.
|
|
|
|
extra_link_args : [string]
|
|
|
|
any extra platform- and compiler-specific information to use
|
|
|
|
when linking object files together to create the extension (or
|
|
|
|
to create a new static Python interpreter). Similar
|
|
|
|
interpretation as for 'extra_compile_args'.
|
|
|
|
export_symbols : [string]
|
|
|
|
list of symbols to be exported from a shared extension. Not
|
|
|
|
used on all platforms, and not generally necessary for Python
|
|
|
|
extensions, which typically export exactly one symbol: "init" +
|
|
|
|
extension_name.
|
2002-06-12 17:08:56 -03:00
|
|
|
depends : [string]
|
|
|
|
list of files that the extension depends on
|
This patch fixes the following bugs:
[#413582] g++ must be called for c++ extensions
[#454030] distutils cannot link C++ code with GCC
topdir = "Lib/distutils"
* bcppcompiler.py
(BCPPCompiler.create_static_lib): Fixed prototype, removing extra_preargs
and extra_postargs parameters. Included target_lang parameter.
(BCPPCompiler.link): Included target_lang parameter.
* msvccompiler.py
(MSVCCompiler.create_static_lib): Fixed prototype, removing extra_preargs
and extra_postargs parameters. Included target_lang parameter.
(MSVCCompiler.link): Included target_lang parameter.
* ccompiler.py
(CCompiler): New language_map and language_order attributes, used by
CCompiler.detect_language().
(CCompiler.detect_language): New method, will return the language of
a given source, or list of sources. Individual source language is
detected using the language_map dict. When mixed sources are used,
language_order will stablish the language precedence.
(CCompiler.create_static_lib, CCompiler.link, CCompiler.link_executable,
CCompiler.link_shared_object, CCompiler.link_shared_lib):
Inlcuded target_lang parameter.
* cygwinccompiler.py
(CygwinCCompiler.link): Included target_lang parameter.
* emxccompiler.py
(EMXCCompiler.link): Included target_lang parameter.
* mwerkscompiler.py
(MWerksCompiler.link): Included target_lang parameter.
* extension.py
(Extension.__init__): New 'language' parameter/attribute, initialized
to None by default. If provided will overlap the automatic detection
made by CCompiler.detect_language(), in build_ext command.
* sysconfig.py
(customize_compiler): Check Makefile for CXX option, and also the
environment variable CXX. Use the resulting value in the 'compiler_cxx'
parameter of compiler.set_executables().
* unixccompiler.py
(UnixCCompiler): Included 'compiler_cxx' in executables dict, defaulting
to 'cc'.
(UnixCCompiler.create_static_lib): Included target_lang parameter.
(UnixCCompiler.link): Included target_lang parameter, and made
linker command use compiler_cxx, if target_lang is 'c++'.
* command/build_ext.py
(build_ext.build_extension): Pass new ext.language attribute
to compiler.link_shared_object()'s target_lang parameter. If
ext.language is not provided, detect language using
compiler.detect_language(sources) instead.
* command/config.py
(config._link): Pass already available lang parameter as target_lang
parameter of compiler.link_executable().
2002-11-05 12:12:02 -04:00
|
|
|
language : string
|
|
|
|
extension language (i.e. "c", "c++", "objc"). Will be detected
|
|
|
|
from the source extensions if not provided.
|
2000-05-30 22:05:35 -03:00
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__ (self, name, sources,
|
|
|
|
include_dirs=None,
|
|
|
|
define_macros=None,
|
|
|
|
undef_macros=None,
|
|
|
|
library_dirs=None,
|
|
|
|
libraries=None,
|
|
|
|
runtime_library_dirs=None,
|
|
|
|
extra_objects=None,
|
|
|
|
extra_compile_args=None,
|
|
|
|
extra_link_args=None,
|
|
|
|
export_symbols=None,
|
2002-06-12 17:08:56 -03:00
|
|
|
depends=None,
|
This patch fixes the following bugs:
[#413582] g++ must be called for c++ extensions
[#454030] distutils cannot link C++ code with GCC
topdir = "Lib/distutils"
* bcppcompiler.py
(BCPPCompiler.create_static_lib): Fixed prototype, removing extra_preargs
and extra_postargs parameters. Included target_lang parameter.
(BCPPCompiler.link): Included target_lang parameter.
* msvccompiler.py
(MSVCCompiler.create_static_lib): Fixed prototype, removing extra_preargs
and extra_postargs parameters. Included target_lang parameter.
(MSVCCompiler.link): Included target_lang parameter.
* ccompiler.py
(CCompiler): New language_map and language_order attributes, used by
CCompiler.detect_language().
(CCompiler.detect_language): New method, will return the language of
a given source, or list of sources. Individual source language is
detected using the language_map dict. When mixed sources are used,
language_order will stablish the language precedence.
(CCompiler.create_static_lib, CCompiler.link, CCompiler.link_executable,
CCompiler.link_shared_object, CCompiler.link_shared_lib):
Inlcuded target_lang parameter.
* cygwinccompiler.py
(CygwinCCompiler.link): Included target_lang parameter.
* emxccompiler.py
(EMXCCompiler.link): Included target_lang parameter.
* mwerkscompiler.py
(MWerksCompiler.link): Included target_lang parameter.
* extension.py
(Extension.__init__): New 'language' parameter/attribute, initialized
to None by default. If provided will overlap the automatic detection
made by CCompiler.detect_language(), in build_ext command.
* sysconfig.py
(customize_compiler): Check Makefile for CXX option, and also the
environment variable CXX. Use the resulting value in the 'compiler_cxx'
parameter of compiler.set_executables().
* unixccompiler.py
(UnixCCompiler): Included 'compiler_cxx' in executables dict, defaulting
to 'cc'.
(UnixCCompiler.create_static_lib): Included target_lang parameter.
(UnixCCompiler.link): Included target_lang parameter, and made
linker command use compiler_cxx, if target_lang is 'c++'.
* command/build_ext.py
(build_ext.build_extension): Pass new ext.language attribute
to compiler.link_shared_object()'s target_lang parameter. If
ext.language is not provided, detect language using
compiler.detect_language(sources) instead.
* command/config.py
(config._link): Pass already available lang parameter as target_lang
parameter of compiler.link_executable().
2002-11-05 12:12:02 -04:00
|
|
|
language=None,
|
2002-11-13 16:54:21 -04:00
|
|
|
**kw # To catch unknown keywords
|
2000-05-30 22:05:35 -03:00
|
|
|
):
|
|
|
|
assert type(name) is StringType, "'name' must be a string"
|
|
|
|
assert (type(sources) is ListType and
|
|
|
|
map(type, sources) == [StringType]*len(sources)), \
|
2000-09-16 21:45:18 -03:00
|
|
|
"'sources' must be a list of strings"
|
2000-05-30 22:05:35 -03:00
|
|
|
|
|
|
|
self.name = name
|
|
|
|
self.sources = sources
|
|
|
|
self.include_dirs = include_dirs or []
|
|
|
|
self.define_macros = define_macros or []
|
|
|
|
self.undef_macros = undef_macros or []
|
|
|
|
self.library_dirs = library_dirs or []
|
|
|
|
self.libraries = libraries or []
|
|
|
|
self.runtime_library_dirs = runtime_library_dirs or []
|
|
|
|
self.extra_objects = extra_objects or []
|
|
|
|
self.extra_compile_args = extra_compile_args or []
|
|
|
|
self.extra_link_args = extra_link_args or []
|
2000-08-12 21:41:40 -03:00
|
|
|
self.export_symbols = export_symbols or []
|
2002-06-12 17:08:56 -03:00
|
|
|
self.depends = depends or []
|
This patch fixes the following bugs:
[#413582] g++ must be called for c++ extensions
[#454030] distutils cannot link C++ code with GCC
topdir = "Lib/distutils"
* bcppcompiler.py
(BCPPCompiler.create_static_lib): Fixed prototype, removing extra_preargs
and extra_postargs parameters. Included target_lang parameter.
(BCPPCompiler.link): Included target_lang parameter.
* msvccompiler.py
(MSVCCompiler.create_static_lib): Fixed prototype, removing extra_preargs
and extra_postargs parameters. Included target_lang parameter.
(MSVCCompiler.link): Included target_lang parameter.
* ccompiler.py
(CCompiler): New language_map and language_order attributes, used by
CCompiler.detect_language().
(CCompiler.detect_language): New method, will return the language of
a given source, or list of sources. Individual source language is
detected using the language_map dict. When mixed sources are used,
language_order will stablish the language precedence.
(CCompiler.create_static_lib, CCompiler.link, CCompiler.link_executable,
CCompiler.link_shared_object, CCompiler.link_shared_lib):
Inlcuded target_lang parameter.
* cygwinccompiler.py
(CygwinCCompiler.link): Included target_lang parameter.
* emxccompiler.py
(EMXCCompiler.link): Included target_lang parameter.
* mwerkscompiler.py
(MWerksCompiler.link): Included target_lang parameter.
* extension.py
(Extension.__init__): New 'language' parameter/attribute, initialized
to None by default. If provided will overlap the automatic detection
made by CCompiler.detect_language(), in build_ext command.
* sysconfig.py
(customize_compiler): Check Makefile for CXX option, and also the
environment variable CXX. Use the resulting value in the 'compiler_cxx'
parameter of compiler.set_executables().
* unixccompiler.py
(UnixCCompiler): Included 'compiler_cxx' in executables dict, defaulting
to 'cc'.
(UnixCCompiler.create_static_lib): Included target_lang parameter.
(UnixCCompiler.link): Included target_lang parameter, and made
linker command use compiler_cxx, if target_lang is 'c++'.
* command/build_ext.py
(build_ext.build_extension): Pass new ext.language attribute
to compiler.link_shared_object()'s target_lang parameter. If
ext.language is not provided, detect language using
compiler.detect_language(sources) instead.
* command/config.py
(config._link): Pass already available lang parameter as target_lang
parameter of compiler.link_executable().
2002-11-05 12:12:02 -04:00
|
|
|
self.language = language
|
2000-05-30 22:05:35 -03:00
|
|
|
|
2002-11-13 16:54:21 -04:00
|
|
|
# If there are unknown keyword options, warn about them
|
|
|
|
if len(kw):
|
|
|
|
L = kw.keys() ; L.sort()
|
|
|
|
L = map(repr, L)
|
|
|
|
msg = "Unknown Extension options: " + string.join(L, ', ')
|
|
|
|
if warnings is not None:
|
|
|
|
warnings.warn(msg)
|
|
|
|
else:
|
|
|
|
sys.stderr.write(msg + '\n')
|
2000-05-30 22:05:35 -03:00
|
|
|
# class Extension
|
2000-09-16 21:45:18 -03:00
|
|
|
|
|
|
|
|
|
|
|
def read_setup_file (filename):
|
|
|
|
from distutils.sysconfig import \
|
|
|
|
parse_makefile, expand_makefile_vars, _variable_rx
|
|
|
|
from distutils.text_file import TextFile
|
|
|
|
from distutils.util import split_quoted
|
|
|
|
|
|
|
|
# First pass over the file to gather "VAR = VALUE" assignments.
|
|
|
|
vars = parse_makefile(filename)
|
|
|
|
|
|
|
|
# Second pass to gobble up the real content: lines of the form
|
|
|
|
# <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...]
|
|
|
|
file = TextFile(filename,
|
|
|
|
strip_comments=1, skip_blanks=1, join_lines=1,
|
|
|
|
lstrip_ws=1, rstrip_ws=1)
|
|
|
|
extensions = []
|
|
|
|
|
|
|
|
while 1:
|
|
|
|
line = file.readline()
|
|
|
|
if line is None: # eof
|
|
|
|
break
|
|
|
|
if _variable_rx.match(line): # VAR=VALUE, handled in first pass
|
|
|
|
continue
|
|
|
|
|
|
|
|
if line[0] == line[-1] == "*":
|
|
|
|
file.warn("'%s' lines not handled yet" % line)
|
|
|
|
continue
|
|
|
|
|
|
|
|
#print "original line: " + line
|
|
|
|
line = expand_makefile_vars(line, vars)
|
|
|
|
words = split_quoted(line)
|
|
|
|
#print "expanded line: " + line
|
|
|
|
|
|
|
|
# NB. this parses a slightly different syntax than the old
|
|
|
|
# makesetup script: here, there must be exactly one extension per
|
|
|
|
# line, and it must be the first word of the line. I have no idea
|
|
|
|
# why the old syntax supported multiple extensions per line, as
|
|
|
|
# they all wind up being the same.
|
|
|
|
|
|
|
|
module = words[0]
|
|
|
|
ext = Extension(module, [])
|
|
|
|
append_next_word = None
|
|
|
|
|
|
|
|
for word in words[1:]:
|
|
|
|
if append_next_word is not None:
|
|
|
|
append_next_word.append(word)
|
|
|
|
append_next_word = None
|
|
|
|
continue
|
|
|
|
|
|
|
|
suffix = os.path.splitext(word)[1]
|
|
|
|
switch = word[0:2] ; value = word[2:]
|
|
|
|
|
2001-12-21 11:34:17 -04:00
|
|
|
if suffix in (".c", ".cc", ".cpp", ".cxx", ".c++", ".m", ".mm"):
|
2000-09-16 21:45:18 -03:00
|
|
|
# hmm, should we do something about C vs. C++ sources?
|
|
|
|
# or leave it up to the CCompiler implementation to
|
|
|
|
# worry about?
|
|
|
|
ext.sources.append(word)
|
|
|
|
elif switch == "-I":
|
|
|
|
ext.include_dirs.append(value)
|
|
|
|
elif switch == "-D":
|
2001-03-21 23:48:31 -04:00
|
|
|
equals = string.find(value, "=")
|
2000-09-16 21:45:18 -03:00
|
|
|
if equals == -1: # bare "-DFOO" -- no value
|
|
|
|
ext.define_macros.append((value, None))
|
|
|
|
else: # "-DFOO=blah"
|
|
|
|
ext.define_macros.append((value[0:equals],
|
|
|
|
value[equals+2:]))
|
|
|
|
elif switch == "-U":
|
|
|
|
ext.undef_macros.append(value)
|
|
|
|
elif switch == "-C": # only here 'cause makesetup has it!
|
|
|
|
ext.extra_compile_args.append(word)
|
|
|
|
elif switch == "-l":
|
|
|
|
ext.libraries.append(value)
|
|
|
|
elif switch == "-L":
|
|
|
|
ext.library_dirs.append(value)
|
|
|
|
elif switch == "-R":
|
|
|
|
ext.runtime_library_dirs.append(value)
|
|
|
|
elif word == "-rpath":
|
|
|
|
append_next_word = ext.runtime_library_dirs
|
|
|
|
elif word == "-Xlinker":
|
|
|
|
append_next_word = ext.extra_link_args
|
2002-03-29 14:00:19 -04:00
|
|
|
elif word == "-Xcompiler":
|
|
|
|
append_next_word = ext.extra_compile_args
|
2000-09-16 21:45:18 -03:00
|
|
|
elif switch == "-u":
|
|
|
|
ext.extra_link_args.append(word)
|
|
|
|
if not value:
|
|
|
|
append_next_word = ext.extra_link_args
|
2002-11-27 09:45:26 -04:00
|
|
|
elif suffix in (".a", ".so", ".sl", ".o", ".dylib"):
|
2000-09-16 21:45:18 -03:00
|
|
|
# NB. a really faithful emulation of makesetup would
|
|
|
|
# append a .o file to extra_objects only if it
|
|
|
|
# had a slash in it; otherwise, it would s/.o/.c/
|
|
|
|
# and append it to sources. Hmmmm.
|
|
|
|
ext.extra_objects.append(word)
|
|
|
|
else:
|
|
|
|
file.warn("unrecognized argument '%s'" % word)
|
|
|
|
|
|
|
|
extensions.append(ext)
|
|
|
|
|
|
|
|
#print "module:", module
|
|
|
|
#print "source files:", source_files
|
|
|
|
#print "cpp args:", cpp_args
|
|
|
|
#print "lib args:", library_args
|
|
|
|
|
|
|
|
#extensions[module] = { 'sources': source_files,
|
|
|
|
# 'cpp_args': cpp_args,
|
|
|
|
# 'lib_args': library_args }
|
2001-12-06 16:51:35 -04:00
|
|
|
|
2000-09-16 21:45:18 -03:00
|
|
|
return extensions
|
|
|
|
|
|
|
|
# read_setup_file ()
|