1
1
# Python C++ extension
2
+
2
3
A template for a standalone C++ library with dependencies managed by
3
4
[ vcpkg] ( https://github.com/microsoft/vcpkg ) accessible through Python using
4
5
[ pybind11] ( https://github.com/pybind/pybind11 ) .
5
6
6
7
## 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
11
13
you should check other [ scikit-build sample
12
14
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
14
16
not a problem if they are long running.
15
17
16
18
If you want to distribute your extension using ` pip ` or ` conda ` and you mind
17
19
that your users take a long time to install it, then it might be better to
18
20
distribute some built binaries instead of optimizing the build process. This
19
21
template 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/ ) .
23
25
24
26
## Example usage
25
27
26
28
### Create a clean Python virtual environment
29
+
27
30
```
28
31
python -m venv venv
29
32
```
33
+
30
34
Activate it on Windows
35
+
31
36
```
32
37
.\venv\Scripts\activate
33
38
```
39
+
34
40
otherwise
41
+
35
42
```
36
43
source ./venv/bin/activate
37
44
```
38
45
39
46
### Install this project
47
+
40
48
```
41
49
pip install git+https://github.com/esdandreu/python-extension-cpp
42
50
```
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,
44
53
but it will work. It is definitely not the most optimal way of installing a
45
54
package as we are installing as well the ` vcpkg ` package manager and building
46
55
from source dependencies that might as well be installed on the system. But
47
56
this allows a fast development environment where adding or removing C++
48
57
dependencies should be easy.
49
58
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
+
51
63
```
52
64
pip install example-python-extension-cpp
53
65
```
54
66
55
67
### Test that the C++ code is working in the Python package
68
+
56
69
Our simple project contains a ` add ` function that adds two numbers together.
70
+
57
71
```
58
72
python -c "import my_python_api; print(my_python_api.add(1, 2))"
59
73
```
60
74
61
75
It also makes use of the C++ library
62
76
[ fftw3] ( https://github.com/FFTW/fftw3.git ) that is available through ` vcpkg `
77
+
63
78
in order to perform a Fast Fourier Transform over a generated signal, printing
64
79
its results.
80
+
65
81
```
66
82
python -c "import my_python_api; my_python_api.hello_fft()"
67
83
```
68
84
69
85
## Setup
86
+
70
87
### Install the requirements
71
88
Install [ vcpkg] ( https://github.com/microsoft/vcpkg ) requirements with the
72
89
addition 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
75
92
Studio] ( https://docs.microsoft.com/en-us/visualstudio/install/install-visual-studio )
76
93
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
79
96
Linux, being ` X ` your version of Python).
80
97
81
98
If running on a clean linux environment (like a container or Windows Subsystem
82
99
for Linux) you will need to install some additional tools as it is stated in
83
- ` vcpkg ` .
100
+ ` vcpkg ` .
101
+
84
102
```
85
103
sudo apt-get install build-essential curl zip unzip tar pkg-config libssl-dev python3-dev
86
104
```
105
+
87
106
#### CMake
107
+
88
108
Follow the [ official instructions] ( https://cmake.org/install/ ) .
89
109
90
110
The required ` cmake ` version is quite high, if you are using a Linux
@@ -95,10 +115,11 @@ line](https://askubuntu.com/a/865294).
95
115
96
116
Make sure that when you run ` cmake --version ` the output is ` 3.21 ` or higher.
97
117
The 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
99
119
are available to Python when using its API.
100
120
101
121
#### Formatters
122
+
102
123
This project uses ` clang-format ` to format the C++ code. There is a
103
124
` .clang-format ` file with options that I personally like. Download
104
125
` clang-format ` as part of ` LLVM ` from the official [ release
@@ -109,40 +130,48 @@ I als recommend using `yapf` to format python code.
109
130
### Clone this repository with ` vcpkg `
110
131
111
132
Cone this repository with ` vcpkg ` as a submodule and navigate into it.
133
+
112
134
```
113
135
git clone --recursive git@github.com:esdandreu/python-extension-cpp.git
114
136
cd python-extension-cpp
115
137
```
116
138
117
139
Bootstrap ` vcpkg ` in Windows. Make sure you have [ installed the
118
140
prerequisites] ( https://github.com/microsoft/vcpkg ) .
141
+
119
142
```
120
143
.\vcpkg\bootstrap-vcpkg.bat
121
144
```
122
145
123
146
Or in Linux/MacOS. Make sure you have [ installed developer
124
147
tools] ( https://github.com/microsoft/vcpkg )
148
+
125
149
```
126
150
./vcpkg/bootstrap-vcpkg.sh
127
151
```
128
152
129
153
## Building
130
154
131
155
### Build locally with CMake
156
+
132
157
Navigate to the root of the repository and create a build directory.
158
+
133
159
```
134
160
mkdir build
135
161
```
136
162
137
- Configure ` cmake ` to use ` vcpkg ` .
163
+ Configure ` cmake ` to use ` vcpkg ` .
164
+
138
165
```
139
166
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="$pwd/vcpkg/scripts/buildsystems/vcpkg.cmake"
140
167
```
141
168
142
169
Build the project.
170
+
143
171
```
144
172
cmake --build build
145
173
```
174
+
146
175
### Build locally with Python
147
176
148
177
It is recommended to use a [ clean virtual
@@ -158,11 +187,11 @@ pip install scikit-build git
158
187
159
188
Install the repository. By adding ` [test] ` to our install command we can
160
189
install additionally the test dependencies.
190
+
161
191
```
162
192
pip install .[test]
163
193
```
164
194
165
-
166
195
## Testing
167
196
168
197
### Test the C++ library with Google Test
@@ -180,16 +209,16 @@ pytest
180
209
## CI/CD
181
210
182
211
This 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 ) .
185
213
186
214
It also contains a continuous deployment workflow that builds wheels and source
187
215
distributions for the python extension, then creates a github release with it
188
216
and 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
+
192
221
```
193
222
git tag -a v0.0.1 -m "First release"
194
223
git push origin --tags
195
- ```
224
+ ```
0 commit comments