Using cxxbuild to easily build C++ project with tests and dependencies

Igor Machado
3 min readNov 8, 2023

This is a quick post on cxxbuild, a simple python script to easily build C++ projects with tests and dependencies. The project aims inexperienced developers or even C/C++ experts that may not be experienced with build systems (such as CMake and Bazel), and also package managers (such as Conan and Vcpkg).

This project is the result of several years teaching C/C++ and observing students with same basic difficulties over the years: why is it so simple to do a basic project with dependencies on python and almost impossible to do that on C++?

Most developers on C/C++ simply ignore dependencies and try to build everything on their own… but that’s not practical or healthy for a modern programming language. To deal with dependencies efficiently, on python one can just create a plaintext requirements.txt file, so in the same spirit we propose acxxdeps.txt file, that consists on few important data, like: project name, version number, package manager (could be conan, vcpkg or even direct link to git repository) and linked libraries. The idea of cxxbuild is to parse cxxdeps file and generate a CMakeLists.txt automatically, for cmake users, or even BUILD.bzl files for Bazel users.

Current prototype works for CMake and git repositories already, and can be tried on: https://github.com/manydeps/cxxbuild

Installation is very simple: just copy cxxbuild.py script to your C++ project folder and run it! Now, it is also available in pip installation, with: pip install cxxbuild ; and then just run it on your project folder: cxxbuild .

It is supposed to compile your project in a cross-platform manner (windows, linux and mac), including dependencies specified on cxxdeps. An example of cxxdeps.txt:

fmt == "9.1.0"     [ fmt ]                    git *    https://github.com/fmtlib/fmt.git
Catch2 == "v3.3.1" [ Catch2::Catch2WithMain ] git test https://github.com/catchorg/Catch2.git
m

This is quite simple and powerful, with few lines describing the following:

  • take fmt project from git repository in specific version
  • take Catch2 project from git repository in specific version and use it for tests only
  • take system -lm dependency

Next steps on this project is to cover some tricky dependencies, such as GMP (previously discussed here) and support some few parameters, such as c++ standard version (which is currently fixed on c++20); support for linters (and enforcing them automatically); and some trickly C/C++ compiler extensions such as OpenMP, CUDA, etc. The idea is to have it the simplest way possible, so that one can simply change the script, if it doesn’t like it (typical of C/C++ community), or perhaps use it directly without any issue (I hope so!). To make it work like this, some basic standards were necessary:

  • source code (.cpp, .cc, .c, etc) is located on a src/ folder
  • test code is located on a tests/ folder
  • header only libraries are located on a include/ folder

All of these are common patterns in C/C++, but again, if one does not want to have them, it’s quite easy to change the script.

Support for toml

As requested by some users, cxxbuild currently supports toml format in a cxxdeps.toml file (that automatically generates cxxdeps.txt and cxxdeps.dev.txt files):

[all]
fmt={ git="https://github.com/fmtlib/fmt.git", tag="9.1.0", links=["fmt"] }
m={ links=["m"] }
pthread={}

[test]
catch2={ git="https://github.com/catchorg/Catch2.git", tag="v3.3.1", links=[
"Catch2::Catch2WithMain"
] }

[dev]
bazel=[{ choco=["bazelisk"], platform="windows" }, { npm=["bazelisk"], platform="linux" }]
ninja=[{ choco=["ninja"], platform="windows" }, { apt=["ninja-build"], platform="linux" }]
cmake={ pip=["cmake"], deps=["ninja"] }
conan={ pip=["conan"] }

Acknowledgements

Any ideas or issues on the project, feel free to share them on GitHub. Thanks for those trying to use the tool and helping improving it in early phases, so special thanks to Fellipe Pessanha for advices on toml format.

--

--