2000-05-31 09:05:35 +08:00
|
|
|
"""distutils.extension
|
|
|
|
|
|
|
|
Provides the Extension class, used to describe C/C++ extension
|
|
|
|
modules in setup scripts."""
|
|
|
|
|
2009-06-03 19:17:15 +08:00
|
|
|
import os
|
2021-04-23 20:02:41 +08:00
|
|
|
import re
|
2009-06-03 19:17:15 +08:00
|
|
|
import warnings
|
2000-05-31 09:05:35 +08: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-07 04:51:35 +08:00
|
|
|
#
|
2000-05-31 09:05:35 +08: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-13 08:38:58 +08:00
|
|
|
way, but there are hooks that let you be as unportable as you need).
|
2000-05-31 09:05:35 +08: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-24 08:18:24 +08: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-31 09:05:35 +08: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.
|
2004-10-14 18:02:08 +08:00
|
|
|
swig_opts : [string]
|
|
|
|
any extra options to pass to SWIG if a source file has the .i
|
|
|
|
extension.
|
2002-06-13 04:08:56 +08: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-06 00:12:02 +08:00
|
|
|
language : string
|
|
|
|
extension language (i.e. "c", "c++", "objc"). Will be detected
|
|
|
|
from the source extensions if not provided.
|
2009-04-01 06:37:55 +08:00
|
|
|
optional : boolean
|
|
|
|
specifies that a build failure in the extension should not abort the
|
|
|
|
build process, but simply not install the failing extension.
|
2000-05-31 09:05:35 +08:00
|
|
|
"""
|
|
|
|
|
2003-01-28 00:30:36 +08:00
|
|
|
# When adding arguments to this constructor, be sure to update
|
|
|
|
# setup_keywords in core.py.
|
2007-08-30 11:52:21 +08:00
|
|
|
def __init__(self, name, sources,
|
2000-05-31 09:05:35 +08:00
|
|
|
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,
|
2004-10-14 18:02:08 +08:00
|
|
|
swig_opts = None,
|
2002-06-13 04:08:56 +08: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-06 00:12:02 +08:00
|
|
|
language=None,
|
2009-04-01 06:37:55 +08:00
|
|
|
optional=None,
|
2002-11-14 04:54:21 +08:00
|
|
|
**kw # To catch unknown keywords
|
2000-05-31 09:05:35 +08:00
|
|
|
):
|
2009-07-22 16:57:28 +08:00
|
|
|
if not isinstance(name, str):
|
|
|
|
raise AssertionError("'name' must be a string")
|
|
|
|
if not (isinstance(sources, list) and
|
|
|
|
all(isinstance(v, str) for v in sources)):
|
|
|
|
raise AssertionError("'sources' must be a list of strings")
|
2000-05-31 09:05:35 +08: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-13 08:41:40 +08:00
|
|
|
self.export_symbols = export_symbols or []
|
2004-10-14 18:02:08 +08:00
|
|
|
self.swig_opts = swig_opts or []
|
2002-06-13 04:08:56 +08: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-06 00:12:02 +08:00
|
|
|
self.language = language
|
2009-04-01 06:37:55 +08:00
|
|
|
self.optional = optional
|
2000-05-31 09:05:35 +08:00
|
|
|
|
2002-11-14 04:54:21 +08:00
|
|
|
# If there are unknown keyword options, warn about them
|
2009-06-03 19:17:15 +08:00
|
|
|
if len(kw) > 0:
|
|
|
|
options = [repr(option) for option in kw]
|
|
|
|
options = ', '.join(sorted(options))
|
|
|
|
msg = "Unknown Extension options: %s" % options
|
|
|
|
warnings.warn(msg)
|
2000-09-17 08:45:18 +08:00
|
|
|
|
2014-03-27 21:14:16 +08:00
|
|
|
def __repr__(self):
|
|
|
|
return '<%s.%s(%r) at %#x>' % (
|
|
|
|
self.__class__.__module__,
|
2014-07-22 20:00:37 +08:00
|
|
|
self.__class__.__qualname__,
|
2014-03-27 21:14:16 +08:00
|
|
|
self.name,
|
|
|
|
id(self))
|
|
|
|
|
|
|
|
|
2007-08-30 11:52:21 +08:00
|
|
|
def read_setup_file(filename):
|
2009-06-03 18:31:15 +08:00
|
|
|
"""Reads a Setup file and returns Extension instances."""
|
2010-07-22 20:50:05 +08:00
|
|
|
from distutils.sysconfig import (parse_makefile, expand_makefile_vars,
|
2009-06-03 18:31:15 +08:00
|
|
|
_variable_rx)
|
|
|
|
|
2000-09-17 08:45:18 +08:00
|
|
|
from distutils.text_file import TextFile
|
|
|
|
from distutils.util import split_quoted
|
|
|
|
|
|
|
|
# First pass over the file to gather "VAR = VALUE" assignments.
|
2010-07-22 20:50:05 +08:00
|
|
|
vars = parse_makefile(filename)
|
2000-09-17 08:45:18 +08:00
|
|
|
|
|
|
|
# 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)
|
2010-11-06 07:51:56 +08:00
|
|
|
try:
|
|
|
|
extensions = []
|
|
|
|
|
|
|
|
while True:
|
|
|
|
line = file.readline()
|
|
|
|
if line is None: # eof
|
|
|
|
break
|
2021-04-23 20:02:41 +08:00
|
|
|
if re.match(_variable_rx, line): # VAR=VALUE, handled in first pass
|
2000-09-17 08:45:18 +08:00
|
|
|
continue
|
|
|
|
|
2010-11-06 07:51:56 +08:00
|
|
|
if line[0] == line[-1] == "*":
|
|
|
|
file.warn("'%s' lines not handled yet" % line)
|
|
|
|
continue
|
|
|
|
|
|
|
|
line = expand_makefile_vars(line, vars)
|
|
|
|
words = split_quoted(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:]
|
|
|
|
|
|
|
|
if suffix in (".c", ".cc", ".cpp", ".cxx", ".c++", ".m", ".mm"):
|
|
|
|
# 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":
|
|
|
|
equals = value.find("=")
|
|
|
|
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":
|
2000-09-17 08:45:18 +08:00
|
|
|
append_next_word = ext.extra_link_args
|
2010-11-06 07:51:56 +08:00
|
|
|
elif word == "-Xcompiler":
|
|
|
|
append_next_word = ext.extra_compile_args
|
|
|
|
elif switch == "-u":
|
|
|
|
ext.extra_link_args.append(word)
|
|
|
|
if not value:
|
|
|
|
append_next_word = ext.extra_link_args
|
|
|
|
elif suffix in (".a", ".so", ".sl", ".o", ".dylib"):
|
|
|
|
# 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)
|
|
|
|
finally:
|
|
|
|
file.close()
|
2000-09-17 08:45:18 +08:00
|
|
|
|
|
|
|
return extensions
|