This is an example of how to create a Modern CMake C++/Python Project.
This project aim to explain how you build a Python 3.6+ native wheel package using
Python3
and a setup.py.
e.g. You have a cross platform C++ library (using a CMake based build) and a
Python wrapper on it thanks to Pybind11
.
Then you want to provide a cross-platform Python packages to consume it in a
Python project...
This project should run on GNU/Linux, MacOS and Windows.
You'll need:
- "CMake >= 3.18".
- "Python >= 3.6" and python module 'pip' (ed "setuptools" and "wheel" will be auto installed on demand).
- "Pybind11 >= 2.10".
The project layout is as follow:
-
CMakeLists.txt Top-level for CMake based build.
-
cmake Subsidiary CMake files.
- python.cmake All internall Python CMake stuff.
-
ci Root directory for continuous integration.
-
Foo Root directory for
Foo
library.- CMakeLists.txt for
Foo
. - include public folder.
- src private folder.
- python
- CMakeLists.txt for
Foo
Python. - pyFoo.cpp Pybind Python wrapper.
- CMakeLists.txt for
- CMakeLists.txt for
-
Bar Root directory for
Bar
library.- CMakeLists.txt for
Bar
. - include public folder.
- src private folder.
- python
- CMakeLists.txt for
Bar
Python. - pyBar.cpp Pybind Python wrapper.
- CMakeLists.txt for
- CMakeLists.txt for
-
FooBar Root directory for
FooBar
library.- CMakeLists.txt for
FooBar
. - include public folder.
- src private folder.
- python
- CMakeLists.txt for
FooBar
Python. - pyFooBar.cpp Pybind Python wrapper.
- CMakeLists.txt for
- CMakeLists.txt for
-
python Root directory for Python template files
setup.py.in
setup.py template for the Python native package.
To complexify a little, the CMake project is composed of three libraries (Foo, Bar and FooBar) with the following dependencies:
Foo:
Bar:
FooBar: PUBLIC Foo PRIVATE Bar
To Create a native dependent package which will contains two parts:
- A bunch of native libraries for the supported platform targeted.
- The Python code depending on it.
note: Since Pypi.org support multiple packages, we will simply upload one package per supported platform.
The pipeline for linux-x86-64
should be as follow:
Thus we have the C++ shared library libFoo.so
and the pybind11
Python shared library e.g. pyFoo.so
in the same package.
Here some dev-note concerning this setup.py
.
- This package is a native package containing native libraries.
Then you can generate the package and install it locally using:
python3 setup.py bdist_wheel
python3 -m pip install --user --find-links=dist cmakepybind11
If everything good the package (located in <buildir>/python/dist
) should have
this layout:
{...}/dist/cmakepybind11-X.Y.9999-cp3Z-cp3Z-<platform>.whl:
\- pythonnative
\- __init__.py
\- .libs
\- libFoo.so
\- ...
\- foo
\- __init__.py
\- pyFoo.so
...
note: <platform>
could be manylinux2014_x86_64
, macosx_10_9_x86_64
or win-amd64
.
tips: since wheel package are just zip archive you can use unzip -l <package>.whl
to study their layout.
Few links on the subject...
Project layout:
- The Pitchfork Layout Revision 1 (cxx-pflR1)
CMake:
- https://llvm.org/docs/CMakePrimer.html
- https://cliutils.gitlab.io/modern-cmake/
- https://cgold.readthedocs.io/en/latest/
Python:
Image has been generated using plantuml:
plantuml -Tsvg docs/{file}.dot
So you can find the dot source files in docs.
Apache 2. See the LICENSE file for details.
This is not an official Google product, it is just code that happens to be owned by Google.