Thank you for your interest in this project! Please refer to the following sections on how to contribute code and bug reports.
Before submitting a question or bug report, please take a moment of your time and ensure that your issue isn't already discussed in the project documentation provided at pybind11.readthedocs.org or in the issue tracker. You can also check gitter to see if it came up before.
Assuming that you have identified a previously unknown problem or an important question, it's essential that you submit a self-contained and minimal piece of code that reproduces the problem. In other words: no external dependencies, isolate the function(s) that cause breakage, submit matched and complete C++ and Python snippets that can be easily compiled and run in isolation; or ideally make a small PR with a failing test case that can be used as a starting point.
Contributions are submitted, reviewed, and accepted using GitHub pull requests. Please refer to this article for details and adhere to the following rules to make the process as smooth as possible:
cmake --build build --target pytest) to ensure that no existing features break.
pre-commit to check your code matches the project style. (Note that
gawk is required.) Use
pre-commit run --all-files before committing (or use installed-mode, check pre-commit docs) to verify your code passes before pushing to save time.
pybind11 is provided under a BSD-style license that can be found in the
LICENSE file. By using, distributing, or contributing to this project, you agree to the terms and conditions of this license.
You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, functionality or performance of the source code (“Enhancements”) to anyone; however, if you choose to make your Enhancements available either publicly, or directly to the author of this software, without imposing a separate written license agreement for such Enhancements, then you hereby grant the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare derivative works, incorporate into other computer software, distribute, and sublicense such enhancements or derivative works thereof, in binary and source code form.
To setup an ideal development environment, run the following commands on a system with CMake 3.14+:
python3 -m venv venv source venv/bin/activate pip install -r tests/requirements.txt cmake -S . -B build -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON cmake --build build -j4
virtualenv (from PyPI) instead of
venv (which is Python 3 only).
-DPYBIND11_FINDPYTHON=ON to use FindPython on CMake 3.12+
-DPYTHON_EXECUTABLE=/path/to/python. FindPython uses
In CMake, configuration options are given with “-D”. Options are stored in the build directory, in the
CMakeCache.txt file, so they are remembered for each build directory. Two selections are special - the generator, given with
-G, and the compiler, which is selected based on environment variables
CXX and similar, or
-DCMAKE_CXX_COMPILER=. Unlike the others, these cannot be changed after the initial run.
The valid options are:
-DCMAKE_BUILD_TYPE: Release, Debug, MinSizeRel, RelWithDebInfo
-DPYBIND11_FINDPYTHON=ON: Use CMake 3.12+’s FindPython instead of the classic, deprecated, custom FindPythonLibs
-DPYBIND11_NOPYTHON=ON: Disable all Python searching (disables tests)
-DBUILD_TESTING=ON: Enable the tests
-DDOWNLOAD_CATCH=ON: Download catch to build the C++ tests
-DOWNLOAD_EIGEN=ON: Download Eigen for the NumPy tests
-DPYBIND11_INSTALL=ON/OFF: Enable the install target (on by default for the master project)
-DUSE_PYTHON_INSTALL_DIR=ON: Try to install into the python dir
cmake --build build -v to see the commands used to build the files.
cmake build -LH to list the CMake options with help.
ccmake if available to see a curses (terminal) gui, or
cmake-gui for a completely graphical interface (not present in the PyPI package).
cmake --build build -j12 to build with 12 cores (for example).
-G and the name of a generator to use something different.
cmake --help lists the generators available. - On Unix, setting
CMAKE_GENERATER=Ninja in your environment will give you automatic mulithreading on all your CMake projects!
CMakeLists.txt with QtCreator to generate for that IDE.
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON to generate the
.json file that some tools expect.
To run the tests, you can “build” the check target:
cmake --build build --target check
--target can be spelled
-t in CMake 3.15+. You can also run individual tests with these targets:
pytest: Python tests only, using the pytest framework
cpptest: C++ tests only
test_cmake_build: Install / subdirectory tests
If you want to build just a subset of tests, use
-DPYBIND11_TEST_OVERRIDE="test_callbacks.cpp;test_pickling.cpp". If this is empty, all tests will be built.
You may also pass flags to the
pytest target by editing
tests/pytest.ini or by using the
PYTEST_ADDOPTS environment variable (see
pytest docs). As an example:
env PYTEST_ADDOPTS="--capture=no --exitfirst" \ cmake --build build --target pytest # Or using abbreviated flags env PYTEST_ADDOPTS="-s -x" cmake --build build --target pytest
All formatting is handled by pre-commit.
Install with brew (macOS) or pip (any OS):
# Any OS python3 -m pip install pre-commit # OR macOS with homebrew: brew install pre-commit
Then, you can run it on the items you've added to your staging area, or all files:
pre-commit run # OR pre-commit run --all-files
And, if you want to always use it, you can install it as a git hook (hence the name, pre-commit):
As of v2.6.2, pybind11 ships with a
clang-format configuration file at the top level of the repo (the filename is
.clang-format). Currently, formatting is NOT applied automatically, but manually using
clang-format for newly developed files is highly encouraged. To check if a file needs formatting:
clang-format -style=file --dry-run some.cpp
The output will show things to be fixed, if any. To actually format the file:
clang-format -style=file -i some.cpp
Note that the
-style-file option searches the parent directories for the
.clang-format file, i.e. the commands above can be run in any subdirectory of the pybind11 repo.
clang-tidy performs deeper static code analyses and is more complex to run, compared to
clang-format, but support for
clang-tidy is built into the pybind11 CMake configuration. To run
clang-tidy, the following recipe should work. Files will be modified in place, so you can use git to monitor the changes.
docker run --rm -v $PWD:/pybind11 -it silkeh/clang:10 apt-get update && apt-get install python3-dev python3-pytest cmake -S pybind11/ -B build -DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);-fix" cmake --build build
To run include what you use, install (
brew install include-what-you-use on macOS), then run:
cmake -S . -B build-iwyu -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=$(which include-what-you-use) cmake --build build
The report is sent to stderr; you can pipe it into a file if you wish.
This builds with the Intel compiler (assuming it is in your path, along with a recent CMake and Python 3):
python3 -m venv venv . venv/bin/activate pip install pytest cmake -S . -B build-intel -DCMAKE_CXX_COMPILER=$(which icpc) -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON -DPYBIND11_WERROR=ON
This will test the PGI compilers:
docker run --rm -it -v $PWD:/pybind11 nvcr.io/hpc/pgi-compilers:ce apt-get update && apt-get install -y python3-dev python3-pip python3-pytest wget -qO- "https://cmake.org/files/v3.18/cmake-3.18.2-Linux-x86_64.tar.gz" | tar --strip-components=1 -xz -C /usr/local cmake -S pybind11/ -B build cmake --build build
These details below are only for packaging the Python sources from git. The SDists and wheels created do not have any extra requirements at all and are completely normal.
The main objective of the packaging system is to create SDists (Python‘s source distribution packages) and wheels (Python’s binary distribution packages) that include everything that is needed to work with pybind11, and which can be installed without any additional dependencies. This is more complex than it appears: in order to support CMake as a first class language even when using the PyPI package, they must include the generated CMake files (so as not to require CMake when installing the
pybind11 package itself). They should also provide the option to install to the “standard” location (
<ENVROOT>/share/cmake/pybind11) so they are easy to find with CMake, but this can cause problems if you are not an environment or using
pyproject.toml requirements. This was solved by having two packages; the “nice” pybind11 package that stores the includes and CMake files inside the package, that you get access to via functions in the package, and a
pybind11-global package that can be included via
pybind11[global] if you want the more invasive but discoverable file locations.
If you want to install or package the GitHub source, it is best to have Pip 10 or newer on Windows, macOS, or Linux (manylinux1 compatible, includes most distributions). You can then build the SDists, or run any procedure that makes SDists internally, like making wheels or installing.
# Editable development install example python3 -m pip install -e .
Since Pip itself does not have an
sdist command (it does have
install), you may want to use the upcoming
python3 -m pip install build # Normal package python3 -m build -s . # Global extra PYBIND11_GLOBAL_SDIST=1 python3 -m build -s .
If you want to use the classic “direct” usage of
python setup.py, you will need CMake 3.15+ and either
ninja preinstalled (possibly via
pip install cmake ninja), since directly running Python on
setup.py cannot pick up and install
pyproject.toml requirements. As long as you have those two things, though, everything works the way you would expect:
# Normal package python3 setup.py sdist # Global extra PYBIND11_GLOBAL_SDIST=1 python3 setup.py sdist
A detailed explanation of the build procedure design for developers wanting to work on or maintain the packaging system is as follows:
When you invoke any
setup.py command from the source directory, including
pip wheel . and
pip install ., you will activate a full source build. This is made of the following steps:
--no-build-isolation as long as you have CMake 3.15+ installed)
PYBIND11_GLOBAL_SDIST is checked - if it is set and truthy, this will be make the accessory
pybind11-global package, instead of the normal
pybind11 package. This package is used for installing the files directly to your environment root directory, using
setup.py reads the version from
pybind11/_version.py and verifies it matches
-DCMAKE_INSTALL_PREIFX=pybind11. Since the CMake install procedure uses only relative paths and is identical on all platforms, these files are valid as long as they stay in the correct relative position to the includes.
pybind11/share/cmake/pybind11 has the CMake files, and
pybind11/include has the includes. The build directory is discarded.
setup_main.py fills in Python packages, and
setup_global.py fills in only the data/header slots.
Since the SDist has the rendered template files in
tools along with the includes and CMake files in the correct locations, the builds are completely trivial and simple. No extra requirements are required. You can even use Pip 9 if you really want to.