Skip to main content

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

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

CMake

  • Option 1
sudo apt-get -y 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

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)

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

ModuleDescriptionUsage
Warnings.cmakeAdds compiler warnings to a target.target_set_warnings(TARGET my-target ENABLE ON AS_ERRORS OFF)
Sanitizer.cmakeAdds analysis tools that help detect undefined behavior, memory errors and more.add_sanitizer_flags()
CodeCoverage.cmakeEnable code coverage analysis.append_coverage_compiler_flags()
Tools.cmakeAdds CppCheck and ClangTidy to target.add_linter_tool_to_target(${LIBRARY_NAME})

Build Steps

Generate

cmake -G "Unix Makefiles" -S . -B build

Build

  • Build all targets
cd build
cmake --build .
  • Build only specific target
cd build
cmake --build . --target my_executable

Source