CMake
CMake is an open-source, cross-platform build system generator. It is a tool that is used to generate build scripts for a variety of different build systems, including makefiles, Visual Studio projects, and Xcode projects. CMake is often used in place of traditional build systems because it is more flexible and can generate build scripts for multiple platforms and compilers.
Install
Prerequisites
- Linux
- Windows
- Mac
Visual Studio Code and extensions:
ms-vscode.cmake-toolsMandotary
sudo apt-get -y install build-essential git
- Optional
sudo apt-get -y install \
doxygen python3 python3-pip lcov gcovr ccache cppcheck llvm clang-format clang-tidy
Visual Studio Code and extensions:
ms-vscode.cmake-tools,ms-vscode-remote.remote-wslMandotary
sudo apt-get -y install build-essential git
- Optional
sudo apt-get -y install \
doxygen python3 python3-pip lcov gcovr ccache cppcheck llvm clang-format clang-tidy
- Compiler Setup
- Visual Studio Code and extensions:
ms-vscode.cmake-tools - Brew
brew install git make doxygen lcov gcovr ccache
CMake
- Linux
- Windows
- Mac
brew install cmake
Setup
Project
CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
execute_process(
COMMAND git describe --tags
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE PROJECT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
project(MyProject VERSION ${PROJECT_VERSION} LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
option(BUILD_TESTS "Whether to build the tests." OFF)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/)
add_subdirectory(app)
add_subdirectory(src)
if (BUILD_TESTS)
add_subdirectory(tests)
endif()
Library
- Shared
- Static
src/CMakeLists.txt
add_library(my_library SHARED my_library.cc)
target_include_directories(my_library PUBLIC "./")
install(TARGETS my_library)
install(FILES my_library.h DESTINATION include)
src/CMakeLists.txt
add_library(my_library STATIC my_library.cc)
target_include_directories(my_library PUBLIC "./")
install(TARGETS my_library)
install(FILES my_library.h DESTINATION include)
Executable
app/CMakeLists.txt
add_executable(my_executable main.cc)
target_link_libraries(my_executable PUBLIC my_library)
install(TARGETS my_executable)
Configured
src/config.h.in
#ifndef CONFIG_H_
#define CONFIG_H_
#include <cstdint>
#include <string_view>
static constexpr std::string_view project_name = "@PROJECT_NAME@";
static constexpr std::string_view project_version = "@PROJECT_VERSION@";
static constexpr std::string_view project_git_commit_hash = "@GIT_COMMIT_HASH@";
static constexpr std::int32_t project_version_major {@PROJECT_VERSION_MAJOR@};
static constexpr std::int32_t project_version_minor {@PROJECT_VERSION_MINOR@};
static constexpr std::int32_t project_version_patch {@PROJECT_VERSION_PATCH@};
#endif // CONFIG_H_
src/CMakeLists.txt
execute_process(
COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
configure_file(
"config.h.in"
"${CMAKE_BINARY_DIR}/configured_files/include/config.h" ESCAPE_QUOTES
)
Third Party
CMakeLists.txt
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.12.0
GIT_SHALLOW TRUE)
FetchContent_MakeAvailable(googletest)
Tests
tests/CMakeLists.txt
set(TESTS_TARGET_NAME "unittests")
add_executable(${TESTS_TARGET_NAME} unittests.cc)
target_include_directories(${TESTS_TARGET_NAME} "./")
target_link_libraries(${TESTS_TARGET_NAME}
my_library
gtest
gtest_main
)
Misc
| Module | Description | Usage |
|---|---|---|
| Warnings.cmake | Adds compiler warnings to a target. | target_set_warnings(TARGET my-target ENABLE ON AS_ERRORS OFF) |
| Sanitizer.cmake | Adds analysis tools that help detect undefined behavior, memory errors and more. | add_sanitizer_flags() |
| CodeCoverage.cmake | Enable code coverage analysis. | append_coverage_compiler_flags() |
| Tools.cmake | Adds CppCheck and ClangTidy to target. | add_linter_tool_to_target(${LIBRARY_NAME}) |
Build Steps
Generate
- Makefile
- MSVC
- Ninja (Android)
- Makefile (Cross Compile)
cmake -G "Unix Makefiles" -S . -B build
cmake -G "Visual Studio 17 2022" -A x64 -S . -B build
export ANDROID_ABI="arm64-v8a"
export ANDROID_NATIVE_API_LEVEL="29"
export ANDROID_PLATFORM="android-${ANDROID_NATIVE_API_LEVEL}"
export CMAKE_SYSTEM_VERSION="23"
export NDK_VERSION="21.1.6352462"
cmake \
-G "Ninja" \
-S . \
-B build \
--toolchain ${HOME}/Android/Sdk/ndk/${NDK_VERSION}/build/cmake/android.toolchain.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_ABI=${ANDROID_ABI} \
-DCMAKE_ANDROID_ARCH_ABI=${ANDROID_ABI} \
-DANDROID_PLATFORM=${ANDROID_PLATFORM} \
-DANDROID_NDK=${HOME}/Android/Sdk/ndk/${NDK_VERSION} \
-DCMAKE_ANDROID_NDK=${HOME}/Android/Sdk/ndk/${NDK_VERSION} \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_MAKE_PROGRAM=${HOME}/Android/Sdk/cmake/3.18.1/bin/ninja \
-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION} \
-DCMAKE_SYSTEM_NAME=Android
cmake \
-G "Unix Makefiles" \
-S . \
-B build \
--toolchain ${CMAKE_SOURCE_DIR}/cmake/<my-toolchain>.cmake
Build
- Build all targets
cd build
cmake --build .
- Build only specific target
cd build
cmake --build . --target my_executable
Source
- Udemy Course CMake, Tests and Tooling for C/C++ Projects by Jan Schaffranek
- Github Repository CppProjectTemplate by Jan Schaffranek