Are you just starting with CMake or C++?
Do you need some easy-to-use starting point, but one that has the basic moving parts you are likely going to need on any medium sized project?
Do you believe in test-driven development, or at the very least — write your tests together with the feature code? If so you'd want to start your project pre-integrated with a good testing framework.
Note
This template is mainly focused on Unix-like systems. It should work on Windows as well, but it is not guaranteed.
Divider is a minimal project that's kept deliberately small. It is used to showcase various parts of the CMake template. When you build it using CMake/make (see below) it generates:
- A tiny static library
lib/libdivision.a, - A command line binary
bin/divider, which links with the library,
You will need:
- A modern C++ compiler in the
CXXenvironment variable cmakeversion 3.25+- optionally, it's recommended to also have
First we need to check out the git repo:
❯ mkdir ~/workspace
❯ cd ~/workspace
❯ git clone \
https://github.com/Maneren/cmake-project-template \
my-project
❯ cd my-projectthen either install GoogleTest from your favorite package manager (preferably) or fetch the git submodule:
❯ git submodule update --initThe project source files are split into 3 folders:
srccontains the library code- here should be the bulk of the logic, classes, etc.
appscontains the application code- here should be the frontend and the main function
testcontains the tests
More on specific subfolders in [[#project-structure]].
Building is done with CMake in two steps:
-
Configure
mkdir build cd build cmake .. -
Build
(still in the
buildfolder)make
There is a Justfile that simplifies this process. It uses (opinionated) recommended defaults – Ninja Multi-Config generator and clang++ compiler (those can be overridden in the Justfile).
just configure
just build [Debug|Release|RelWithDebInfo|MinSizeRel] [target]❯ cd build && ctest
Start 1: DividerTest.5_DivideBy_2
1/5 Test #1: DividerTest.5_DivideBy_2 ......... Passed 0.00 sec
Start 2: DividerTest.9_DivideBy_3
2/5 Test #2: DividerTest.9_DivideBy_3 ......... Passed 0.00 sec
Start 3: DividerTest.17_DivideBy_19
3/5 Test #3: DividerTest.17_DivideBy_19 ....... Passed 0.00 sec
Start 4: DividerTest.Long_DivideBy_Long
4/5 Test #4: DividerTest.Long_DivideBy_Long ... Passed 0.00 sec
Start 5: DividerTest.DivisionByZero
5/5 Test #5: DividerTest.DivisionByZero ....... Passed 0.00 sec
100% tests passed, 0 tests failed out of 5
Total Test time (real) = 0.01 secAgain, with Just it's a one-liner:
just testWithout arguments, it prints out its usage:
❯ bin/divider
Divider © 2018 Monkey Claps Inc.
Usage:
divider <numerator> <denominator>
Description:
Computes the result of a fractional division,
and reports both the result and the remainder.But with arguments, it computes as expected the denominator:
❯ build/bin/Debug/divider 112443477 12309324
Divider © 2018 Monkey Claps Inc.
Division : 112443477 / 12309324 = 9
Remainder: 112443477 % 12309324 = 1659561And lastly, with Just it's again as simple as:
just run [Debug|Release|RelWithDebInfo|MinSizeRel] [...args]Debug is the CMake build type, so it can be also Release, RelWithDebInfo or MinSizeRel.
We build a static library that, given a simple fraction will return the integer result of the division, and the remainder.
We can use it from C++ like so:
#include <division/division.h>
#include <iostream>
const auto f = division::Fraction{.numerator = 25, .denominator = 7};
const auto r = division::Division(f).divide();
std::cout << "Result of the division is " << r.division;
std::cout << "Remainder of the division is " << r.remainder;The template automatically recognizes new files and subfolders with source files but when adding a more significant part of the project, like a new application or library (both internal and external), you have to reconfigure the project.
This is done similarly to the initial build:
cd build
cmake ..or with Just:
just configureWhen encountering issues with CMake or compilation, first try clean building:
rm -rf build
mkdir build
cd build
cmake ..or
just clean configuresrc– library codeexternal– external libraries*– individual project librariessrc– private source filesinclude/*– public headers
apps- application code*- individual project applicationssrc- source files
testexternal– external libraries used for tests (e.g. Google Test)unit– unit tests*– unit tests for each library**/*.cpp– should mirror corresponding source files
CMakeLists.txt– add unit tests to this file
*– other test types (e.g. integration, end-to-end, etc.)- structure should mirror that of
test/unit - add this subfolder to
test/CMakeLists.txt
- structure should mirror that of
cmake– CMake helpers
Read through the sample divider project to understand the details.
The template by default sets the following compiler flags:
- for all build configurations
-std=c++${DEFAULT_CXX_STD}– specify C++ standard-Wall -Wextra -Wpedantic– enable as many warnings as possible
- for
Debugbuild configuration-Og– enable a few optimizations that improve debug information-fsanitize=address,undefined,leak,bounds,signed-integer-overflow- use all basic sanitizers for runtime safety checking (modern replacement
for
valgrindmemcheck)
- use all basic sanitizers for runtime safety checking (modern replacement
for
- for
DebugandRelWithDebInfobuild configurations-g3 -gdwarf-5– enable debug information in the Dwarf format-fno-omit-frame-pointer– enable frame pointer for better debugging
- for
ReleaseandRelWithDebInfobuild configurations-O3– enable aggressive optimizations-flto– link-time optimization
You can add additional flags with CMAKE_CXX_FLAGS or
CMAKE_CXX_FLAGS_${BUILD_TYPE} and other common environment variables.
For more info see the cmake/CommonUtils.cmake file, where they are set, and
build/compile_commands.json, where the effective compilation commands are.
© 2017-2019 Konstantin Gredeskoul. 2025-present Maneren
Open sourced under MIT license, the terms of which can be read here — MIT License.
This project is a derivative of the CMake Tutorial, and is aimed at saving time for starting new projects in C++ that use CMake and GoogleTest.