Introducing CPPLib

C++ and Python Library

This is a template repository used to create C++/Python libraries. This is for individuals who want to write a standalone C++ library that can also be bound to Python using Pybind11 for better performance. This repository additionally takes care of the intricate world of building binary wheels automatically and publishing to PyPI, including linux and windows. I have tried my best to use good tools and practices in this repo to provide a clean codebase for others to start their project on. What you see in this repo is not all my work, but lessons/code I have learned after observing others work.

Key Features

  • C++ Library is independent of Python Extension, i.e. can be dropped into pure C++ projects.

  • Cross platform using Modern CMake.

  • Benchmark (Nanobench) and Testing (doctest) built in.

  • Good handling of thirdparty dependencies using CMake FetchContent.

  • Documentation for both C++ and Python created using Sphinx, Doxygen, Breathe, and Exhale. The documentation is unified into one website.

  • Integration of CMake into setup.py so that pip install works for python users wanting to build manually (CMake must be installed still).

    • Note that the C++ Library and even the python extension can still be built with standard CMake procedures, see Build with CMake

  • Automatic building of python binary wheels using github actions, see Workflow

This repo relies upon using Modern CMake to build both the C++ and Python Extension libraries. I find that integrating it all in CMake leads to a much nicer developer experience. External users building the library will need CMake installed which may be a consideration before using this template repo as a starting point. However, this repo has a github workflow setup to automatically build python binary wheels for you and upload to PyPI for a variety of python versions/OS/architectures! Please see workflows

Instructions For Using Template

  1. git clone https://github.com/JeremyBYU/cpp-pybind-skel.git

Rename Files

You will want to rename files and library names with a simple find and replace using your IDE/editor. Lets say you named your project SimpleImageFilters with an associates short acronym of SIF . Then simply find and replace in this repository the following (case sensitivity matters):

  • CPPLib -> SimpleImageFilters - C++ Top Namespace and CMake Project Name

  • CPPLIB -> SIMPLEIMAGEFILTERS - Same but uppercase, used in CMake

  • CPPL -> SIF - Acronym used in CMake alias for project

  • cpplib -> simpleimagefilters - Python Library Extension Name

A helper python script, rename_project.py is provided if desired. I would recommend using it because it saves a lot of time.

Note: you don’t have to use the naming convention proposed above and may use any you would like. I think the most important thing is simply that the Python extension target is different then C++ library target.

Build Project Manually

You can build the project manually in two ways: one in pure CMake, the other using python setup.py.

Build Manually With CMake

Building happens entirely with CMake. This is meant really only for the library developers who are working on C++ and Python in an edit-compile cycle.

C++ Library
  1. mkdir cmake-build && cd cmake-build

  2. cmake .. - Note - For windows also add -DCMAKE_GENERATOR_PLATFORM=x64

  3. cmake --build . -j$(nproc) --config Release

Build options:

CPPL_BUILD_BENCHMARKS:BOOL=ON // CPPL - Build Benchmarks
CPPL_BUILD_EXAMPLES:BOOL=ON // CPPL - Build Examples
CPPL_BUILD_PYMODULE:BOOL=ON // CPPL -Build Python Module
CPPL_BUILD_TESTS:BOOL=ON // CPPL - Build Tests
CPPL_BUILD_WERROR:BOOL=OFF // CPPL - Add Werror flag to build (turns warnings into errors)
CPPL_WITH_OPENMP:BOOL=ON // CPPL - Build with OpenMP Support
Python Extension

This is meant for advanced python users who are actively developing the extension.

  1. Install conda or create a python virtual environment (Why?). I recommend conda for Windows users.

  2. Perform CMake build as described above

  3. cd cmake-build && cmake --build . --target python-package --config Release

  4. cd lib/python_package &&  pip install -e . . This installs the library in develop/edit mode. To update the python extension in your python virtual environment all you need to do is run step 3 again.