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 recommended way to build a module is the c2py_add_module macro provided by c2py: it declares
the Python extension module, links it against c2py, and – when Update_Python_Bindings is ON –
(re)generates the bindings with clair-c2py. The CMakeLists.txt for our Getting Started
example looks as follows:
1cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
2project(getting-started-example LANGUAGES C CXX)
3set(CMAKE_CXX_STANDARD 20)
4set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
5
6# This example ships without generated bindings, so regenerate them with clair-c2py.
7set(Update_Python_Bindings ON CACHE BOOL "Regenerate bindings via clair-c2py")
8
9include(FetchContent)
10
11# Fetch c2py; this also makes the c2py_add_module macro available.
12FetchContent_Declare(c2py
13 GIT_REPOSITORY https://github.com/flatironinstitute/c2py
14 GIT_TAG unstable
15 EXCLUDE_FROM_ALL
16)
17FetchContent_MakeAvailable(c2py)
18
19# Build the getting_started Python module and (re)generate its bindings.
20c2py_add_module(getting_started)
Let’s take a closer look at the CMakeLists.txt file:
[Lines 1-4] Standard CMake project configuration: we require
c++20support and tell CMake to generate acompile_commands.jsondatabase (clair-c2pyrelies on it to parse the code).[Line 7] This example ships without generated bindings, so we default
Update_Python_BindingstoONto (re)generate them; see the General Workflow below.[Lines 9-17] We fetch c2py from GitHub and make it available for the current project rather than relying on a system installation. This ensures that c2py and the extension module are built with consistent compiler options and linked against the same Python interpreter, and it makes the
c2py_add_modulemacro available. As c2py compiles quickly, it does not add significant overhead. (If c2py is already installed,find_package(c2py)makes the macro available just as well.)[Line 20]
c2py_add_moduledeclares thegetting_startedextension module, links it against c2py, and – whenUpdate_Python_BindingsisON– findsclair-c2pyand (re)generates the bindings before the module is compiled. It also accepts optional arguments such asLINK_LIBRARIESfor extra dependencies andDEPENDS_ON_BINDINGSto order generation across modules (see Across multiple modules).
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 tool 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.