Package: cmake-build-extension
cmake-build-extensionSetuptools 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 eitherSWIGandpybind11,
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:Bridge between CMake projects and Python packaging.Configure and build the CMake project fromsetup.py.Install the CMake project in the resulting Python package.Allow passing custom CMake options.Allow creating a top-level__init__.py.Expose C++ executables to the Python environment.Provide a context manager to import reliably CPython modules on all major OSs.Disable the C++ extension in editable installations (requiring to manually call CMake to install the C++ project).Have a look to theexamplefor 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.Advanced featuresThis extension supports creating packagesPEP517andPEP518compliant (more details).If the CMake projectexports the targets, downstream projects can:Extend theirCMAKE_MODULE_PATHwith 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.Usecmake-build-extensionwith thecmake_depends_onoption 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 likepybind11andCasADi.
Be aware that ensuring ABI compatibility could be problematic in edge cases,
and the usage of a propercompatible release pattern(~=) could be necessary.InstallationFrom PyPI:pipinstallcmake-build-extensionFrom the repository:pipinstallgit+https://github.com/diegoferigo/cmake-build-extensionUsageOnce both CMake project andsetup.py|setup.cfg|pyproject.tomlof 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.pypythonsetup.pysdist# Using pypa/buildpython-mbuild--sdist# ============# Create wheel# ============# Calling setup.pypythonsetup.pybdist_wheel# Using pippipwheel-wdist/.# Using pypa/buildpython-mbuild--wheel# ==========================================================# Create wheel or install package passing additional options# ==========================================================# Calling setup.pypythonsetup.py{bdist_wheel|install}build_ext-D"BAR=Foo;VAR=TRUE"# Using pippip{wheel|install}--global-option="build_ext"--global-option="-DBAR=Foo;VAR=TRUE".# Using pypa/build (only wheel creation)python-mbuild--wheel"-C--global-option=build_ext""-C--global-option=-DBAR=Foo;VAR=TRUE"Caveatsmanylinux*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 theexported targetsare 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 anymanylinux*standard.
Tools suchauditwheelexist to fix these wheels, but they require running on selected distributions.
Luckily, other projects likecibuildwheelgreatly simplify the process in CI.This being said,manylinux*guidelines could still work against you.
In fact, wheels supportingmanylinux2010|manylinux2014are builtwith gcc4that 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 visitrobotology/idyntree#776.Luckily, the situation changed thanks to the finalization ofPEP600, 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.Loading CPython modules in WindowsPython 3.8changedhow DLL are resolved.
By default, modules that could be imported in Python 3.7 stopped working, and using the newos.add_dll_directoryis now necessary.In order to streamline the process,cmake-build-extensionimplements a context manager that can be used
to import reliably the bindings module:importcmake_build_extensionwithcmake_build_extension.build_extension_env():from.importbindingsIt will take care to temporarily fix the search path.For more details, refer to#8and#12.setup.py|setup.cfg|pyproject.tomlfiles 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 mainCMakeLists.txtis kept in the top-level folder
(seepypa/build#322).
To solve this problem,cmake-build-extensionprovides custom commands to create source distribution.
You can use one of the following customsdistoptions insetup.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),)Downstream projectsIf the provided example is not enough complex, find here below a list of projects usingcmake-build-extension:robotology/idyntreerobotology/yarprobotology/ycmdiegoferigo/gazebo-yarp-synchronizerrobotology/gym-ignition@scenariodic-iit/gazebo-scenario-pluginsdic-iit/bipedal-locomotion-frameworkartivis/manifContributingPull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.LicenseMIT