Template for a modern C++ project using CMake.
Read through both the README and the justfile to better understand how everything works.
- Only Linux is supported
- This project uses devcontainers to avoid dependencies polluting the host. Specifically, we use podman instead of Docker, which enables the devcontainer to run on a host that is itself containerized (ie. a GCP Cloud Workstation instance)
- The devcontainer uses
brewfor a few reasons:- We use a non-root user in the container so you can't use the system package manager
- The LLVM build in Fedora's repos lacks debug symbols
- The devcontainer is setup to use fish as the default shell
On the host:
git clone --recurse-submodules https://github.com/rdong8/cpp_project.git
cd cpp_project/Also make sure you have podman installed on the host. For example:
# Fedora
sudo dnf -y install podman
# Ubuntu
sudo apt update
sudo apt -y install podmanThen run id on the host to determine your user's UID and GID. Use that to fill in the build.dockerfile.args.HOST_UID and build.dockerfile.args.HOST_GID values in the devcontainer.json file.
Then build the devcontainer. All commands after this point are to be run in the devcontainer, not on the host.
First ensure you have uv installed. Then:
just venv # Creates a virtual environment
just py-deps # Installs the Python dependencies. Use `just py-deps 1` to force a reinstall.In the devcontainer configuration, a volume has been configured for Conan's cache and configurations so this step only needs to be run once per devcontainer host.
Check if you already have a Conan profile with just list-conan-profiles.
If you haven't already created them, this command will create a default for you:
just create-conan-profile defaultThen, edit the profile with just edit-conan-profile default. For example:
# TODO: brew's LLVM is build with libstdc++, can't use libc++
# [buildenv]
# CXXFLAGS=-isystem ${HOMEBREW_PREFIX}/include/c++/v1
# LDFLAGS=-L${HOMEBREW_PREFIX}/lib -Wl,-rpath,${HOMEBREW_PREFIX}/lib
[conf]
tools.build:compiler_executables={'c': 'clang', 'cpp': 'clang++'}
# TODO: https://github.com/conan-io/conan/issues/15864
# TODO: https://github.com/conan-io/conan/issues/14174
tools.cmake.cmaketoolchain:extra_variables={'CMAKE_LINKER_TYPE': 'MOLD', 'CMAKE_OPTIMIZE_DEPENDENCIES': 'ON'}
tools.cmake.cmaketoolchain:generator=Ninja Multi-Config
[platform_tool_requires]
# Tell Conan to look for CMake on the machine instead of installing it itself
cmake/4.1.1
[settings]
arch=x86_64
compiler=clang
# TODO: https://github.com/conan-io/conan-center-index/issues/26390
compiler.cppstd=23
compiler.libcxx=libstdc++
compiler.version=22
os=LinuxNote that if your compiler.version is too new, you may get an error from Conan. Just edit ~/.conan2/settings.yml and add it there.
Now build the project's C++ dependencies with Conan:
just conan-installThis command runs the CMake configure. Theoretically it only needs to be run once, since the just build command invokes cmake --build which should automatically reconfigure if necessary. In practice if you're having CMake issues, just try rerunning this.
just configAt this point, you may want to restart clangd (clangd: Restart language server in VSCode command palette) so it picks up the new compile commands.
Build a target:
just build target-nameYou can omit the target name to build everything.
The target will end up in ./build/src/path/to/target/build_type/target.
To open the documentation in the default browser (must be built first via just build docs):
just docsYou may also pass a command that will be used to open the index.html file:
just docs firefox
just docs 'flatpak run com.brave.Browser' # You need to use Flatseal to give the flatpak permission in this caseRun all tests:
just testAny flags will be forwarded to ctest, for example:
just test -R math # Run tests matching regular expression "math"While developing, you may want to have some tasks automatically run with pre-commit.
just pre-commitClean the build directory and Conan generated files:
just cleanClean Python files as well:
just clean-allYou'll need to make the project's Conan dependencies and run the CMake config again with just conan-deps config.
You can also delete all installed Conan packages matching a pattern:
just clean-conan 'boost/*'
just clean-conan # Removes everything