Product
Introducing License Enforcement in Socket
Ensure open-source compliance with Socket’s License Enforcement Beta. Set up your License Policy and secure your software!
cmake-build-extension
Advanced tools
Setuptools extension to build and package CMake projects.
This project aims to simplify the integration of C++ projects based on CMake with Python packaging tools. CMake provides out-of-the-box support to either SWIG and pybind11, that are two among the most used projects to create Python bindings from C++ sources.
If you have any experience with these hybrid projects, you know the challenges to make packaging right!
This project takes inspiration from pre-existing examples
(pybind/cmake_example
, among many others)
and provides a simple, flexible, and reusable setuptools extension with the following features:
setup.py
.__init__.py
.Have a look to the example for an overview of what can be done with this extension. It shows how to create SWIG and pybind11 bindings for a project composed by a small C++ library with NumPy support and an executable.
CMAKE_MODULE_PATH
with the root of your installed Python package,
that could be obtained with:
python -c "import <pkg>, pathlib; print(pathlib.Path(<pkg>.__file__).parent)"
and consume the exported CMake targets.cmake-build-extension
with the cmake_depends_on
option and link against the exported CMake targets
during the downstream packaging.Note that the second feature allows distributing C++ dependencies through PyPI.
The resulting package structure is similar to other projects like pybind11 and CasADi.
Be aware that ensuring ABI compatibility could be problematic in edge cases,
and the usage of a proper compatible release pattern (~=
) could be necessary.
From PyPI:
pip install cmake-build-extension
From the repository:
pip install git+https://github.com/diegoferigo/cmake-build-extension
Once both CMake project and setup.py|setup.cfg|pyproject.toml
of your hybrid package are correctly configured
to use the resources provided by cmake-build-extension, the following commands can be used:
# ============
# Create sdist
# ============
# Calling setup.py
python setup.py sdist
# Using pypa/build
python -m build --sdist
# ============
# Create wheel
# ============
# Calling setup.py
python setup.py bdist_wheel
# Using pip
pip wheel -w dist/ .
# Using pypa/build
python -m build --wheel
# ==========================================================
# Create wheel or install package passing additional options
# ==========================================================
# Calling setup.py
python setup.py {bdist_wheel|install} build_ext -D"BAR=Foo;VAR=TRUE"
# Using pip
pip {wheel|install} --global-option="build_ext" --global-option="-DBAR=Foo;VAR=TRUE" .
# Using pypa/build (only wheel creation)
python -m build --wheel "-C--global-option=build_ext" "-C--global-option=-DBAR=Foo;VAR=TRUE"
manylinux*
supportThis extension, beyond packaging the hybrid C++ / Python project, also allows the inclusion of the exported CMake targets in the resulting wheel. This result depends on how the CMake project is configured, and whether the exported targets are installed together with the other files.
Such hybrid packages can then be uploaded to PyPI.
Though, on GNU/Linux, the generated wheel is not compliant by default with any manylinux*
standard.
Tools such auditwheel exist to fix these wheels, but they require running on selected distributions.
Luckily, other projects like cibuildwheel greatly simplify the process in CI.
This being said, manylinux*
guidelines could still work against you.
In fact, wheels supporting manylinux2010|manylinux2014
are built with gcc4
that does not support the new C++11 ABIs.
In few words, this means that the exported libraries bundled in the wheel cannot
be imported in a downstream project using relatively new C++ standards!
For more details visit robotology/idyntree#776.
Luckily, the situation changed thanks to the finalization of PEP600, i.e. manylinuxX_YY
:tada:
If you build a PEP600 compliant wheel (nowadays compatible with most of the commonly used distributions),
your exported CMake project bundled in the wheel can be successfully imported downstream.
If you want to support this use case, make sure to produce and distribute wheels compliant with PEP600.
Python 3.8 changed how DLL are resolved.
By default, modules that could be imported in Python 3.7 stopped working, and using the new
os.add_dll_directory
is now necessary.
In order to streamline the process, cmake-build-extension
implements a context manager that can be used
to import reliably the bindings module:
import cmake_build_extension
with cmake_build_extension.build_extension_env():
from . import bindings
It will take care to temporarily fix the search path.
For more details, refer to #8 and #12.
setup.py|setup.cfg|pyproject.toml
files in subfolderSometimes hybrid projects are C++ centric, and keeping these files in the top-level folder is not desirable.
In this setup, however, problems occur if the main CMakeLists.txt
is kept in the top-level folder
(see pypa/build#322).
To solve this problem, cmake-build-extension
provides custom commands to create source distribution.
You can use one of the following custom sdist
options in setup.py
:
setuptools.setup(
cmdclass=dict(
# [...]
# Pack the whole git folder:
sdist=cmake_build_extension.GitSdistFolder,
# Pack only the git tree:
sdist=cmake_build_extension.GitSdistTree,
# Or, inherit from cmake_build_extension.sdist_command.GitSdistABC and
# make your own custom sdist including only the files you are interested
),
)
If the provided example is not enough complex, find here below a list of projects using cmake-build-extension
:
robotology/idyntree
robotology/yarp
robotology/ycm
diegoferigo/gazebo-yarp-synchronizer
robotology/gym-ignition@scenario
dic-iit/gazebo-scenario-plugins
dic-iit/bipedal-locomotion-framework
artivis/manif
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
FAQs
Setuptools extension to build and package CMake projects.
We found that cmake-build-extension demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Ensure open-source compliance with Socket’s License Enforcement Beta. Set up your License Policy and secure your software!
Product
We're launching a new set of license analysis and compliance features for analyzing, managing, and complying with licenses across a range of supported languages and ecosystems.
Product
We're excited to introduce Socket Optimize, a powerful CLI command to secure open source dependencies with tested, optimized package overrides.