11# Python C++ extension
2+
23A template for a standalone C++ library with dependencies managed by
34[ vcpkg] ( https://github.com/microsoft/vcpkg ) accessible through Python using
45[ pybind11] ( https://github.com/pybind/pybind11 ) .
56
67## Why should I use this template?
7- - You want to write a C++ library that can be accessed through Python.
8- - You want to use ` cmake ` to build your C++ code.
9- - You want to use ` pybind11 ` to expose your C++ library as a Python module.
10- - You want to use some C++ dependencies and manage them with ` vcpkg ` . Otherwise
8+
9+ * You want to write a C++ library that can be accessed through Python.
10+ * You want to use ` cmake ` to build your C++ code.
11+ * You want to use ` pybind11 ` to expose your C++ library as a Python module.
12+ * You want to use some C++ dependencies and manage them with ` vcpkg ` . Otherwise
1113 you should check other [ scikit-build sample
1214 projects] ( https://github.com/scikit-build/scikit-build-sample-projects ) .
13- - You are not specially concerned about build and install optimizations, it is
15+ * You are not specially concerned about build and install optimizations, it is
1416 not a problem if they are long running.
1517
1618If you want to distribute your extension using ` pip ` or ` conda ` and you mind
1719that your users take a long time to install it, then it might be better to
1820distribute some built binaries instead of optimizing the build process. This
1921template might still be useful for you as it has a
20- [ release ] ( .github/workflows/release .yml ) workflow for building python wheels
21- with [ cibuildwheel] ( https://github.com/pypa/cibuildwheel ) and distributing them
22- to [ PyPI] ( https://pypi.org/ ) .
22+ [ CD ] ( .github/workflows/cd .yml ) workflow for building python wheels
23+ with [ cibuildwheel] ( https://github.com/pypa/cibuildwheel ) and uploading them to
24+ [ PyPI] ( https://pypi.org/ ) .
2325
2426## Example usage
2527
2628### Create a clean Python virtual environment
29+
2730```
2831python -m venv venv
2932```
33+
3034Activate it on Windows
35+
3136```
3237.\venv\Scripts\activate
3338```
39+
3440otherwise
41+
3542```
3643source ./venv/bin/activate
3744```
3845
3946### Install this project
47+
4048```
4149pip install git+https://github.com/esdandreu/python-extension-cpp
4250```
43- It will take a while to build as it will build the C++ dependencies as well,
51+
52+ It will take a while to build as it will build the C++ dependencies as well,
4453but it will work. It is definitely not the most optimal way of installing a
4554package as we are installing as well the ` vcpkg ` package manager and building
4655from source dependencies that might as well be installed on the system. But
4756this allows a fast development environment where adding or removing C++
4857dependencies should be easy.
4958
50- Alternatively, you can install the package from the binaries distributed in [ PyPI] ( https://pypi.org/project/example-python-extension-cpp/ ) .
59+ Alternatively, you can install the package from the binaries distributed in
60+ [ PyPI] ( https://pypi.org/project/example-python-extension-cpp/ ) using the
61+ [ continuous deployment] ( #cicd ) workflow.
62+
5163```
5264pip install example-python-extension-cpp
5365```
5466
5567### Test that the C++ code is working in the Python package
68+
5669Our simple project contains a ` add ` function that adds two numbers together.
70+
5771```
5872python -c "import my_python_api; print(my_python_api.add(1, 2))"
5973```
6074
6175It also makes use of the C++ library
6276[ fftw3] ( https://github.com/FFTW/fftw3.git ) that is available through ` vcpkg `
77+
6378in order to perform a Fast Fourier Transform over a generated signal, printing
6479its results.
80+
6581```
6682python -c "import my_python_api; my_python_api.hello_fft()"
6783```
6884
6985## Setup
86+
7087### Install the requirements
7188Install [ vcpkg] ( https://github.com/microsoft/vcpkg ) requirements with the
7289addition of ` cmake ` and Python. It could be summarized as:
73- - [ git] ( https://git-scm.com/downloads )
74- - Build tools ([ Visual
90+ * [ git] ( https://git-scm.com/downloads )
91+ * Build tools ([ Visual
7592 Studio] ( https://docs.microsoft.com/en-us/visualstudio/install/install-visual-studio )
7693 on Windows or ` gcc ` on Linux for example)
77- - [ cmake] ( #cmake )
78- - Python. Make sure to have development tools installed (` python3.X-dev ` on
94+ * [ cmake] ( #cmake )
95+ * Python. Make sure to have development tools installed (` python3.X-dev ` on
7996 Linux, being ` X ` your version of Python).
8097
8198If running on a clean linux environment (like a container or Windows Subsystem
8299for Linux) you will need to install some additional tools as it is stated in
83- ` vcpkg ` .
100+ ` vcpkg ` .
101+
84102```
85103sudo apt-get install build-essential curl zip unzip tar pkg-config libssl-dev python3-dev
86104```
105+
87106#### CMake
107+
88108Follow the [ official instructions] ( https://cmake.org/install/ ) .
89109
90110The required ` cmake ` version is quite high, if you are using a Linux
@@ -95,10 +115,11 @@ line](https://askubuntu.com/a/865294).
95115
96116Make sure that when you run ` cmake --version ` the output is ` 3.21 ` or higher.
97117The reason for this is that we are using some of the ` 3.21 ` features to install
98- runtime dependencies (managed with ` vcpkg ` ) together with our project so they
118+ runtime dependencies (managed with ` vcpkg ` ) together with our project so they
99119are available to Python when using its API.
100120
101121#### Formatters
122+
102123This project uses ` clang-format ` to format the C++ code. There is a
103124` .clang-format ` file with options that I personally like. Download
104125` clang-format ` as part of ` LLVM ` from the official [ release
@@ -109,40 +130,48 @@ I als recommend using `yapf` to format python code.
109130### Clone this repository with ` vcpkg `
110131
111132Cone this repository with ` vcpkg ` as a submodule and navigate into it.
133+
112134```
113135git clone --recursive git@github.com:esdandreu/python-extension-cpp.git
114136cd python-extension-cpp
115137```
116138
117139Bootstrap ` vcpkg ` in Windows. Make sure you have [ installed the
118140prerequisites] ( https://github.com/microsoft/vcpkg ) .
141+
119142```
120143.\vcpkg\bootstrap-vcpkg.bat
121144```
122145
123146Or in Linux/MacOS. Make sure you have [ installed developer
124147tools] ( https://github.com/microsoft/vcpkg )
148+
125149```
126150./vcpkg/bootstrap-vcpkg.sh
127151```
128152
129153## Building
130154
131155### Build locally with CMake
156+
132157Navigate to the root of the repository and create a build directory.
158+
133159```
134160mkdir build
135161```
136162
137- Configure ` cmake ` to use ` vcpkg ` .
163+ Configure ` cmake ` to use ` vcpkg ` .
164+
138165```
139166cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="$pwd/vcpkg/scripts/buildsystems/vcpkg.cmake"
140167```
141168
142169Build the project.
170+
143171```
144172cmake --build build
145173```
174+
146175### Build locally with Python
147176
148177It is recommended to use a [ clean virtual
@@ -158,11 +187,11 @@ pip install scikit-build git
158187
159188Install the repository. By adding ` [test] ` to our install command we can
160189install additionally the test dependencies.
190+
161191```
162192pip install .[test]
163193```
164194
165-
166195## Testing
167196
168197### Test the C++ library with Google Test
@@ -180,16 +209,16 @@ pytest
180209## CI/CD
181210
182211This template contains a continuous integration workflow that builds and tests
183- the C++ library and the python extension
184- [ test.yml] ( .github/workflows/test.yml ) .
212+ the C++ library and the python extension [ ci.yml] ( .github/workflows/ci.yml ) .
185213
186214It also contains a continuous deployment workflow that builds wheels and source
187215distributions for the python extension, then creates a github release with it
188216and uploads it to [ PyPI] ( https://pypi.org/ ) :
189- [ release.yml] ( .github/workflows/release.yml ) . That workflow requires a
190- repository secret named ` PYPI_TOKEN ` with a PyPI API token. is activated when
191- pushing a version tag to the repository:
217+ [ cd.yml] ( .github/workflows/cd.yml ) . That workflow requires a repository secret
218+ named ` PYPI_TOKEN ` with a PyPI API token. is activated when pushing a version
219+ tag to the repository:
220+
192221```
193222git tag -a v0.0.1 -m "First release"
194223git push origin --tags
195- ```
224+ ```
0 commit comments