Building Extension Modules¶
Setuptools can build C/C++ extension modules. The keyword argument
ext_modules
of setup()
should be a list of instances of the
setuptools.Extension
class.
For example, let’s consider a simple project with only one extension module:
<project_folder>
├── pyproject.toml
└── foo.c
and all project metadata configuration in the pyproject.toml
file:
# pyproject.toml
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "mylib-foo" # as it would appear on PyPI
version = "0.42"
To instruct setuptools to compile the foo.c
file into the extension module
mylib.foo
, we need to define an appropriate configuration in either
pyproject.toml
[1] or setup.py
file ,
similar to the following:
[tool.setuptools]
ext-modules = [
{name = "mylib.foo", sources = ["foo.c"]}
]
from setuptools import Extension, setup
setup(
ext_modules=[
Extension(
name="mylib.foo",
sources=["foo.c"],
),
]
)
The name
value corresponds to how the extension module would be
imported and may include packages/namespaces separated by .
.
The sources
value is a list of all source files that are compiled
into a single binary file.
Optionally any other parameter of setuptools.Extension
can be defined
in the configuration file (but in the case of pyproject.toml
they must be
written using kebab-case convention).
See also
You can find more information on the Python docs about C/C++ extensions. Alternatively, you might also be interested in learning about Cython.
If you plan to distribute a package that uses extensions across multiple platforms, cibuildwheel can also be helpful.
Important
All files used to compile your extension need to be available on the system when building the package, so please make sure to include some documentation on how developers interested in building your package from source can obtain operating system level dependencies (e.g. compilers and external binary libraries/artifacts).
You will also need to make sure that all auxiliary files that are contained inside your project (e.g. C headers authored by you or your team) are configured to be included in your sdist. Please have a look on our section on Controlling files in the distribution.
Compiler and linker options¶
The command build_ext
builds C/C++ extension modules. It creates
a command line for running the compiler and linker by combining
compiler and linker options from various sources:
the
sysconfig
variablesCC
,CXX
,CCSHARED
,LDSHARED
, andCFLAGS
,the environment variables
CC
,CPP
,CXX
,LDSHARED
andCFLAGS
,CPPFLAGS
,LDFLAGS
,the
Extension
attributesinclude_dirs
,library_dirs
,extra_compile_args
,extra_link_args
,runtime_library_dirs
.
Specifically, if the environment variables CC
, CPP
, CXX
, and LDSHARED
are set, they will be used instead of the sysconfig
variables of the same names.
The compiler options appear in the command line in the following order:
first, the options provided by the
sysconfig
variableCFLAGS
,then, the options provided by the environment variables
CFLAGS
andCPPFLAGS
,then, the options provided by the
sysconfig
variableCCSHARED
,then, a
-I
option for each element ofExtension.include_dirs
,finally, the options provided by
Extension.extra_compile_args
.
The linker options appear in the command line in the following order:
first, the options provided by environment variables and
sysconfig
variables,then, a
-L
option for each element ofExtension.library_dirs
,then, a linker-specific option like
-Wl,-rpath
for each element ofExtension.runtime_library_dirs
,finally, the options provided by
Extension.extra_link_args
.
The resulting command line is then processed by the compiler and linker.
According to the GCC manual sections on directory options and
environment variables, the C/C++ compiler searches for files named in
#include <file>
directives in the following order:
first, in directories given by
-I
options (in left-to-right order),then, in directories given by the environment variable
CPATH
(in left-to-right order),then, in directories given by
-isystem
options (in left-to-right order),then, in directories given by the environment variable
C_INCLUDE_PATH
(for C) andCPLUS_INCLUDE_PATH
(for C++),then, in standard system directories,
finally, in directories given by
-idirafter
options (in left-to-right order).
The linker searches for libraries in the following order:
first, in directories given by
-L
options (in left-to-right order),then, in directories given by the environment variable
LIBRARY_PATH
(in left-to-right order).
Distributing Extensions compiled with Cython¶
When your Cython extension modules are declared using the
setuptools.Extension
class, setuptools
will detect at build time
whether Cython is installed or not.
If Cython is present, then setuptools
will use it to build the .pyx
files.
Otherwise, setuptools
will try to find and compile the equivalent .c
files
(instead of .pyx
). These files can be generated using the
cython command line tool.
You can ensure that Cython is always automatically installed into the build
environment by including it as a build dependency in
your pyproject.toml
:
[build-system]
requires = [
# ...,
"cython",
]
Alternatively, you can include the .c
code that is pre-compiled by Cython
into your source distribution, alongside the original .pyx
files (this
might save a few seconds when building from an sdist
).
To improve version compatibility, you probably also want to include current
.c
files in your revision control system, and rebuild them whenever
you check changes in for the .pyx
source files.
This will ensure that people tracking your project will be able to build it
without installing Cython, and that there will be no variation due to small
differences in the generate C files.
Please checkout our docs on Controlling files in the distribution for
more information.
Extension API Reference¶
- class setuptools.Extension(name: str, sources, *args, py_limited_api: bool = False, **kw)¶
Describes a single extension module.
This means that all source files will be compiled into a single binary file
<module path>.<suffix>
(with<module path>
derived fromname
and<suffix>
defined by one of the values inimportlib.machinery.EXTENSION_SUFFIXES
).In the case
.pyx
files are passed assources and
Cython
is not installed in the build environment,setuptools
may also try to look for the equivalent.cpp
or.c
files.- Parameters:
name (str) – the full name of the extension, including any packages – ie. not a filename or pathname, but Python dotted name
sources (list[str]) – 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.
include_dirs (list[str]) – list of directories to search for C/C++ header files (in Unix form for portability)
define_macros (list[tuple[str, str|None]]) – list of macros to define; each macro is defined using a 2-tuple: the first item corresponding to the name of the macro and the second item either a string with its value 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 (list[str]) – list of macros to undefine explicitly
library_dirs (list[str]) – list of directories to search for C/C++ libraries at link time
libraries (list[str]) – list of library names (not filenames or paths) to link against
runtime_library_dirs (list[str]) – list of directories to search for C/C++ libraries at run time (for shared extensions, this is when the extension is loaded). Setting this will cause an exception during build on Windows platforms.
extra_objects (list[str]) – 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 (list[str]) – 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 (list[str]) – 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 (list[str]) – 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.
swig_opts (list[str]) – any extra options to pass to SWIG if a source file has the .i extension.
depends (list[str]) – list of files that the extension depends on
language (str) – extension language (i.e. “c”, “c++”, “objc”). Will be detected from the source extensions if not provided.
optional (bool) – specifies that a build failure in the extension should not abort the build process, but simply not install the failing extension.
py_limited_api (bool) – opt-in flag for the usage of Python’s limited API.
- Raises:
setuptools.errors.PlatformError – if
runtime_library_dirs
is specified on Windows. (since v63)
Notes