Use CMake integration [Recommended]
Generate Python Bindings and Compile the Module
To generate the Python bindings and compile the module with CMake, we simply run
$ mkdir build
$ cd build
$ cmake ..
$ make -j 8
CMake Configuration
The CMakeLists.txt used for our Getting Started example looks as follows:
1cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
2project(getting-started-example VERSION 3.2.0 LANGUAGES C CXX)
3set(CMAKE_CXX_STANDARD 20)
4set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
5include(FetchContent)
6
7# Locate Python and NumPy components
8find_package(Python COMPONENTS Interpreter Development NumPy)
9
10# Fetch the c2py library
11FetchContent_Declare(c2py
12 GIT_REPOSITORY https://github.com/flatironinstitute/c2py
13 GIT_TAG unstable
14 EXCLUDE_FROM_ALL
15)
16FetchContent_MakeAvailable(c2py)
17include(${c2py_SOURCE_DIR}/share/cmake/clair_c2py_generate_bindings.cmake)
18
19# Build the Python C++ extension module
20Python_add_library(getting_started MODULE getting_started.cpp)
21target_link_libraries(getting_started PRIVATE c2py::c2py)
22
23# -----------------------------------------------
24# Optionally regenerate bindings with clair-c2py
25# -----------------------------------------------
26
27option(Update_Python_Bindings "Use clair python bindings generators" ON)
28
29if (Update_Python_Bindings)
30 clair_c2py_generate_bindings(getting_started)
31endif()
Let’s take a closer look at the CMakeLists.txt file:
[Lines 1-5] Standard CMake project configuration where we require
c++20support and tell CMake to generate acompile_commands.jsondatabase file.[Lines 8] Since we want to build a Python C++ extension, we need to find Python/Numpy on the system.
[Lines 11-17] We fetch c2py from GitHub and make it available for the current project rather than relying on a system installation. This ensures that both, c2py and the extension module, iare built with consistent compiler options and linked against the same Python interpreter. As c2py compiles quickly, it does not add significant overhead to the build process.
[Lines 20–21] We use the
Python_add_librarycommand to declare ourgetting_startedextension module. The command is part of CMake.[Line 27-end] Here we introduce the user option
Update_Python_Bindingsand, if it is set toON, we call theclair_c2py_generate_bindingsmacro provided by c2py. The macro finds theclair-c2pyexecutable and makes sure to (re)generate the bindings before the module is compiled.
Note
The bindings are only (re)generated if the option
Update_Python_Bindingsis set toON.clair-c2pyautomatically uses the compilation database generated by CMake.Even if CMake uses an out-of-source build, the tools acts in the source directory, where it generates the binding files.
General Workflow
The above CMakeLists.txt file is designed to be used in two different modes, depending on the value of the
Update_Python_Bindings option:
Developer Mode (
Update_Python_Bindings == ON)[default]:The bindings are automatically regenerated using
clair-c2pywhen the C++ code or the options TOML file are modified.At the end, the regenerated bindings should be committed along with the rest of the source (they are produced in the source directory).
Any C++20-compliant compiler can be used to compile the module, even though
clair-c2pyitself relies on Clang and its libraries.
User Mode (
Update_Python_Bindings == OFF):The compilation uses the bindings already present in the source, as they are included in
my_module.cpp.clair-c2pyand clair in general are not needed.Any C++20-compliant compiler can be used.