CMake Cheatsheet¶
Überblick¶
CMake ist ein plattformübergreifendes Build-System-Generator, der plattformunabhängige Konfigurationsdateien verwendet, um native Build-Tool-Dateien (Makefiles, Visual Studio-Projekte, Xcode-Projekte usw.) zu generieren.
Installation¶
Paketmanager¶
[Placeholder for text 2]
[Placeholder for text 3]
[Placeholder for text 4]
[Placeholder for text 5]
[Placeholder for text 6]
[Placeholder for text 7]
[Placeholder for text 8]
[Placeholder for text 9]
[Placeholder for text 10]
[Placeholder for text 11]
[Placeholder for text 12]
[Placeholder for text 13]
[Placeholder for text 14]
[Placeholder for text 15]
[Placeholder for text 16]
[Placeholder for text 17]
[Placeholder for text 18]
[Placeholder for text 19]
[Placeholder for text 20]
Would you like me to fill in the other placeholders? If you provide the specific text for each section, I can translate them accordingly.```bash
Ubuntu/Debian¶
sudo apt install cmake
macOS¶
brew install cmake
CentOS/RHEL¶
sudo yum install cmake
Windows (Chocolatey)¶
choco install cmake
From source¶
wget https://cmake.org/files/v3.25/cmake-3.25.0.tar.gz tar -xzf cmake-3.25.0.tar.gz cd cmake-3.25.0 && ./bootstrap && make && sudo make install
CMakeLists.txt # Configuration file Target # Executable, library, or custom target Generator # Tool that creates build files Cache # Stored configuration variables Out-of-source # Build directory separate from source project/ ├── CMakeLists.txt ├── src/ │ ├── main.cpp │ └── utils.cpp ├── include/ │ └── utils.h └── build/ # Out-of-source build directory## Basic CMakeLists.txt
### Minimal Example
```cmake
cmake_minimum_required(VERSION 3.10)
project(MyProject)
set(CMAKE_CXX_STANDARD 17)
add_executable(myapp main.cpp)
Simple Library¶
cmake_minimum_required(VERSION 3.10)
project(MyProject VERSION 1.0.0)
# Set C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Add library
add_library(mylib utils.cpp network.cpp)
# Add executable
add_executable(myapp main.cpp)
# Link library to executable
target_link_libraries(myapp mylib)
Variables¶
Built-in Variables¶
# Project information
$\\\\{PROJECT_NAME\\\\}
$\\\\{PROJECT_VERSION\\\\}
$\\\\{PROJECT_SOURCE_DIR\\\\}
$\\\\{PROJECT_BINARY_DIR\\\\}
# System information
$\\\\{CMAKE_SYSTEM_NAME\\\\} # Linux, Windows, Darwin
$\\\\{CMAKE_SYSTEM_VERSION\\\\}
$\\\\{CMAKE_SYSTEM_PROCESSOR\\\\}
# Compiler information
$\\\\{CMAKE_CXX_COMPILER\\\\}
$\\\\{CMAKE_CXX_COMPILER_ID\\\\} # GNU, Clang, MSVC
$\\\\{CMAKE_CXX_COMPILER_VERSION\\\\}
# Build information
$\\\\{CMAKE_BUILD_TYPE\\\\} # Debug, Release, RelWithDebInfo
$\\\\{CMAKE_CURRENT_SOURCE_DIR\\\\}
$\\\\{CMAKE_CURRENT_BINARY_DIR\\\\}
Setting Variables¶
# Set variable
set(SOURCES main.cpp utils.cpp)
set(MY_VAR "value")
# List operations
list(APPEND SOURCES network.cpp)
list(REMOVE_ITEM SOURCES main.cpp)
list(LENGTH SOURCES NUM_SOURCES)
# String operations
string(TOUPPER $\\\\{PROJECT_NAME\\\\} PROJECT_NAME_UPPER)
string(REPLACE "old" "new" NEW_STRING $\\\\{OLD_STRING\\\\})
# Cache variables
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries")
Targets¶
Executables¶
# Simple executable
add_executable(myapp main.cpp)
# Executable with multiple sources
add_executable(myapp
main.cpp
utils.cpp
network.cpp
)
# Executable with variable sources
set(SOURCES main.cpp utils.cpp)
add_executable(myapp $\\\\{SOURCES\\\\})
Libraries¶
# Static library
add_library(mylib STATIC utils.cpp network.cpp)
# Shared library
add_library(mylib SHARED utils.cpp network.cpp)
# Header-only library
add_library(mylib INTERFACE)
target_include_directories(mylib INTERFACE include/)
# Object library
add_library(mylib OBJECT utils.cpp network.cpp)
add_executable(myapp main.cpp $<TARGET_OBJECTS:mylib>)
Target Properties¶
# Set target properties
set_target_properties(myapp PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
OUTPUT_NAME "my_application"
)
# Include directories
target_include_directories(myapp
PRIVATE include/
PUBLIC $\\\\{CMAKE_CURRENT_SOURCE_DIR\\\\}/public_include/
)
# Compile definitions
target_compile_definitions(myapp
PRIVATE DEBUG_MODE
PUBLIC API_VERSION=2
)
# Compile options
target_compile_options(myapp
PRIVATE -Wall -Wextra
PUBLIC -fPIC
)
# Link libraries
target_link_libraries(myapp
PRIVATE mylib
PUBLIC pthread
)
Finding Packages¶
find_package¶
# Find required package
find_package(Threads REQUIRED)
target_link_libraries(myapp Threads::Threads)
# Find optional package
find_package(OpenSSL)
if(OpenSSL_FOUND)
target_link_libraries(myapp OpenSSL::SSL OpenSSL::Crypto)
target_compile_definitions(myapp PRIVATE HAVE_OPENSSL)
endif()
# Find package with components
find_package(Boost REQUIRED COMPONENTS system filesystem)
target_link_libraries(myapp Boost::system Boost::filesystem)
# Find package with version
find_package(Qt5 5.10 REQUIRED COMPONENTS Core Widgets)
target_link_libraries(myapp Qt5::Core Qt5::Widgets)
pkg-config¶
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
target_include_directories(myapp PRIVATE $\\\\{GTK3_INCLUDE_DIRS\\\\})
target_link_libraries(myapp $\\\\{GTK3_LIBRARIES\\\\})
target_compile_options(myapp PRIVATE $\\\\{GTK3_CFLAGS_OTHER\\\\})
Conditional Logic¶
if/else/endif¶
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(myapp PRIVATE DEBUG_MODE)
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
target_compile_definitions(myapp PRIVATE RELEASE_MODE)
endif()
# Platform-specific code
if(WIN32)
target_sources(myapp PRIVATE windows_specific.cpp)
elseif(UNIX)
target_sources(myapp PRIVATE unix_specific.cpp)
endif()
# Compiler-specific options
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(myapp PRIVATE -Wall -Wextra)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(myapp PRIVATE /W4)
endif()
option¶
option(BUILD_TESTS "Build test programs" ON)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
if(BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
Functions and Macros¶
Functions¶
function(add_my_executable name)
add_executable($\\\\{name\\\\} $\\\\{ARGN\\\\})
target_compile_features($\\\\{name\\\\} PRIVATE cxx_std_17)
target_compile_options($\\\\{name\\\\} PRIVATE -Wall -Wextra)
endfunction()
# Usage
add_my_executable(myapp main.cpp utils.cpp)
Macros¶
macro(set_default_build_type)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
endif()
endmacro()
# Usage
set_default_build_type()
Advanced Functions¶
function(add_library_with_alias target_name)
set(options SHARED STATIC)
set(oneValueArgs ALIAS)
set(multiValueArgs SOURCES HEADERS)
cmake_parse_arguments(ARG "$\\\\{options\\\\}" "$\\\\{oneValueArgs\\\\}" "$\\\\{multiValueArgs\\\\}" $\\\\{ARGN\\\\})
if(ARG_SHARED)
add_library($\\\\{target_name\\\\} SHARED $\\\\{ARG_SOURCES\\\\})
else()
add_library($\\\\{target_name\\\\} STATIC $\\\\{ARG_SOURCES\\\\})
endif()
if(ARG_ALIAS)
add_library($\\\\{ARG_ALIAS\\\\} ALIAS $\\\\{target_name\\\\})
endif()
endfunction()
# Usage
add_library_with_alias(mylib
SHARED
ALIAS MyNamespace::mylib
SOURCES utils.cpp network.cpp
)
Testing¶
CTest Integration¶
enable_testing()
# Add test executable
add_executable(test_utils test_utils.cpp)
target_link_libraries(test_utils mylib)
# Add test
add_test(NAME test_utils COMMAND test_utils)
# Test with arguments
add_test(NAME test_with_args COMMAND myapp --test --verbose)
# Test properties
set_tests_properties(test_utils PROPERTIES
TIMEOUT 30
WORKING_DIRECTORY $\\\\{CMAKE_CURRENT_BINARY_DIR\\\\}
)
Google Test Integration¶
find_package(GTest REQUIRED)
add_executable(unit_tests
test_main.cpp
test_utils.cpp
)
target_link_libraries(unit_tests
mylib
GTest::GTest
GTest::Main
)
# Discover tests automatically
include(GoogleTest)
gtest_discover_tests(unit_tests)
Installation¶
Basic Installation¶
```cmake
Install executable¶
install(TARGETS myapp RUNTIME DESTINATION bin )
Install library¶
install(TARGETS mylib LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin )
Install headers¶
install(DIRECTORY include/ DESTINATION include FILES_MATCHING PATTERN "*.h" )
Install files¶
install(FILES config.txt
DESTINATION etc
)
### Paketconfigurationcmake
Generate package config files¶
include(CMakePackageConfigHelpers)
Create config file¶
configure_package_config_file( $\\{CMAKE_CURRENT_SOURCE_DIR\\}/Config.cmake.in $\\{CMAKE_CURRENT_BINARY_DIR\\}/MyProjectConfig.cmake INSTALL_DESTINATION lib/cmake/MyProject )
Create version file¶
write_basic_package_version_file( $\\{CMAKE_CURRENT_BINARY_DIR\\}/MyProjectConfigVersion.cmake VERSION $\\{PROJECT_VERSION\\} COMPATIBILITY SameMajorVersion )
Install config files¶
install(FILES $\\{CMAKE_CURRENT_BINARY_DIR\\}/MyProjectConfig.cmake $\\{CMAKE_CURRENT_BINARY_DIR\\}/MyProjectConfigVersion.cmake DESTINATION lib/cmake/MyProject )
Export targets¶
install(EXPORT MyProjectTargets
FILE MyProjectTargets.cmake
NAMESPACE MyProject::
DESTINATION lib/cmake/MyProject
)
## Generator-Ausdrückecmake
Build type specific¶
target_compile_definitions(myapp PRIVATE
\(<\)
Platform specific¶
target_compile_definitions(myapp PRIVATE
\(<\)
Compiler specific¶
target_compile_options(myapp PRIVATE
\(<\)### Grundlegende Generator-Ausdrückecmake
Target properties¶
target_include_directories(myapp PRIVATE
$
Conditional linking¶
target_link_libraries(myapp
\(<\)
File operations¶
target_sources(myapp PRIVATE
\(<\)### Fortgeschrittene Generator-Ausdrückebash
Configure (generate build files)¶
cmake -S . -B build
Build¶
cmake --build build
Install¶
cmake --install build
Test¶
cd build && ctest
Clean¶
cmake --build build --target clean
## Befehlszeilenverwendungbash
Set build type¶
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
Set variables¶
cmake -S . -B build -DBUILD_TESTS=ON -DBUILD_SHARED_LIBS=ON
Set generator¶
cmake -S . -B build -G "Unix Makefiles" cmake -S . -B build -G "Ninja" cmake -S . -B build -G "Visual Studio 16 2019"
Set toolchain¶
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
Parallel build¶
cmake --build build --parallel 4
cmake --build build -j 4
### Grundlegende Befehlebash
Configure with preset¶
cmake --preset=default
Build specific target¶
cmake --build build --target myapp
Install to custom prefix¶
cmake --install build --prefix /opt/myapp
Run specific test¶
cd build && ctest -R test_utils
Verbose output¶
cmake --build build --verbose
ctest --verbose
### Konfigurationsoptionencmake
if(WIN32)
# Windows-specific code
target_compile_definitions(myapp PRIVATE PLATFORM_WINDOWS)
elseif(APPLE)
# macOS-specific code
target_compile_definitions(myapp PRIVATE PLATFORM_MACOS)
elseif(UNIX)
# Linux/Unix-specific code
target_compile_definitions(myapp PRIVATE PLATFORM_LINUX)
endif()
### Erweiterte Verwendungcmake
toolchain-mingw.cmake¶
set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Usage¶
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=toolchain-mingw.cmake
## Plattformübergreifende Entwicklungcmake
cmake_minimum_required(VERSION 3.15)
project(MyProject VERSION 1.0.0 DESCRIPTION "My awesome project" LANGUAGES CXX )
Only do these if this is the main project¶
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(CMAKE_CXX_EXTENSIONS OFF) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
include(CTest)
if(BUILD_TESTING)
add_subdirectory(tests)
endif()
endif()
Add subdirectories¶
add_subdirectory(src)
add_subdirectory(external)
### Plattformerkennungcmake
Use target-based approach¶
target_include_directories(mylib PUBLIC
\(<BUILD_INTERFACE:\)\\{CMAKE_CURRENT_SOURCE_DIR\\}/include>
$
Use imported targets¶
find_package(Threads REQUIRED) target_link_libraries(myapp PRIVATE Threads::Threads)
Use generator expressions¶
target_compile_features(myapp PRIVATE cxx_std_17)
Avoid global commands¶
Don't use: include_directories(), link_directories(), add_definitions()¶
Use target-specific commands instead¶
### Toolchain-Dateiencmake
Check CMake version¶
cmake_minimum_required(VERSION 3.15)
Validate variables¶
if(NOT DEFINED PROJECT_VERSION) message(FATAL_ERROR "PROJECT_VERSION must be defined") endif()
Check for required files¶
if(NOT EXISTS "$\\{CMAKE_CURRENT_SOURCE_DIR\\}/src/main.cpp") message(FATAL_ERROR "main.cpp not found") endif()
Validate options¶
if(BUILD_TYPE AND NOT BUILD_TYPE MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)$")
message(FATAL_ERROR "Invalid BUILD_TYPE: $\\{BUILD_TYPE\\}")
endif()
## Best Practicescmake
Print variables¶
message(STATUS "CMAKE_BUILD_TYPE: $\\{CMAKE_BUILD_TYPE\\}") message(STATUS "CMAKE_CXX_COMPILER: $\\{CMAKE_CXX_COMPILER\\}")
Print all variables¶
get_cmake_property(_variableNames VARIABLES) foreach(_variableName \(\\\\{_variableNames\\\\}) message(STATUS "\)\\{_variableName\\}=\(\\\\{\)\\{_variableName\\}\\}") endforeach()
Print target properties¶
get_target_property(MYAPP_SOURCES myapp SOURCES)
message(STATUS "myapp sources: $\\{MYAPP_SOURCES\\}")
### Projektstrukturbash
Verbose makefile¶
cmake -S . -B build -DCMAKE_VERBOSE_MAKEFILE=ON
Debug find_package¶
cmake -S . -B build --debug-find
Trace execution¶
cmake -S . -B build --trace
Debug output¶
cmake -S . -B build --debug-output ```### Moderne CMake-Muster https://cmake.org/documentation/##
Fehlerbehandlung¶
https://cmake.org/cmake/help/latest/guide/tutorial/#
Debugging¶
https://cliutils.gitlab.io/modern-cmake/##
Debug-Ausgabe¶
https://github.com/ttroy50/cmake-examples##