33Build systems
44#############
55
6+ For an overview of Python packaging including compiled packaging with a pybind11
7+ example, along with a cookiecutter that includes several pybind11 options, see
8+ the `Scientific Python Development Guide `_.
9+
10+ .. _Scientific Python Development Guide : https://learn.scientific-python.org/development/guides/packaging-compiled/
11+
12+ .. scikit-build-core:
13+
14+ Modules with CMake
15+ ==================
16+
17+ A Python extension module can be created with just a few lines of code:
18+
19+ .. code-block :: cmake
20+
21+ cmake_minimum_required(VERSION 3.15...3.29)
22+ project(example LANGUAGES CXX)
23+
24+ set(PYBIND11_FINDPYTHON ON)
25+ find_package(pybind11 CONFIG REQUIRED)
26+
27+ pybind11_add_module(example example.cpp)
28+ install(TARGET example DESTINATION .)
29+
30+ (You use the ``add_subdirectory `` instead, see the example in :ref: `cmake `.) In
31+ this example, the code is located in a file named :file: `example.cpp `. Either
32+ method will import the pybind11 project which provides the
33+ ``pybind11_add_module `` function. It will take care of all the details needed
34+ to build a Python extension module on any platform.
35+
36+ To build with pip, build, cibuildwheel, uv, or other Python tools, you can
37+ add a ``pyproject.toml `` file like this:
38+
39+ .. code-block :: toml
40+
41+ [build-system]
42+ requires = ["scikit-build-core", "pybind11"]
43+ build-backend = "scikit_build_core.build"
44+
45+ [project]
46+ name = "example"
47+ version = "0.1.0"
48+
49+ You don't need setuptools files like ``MANIFEST.in ``, ``setup.py ``, or
50+ ``setup.cfg ``, as this is not setuptools. See `scikit-build-core `_ for details.
51+ For projects you plan to upload to PyPI, be sure to fill out the ``[project] ``
52+ table with other important metadata as well (see `Writing pyproject.toml `_).
53+
54+ A working sample project can be found in the [scikit_build_example ]_
55+ repository. An older and harder-to-maintain method is in [cmake_example ]_. More
56+ details about our cmake support can be found below in :ref: `cmake `.
57+
58+ .. _scikit-build-core : https://scikit-build-core.readthedocs.io
59+
60+ .. [scikit_build_example ] https://github.com/pybind/scikit_build_example
61+
62+ .. [cmake_example ] https://github.com/pybind/cmake_example
63+
64+ .. _modules-meson-python :
65+
66+ Modules with meson-python
67+ =========================
68+
69+ You can also build a package with `Meson `_ using `meson-python `_, if you prefer
70+ that. Your ``meson.build `` file would look something like this:
71+
72+ .. _meson-example :
73+
74+ .. code-block :: meson
75+
76+ project(
77+ 'example',
78+ 'cpp',
79+ version: '0.1.0',
80+ default_options: [
81+ 'cpp_std=c++11',
82+ ],
83+ )
84+
85+ py = import('python').find_installation(pure: false)
86+ pybind11_dep = dependency('pybind11')
87+
88+ py.extension_module('example',
89+ 'example.cpp',
90+ install: true,
91+ dependencies : [pybind11_dep],
92+ )
93+
94+
95+ And you would need a ``pyproject.toml `` file like this:
96+
97+ .. code-block :: toml
98+
99+ [build-system]
100+ requires = ["meson-python", "pybind11"]
101+ build-backend = "mesonpy"
102+
103+ Meson-python *requires * your project to be in git (or mercurial) as it uses it
104+ for the SDist creation. For projects you plan to upload to PyPI, be sure to fill out the
105+ ``[project] `` table as well (see `Writing pyproject.toml `_).
106+
107+
108+ .. _Writing pyproject.toml : https://packaging.python.org/en/latest/guides/writing-pyproject-toml
109+
110+ .. _meson : https://mesonbuild.com
111+
112+ .. _meson-python : https://meson-python.readthedocs.io/en/latest
113+
6114.. _build-setuptools :
7115
8- Building with setuptools
9- ========================
116+ Modules with setuptools
117+ =======================
10118
11- For projects on PyPI, building with setuptools is the way to go . Sylvain Corlay
12- has kindly provided an example project which shows how to set up everything,
13- including automatic generation of documentation using Sphinx. Please refer to
14- the [python_example ]_ repository.
119+ For projects on PyPI, a historically popular option is setuptools . Sylvain
120+ Corlay has kindly provided an example project which shows how to set up
121+ everything, including automatic generation of documentation using Sphinx.
122+ Please refer to the [python_example ]_ repository.
15123
16124.. [python_example ] https://github.com/pybind/python_example
17125
@@ -21,11 +129,11 @@ To use pybind11 inside your ``setup.py``, you have to have some system to
21129ensure that ``pybind11 `` is installed when you build your package. There are
22130four possible ways to do this, and pybind11 supports all four: You can ask all
23131users to install pybind11 beforehand (bad), you can use
24- :ref: `setup_helpers-pep518 ` (good, but very new and requires Pip 10),
25- :ref: `setup_helpers-setup_requires ` (discouraged by Python packagers now that
26- PEP 518 is available, but it still works everywhere), or you can
27- :ref: ` setup_helpers-copy-manually ` (always works but you have to manually sync
28- your copy to get updates) .
132+ :ref: `setup_helpers-pep518 ` (good), `` setup_requires= `` (discouraged), or you
133+ can :ref: `setup_helpers-copy-manually ` (works but you have to manually sync
134+ your copy to get updates). Third party packagers like conda-forge generally
135+ strongly prefer the `` pyproject.toml `` method, as it gives them control over
136+ the `` pybind11 `` version, and they may apply patches, etc .
29137
30138An example of a ``setup.py `` using pybind11's helpers:
31139
@@ -122,70 +230,41 @@ version number that includes the number of commits since your last tag and a
122230hash for a dirty directory. Another way to force a rebuild is purge your cache
123231or use Pip's ``--no-cache-dir `` option.
124232
233+ You also need a ``MANIFEST.in `` file to include all relevant files so that you
234+ can make an SDist. If you use `pypa-build `_, that will build an SDist then a
235+ wheel from that SDist by default, so you can look inside those files (wheels
236+ are just zip files with a ``.whl `` extension) to make sure you aren't missing
237+ files. `check-manifest `_ (setuptools specific) or `check-sdist `_ (general) are
238+ CLI tools that can compare the SDist contents with your source control.
239+
125240.. [Ccache ] https://ccache.dev
126241
127242 .. [setuptools_scm ] https://github.com/pypa/setuptools_scm
128243
129244 .. _setup_helpers-pep518 :
130245
131- PEP 518 requirements (Pip 10+ required)
132- ---------------------------------------
246+ Build requirements
247+ ------------------
133248
134- If you use `PEP 518's <https://www.python.org/dev/peps/pep-0518/ >`_
135- ``pyproject.toml `` file, you can ensure that ``pybind11 `` is available during
136- the compilation of your project. When this file exists, Pip will make a new
137- virtual environment, download just the packages listed here in ``requires= ``,
138- and build a wheel (binary Python package). It will then throw away the
139- environment, and install your wheel.
249+ With a ``pyproject.toml `` file, you can ensure that ``pybind11 `` is available
250+ during the compilation of your project. When this file exists, Pip will make a
251+ new virtual environment, download just the packages listed here in
252+ ``requires= ``, and build a wheel (binary Python package). It will then throw
253+ away the environment, and install your wheel.
140254
141255Your ``pyproject.toml `` file will likely look something like this:
142256
143257.. code-block :: toml
144258
145259 [build-system]
146- requires = ["setuptools>=42 ", "pybind11>=2.6.1 "]
260+ requires = ["setuptools", "pybind11"]
147261 build-backend = "setuptools.build_meta"
148262
149- .. note ::
150-
151- The main drawback to this method is that a `PEP 517 `_ compliant build tool,
152- such as Pip 10+, is required for this approach to work; older versions of
153- Pip completely ignore this file. If you distribute binaries (called wheels
154- in Python) using something like `cibuildwheel `_, remember that ``setup.py ``
155- and ``pyproject.toml `` are not even contained in the wheel, so this high
156- Pip requirement is only for source builds, and will not affect users of
157- your binary wheels. If you are building SDists and wheels, then
158- `pypa-build `_ is the recommended official tool.
159-
160263 .. _PEP 517 : https://www.python.org/dev/peps/pep-0517/
161- .. _cibuildwheel : https://cibuildwheel.readthedocs.io
162- .. _pypa-build : https://pypa-build.readthedocs.io/en/latest/
163-
164- .. _setup_helpers-setup_requires :
165-
166- Classic ``setup_requires ``
167- --------------------------
168-
169- If you want to support old versions of Pip with the classic
170- ``setup_requires=["pybind11"] `` keyword argument to setup, which triggers a
171- two-phase ``setup.py `` run, then you will need to use something like this to
172- ensure the first pass works (which has not yet installed the ``setup_requires ``
173- packages, since it can't install something it does not know about):
174-
175- .. code-block :: python
176-
177- try :
178- from pybind11.setup_helpers import Pybind11Extension
179- except ImportError :
180- from setuptools import Extension as Pybind11Extension
181-
182-
183- It doesn't matter that the Extension class is not the enhanced subclass for the
184- first pass run; and the second pass will have the ``setup_requires ``
185- requirements.
186-
187- This is obviously more of a hack than the PEP 518 method, but it supports
188- ancient versions of Pip.
264+ .. _cibuildwheel : https://cibuildwheel.pypa.io
265+ .. _pypa-build : https://build.pypa.io/en/latest/
266+ .. _check-manifest : https://pypi.io/project/check-manifest
267+ .. _check-sdist : https://pypi.io/project/check-sdist
189268
190269.. _setup_helpers-copy-manually :
191270
@@ -231,39 +310,30 @@ the C++ source file. Python is then able to find the module and load it.
231310
232311.. [cppimport ] https://github.com/tbenthompson/cppimport
233312
313+
314+
234315 .. _cmake :
235316
236317Building with CMake
237318===================
238319
239320For C++ codebases that have an existing CMake-based build system, a Python
240- extension module can be created with just a few lines of code:
241-
242- .. code-block :: cmake
243-
244- cmake_minimum_required(VERSION 3.5...3.29)
245- project(example LANGUAGES CXX)
321+ extension module can be created with just a few lines of code, as seen above in
322+ the module section. Pybind11 currently supports a lower minimum if you don't
323+ use the modern FindPython, though be aware that CMake 3.27 removed the old
324+ mechanism, so pybind11 will automatically switch if the old mechanism is not
325+ available. Please opt into the new mechanism if at all possible. Our default
326+ may change in future versions. This is the minimum required:
246327
247- add_subdirectory(pybind11)
248- pybind11_add_module(example example.cpp)
249-
250- This assumes that the pybind11 repository is located in a subdirectory named
251- :file: `pybind11 ` and that the code is located in a file named :file: `example.cpp `.
252- The CMake command ``add_subdirectory `` will import the pybind11 project which
253- provides the ``pybind11_add_module `` function. It will take care of all the
254- details needed to build a Python extension module on any platform.
255328
256- A working sample project, including a way to invoke CMake from :file: `setup.py ` for
257- PyPI integration, can be found in the [cmake_example ]_ repository.
258-
259- .. [cmake_example ] https://github.com/pybind/cmake_example
260329
261330.. versionchanged :: 2.6
262331 CMake 3.4+ is required.
263332
264333.. versionchanged :: 2.11
265334 CMake 3.5+ is required.
266335
336+
267337Further information can be found at :doc: `cmake/index `.
268338
269339pybind11_add_module
@@ -616,6 +686,13 @@ Building with Bazel
616686You can build with the Bazel build system using the `pybind11_bazel
617687<https://github.com/pybind/pybind11_bazel> `_ repository.
618688
689+ Building with Meson
690+ ===================
691+
692+ You can use Meson, which has support for ``pybind11 `` as a dependency (internally
693+ relying on our ``pkg-config `` support). See the :ref: `module example above <meson-example >`.
694+
695+
619696Generating binding code automatically
620697=====================================
621698
0 commit comments