-
Cross-platform support: CMake supports multiple operating systems and compilers, allowing the same build configuration to be used in different environments. -
Simplified configuration: Through the CMakeLists.txt file, users can define project structure, dependencies, compilation options, etc., without manually writing complex build scripts. -
Automated building: CMake can automatically detect libraries and tools on the system, reducing the manual configuration workload. -
Flexibility: Supports multiple build types and configurations (such as Debug, Release) and allows users to customize build options and modules.

CMake Basics
File Structure and Basic Syntax:
-
Specify the minimum required version of CMake:
cmake_minimum_required(VERSION <version>)
cmake_minimum_required(VERSION 3.10)
-
Define the project name and the programming languages used:
project(<project_name> [<language>...])
project(MyProject CXX)
-
Specify the executable to be generated and its source files:
add_executable( ...)
add_executable(MyExecutable main.cpp other_file.cpp)
-
Create a library (static or dynamic) and its source files:
add_library( ...)
add_library(MyLibrary STATIC library.cpp)
-
Link target files with other libraries:
target_link_libraries( ...)
target_link_libraries(MyExecutable MyLibrary)
-
Add header file search paths:
include_directories(...)
include_directories(${PROJECT_SOURCE_DIR}/include)
-
Set the value of variables:
set( ...)
set(CMAKE_CXX_STANDARD 11)
-
Set target properties:
target_include_directories(TARGET target_name
[BEFORE | AFTER]
[SYSTEM] [PUBLIC | PRIVATE | INTERFACE]
[items1...])
target_include_directories(MyExecutable PRIVATE ${PROJECT_SOURCE_DIR}/include)
-
Installation rules:
install(TARGETS target1 [target2 ...]
[RUNTIME DESTINATION dir]
[LIBRARY DESTINATION dir]
[ARCHIVE DESTINATION dir]
[INCLUDES DESTINATION [dir ...]]
[PRIVATE_HEADER DESTINATION dir]
[PUBLIC_HEADER DESTINATION dir])
install(TARGETS MyExecutable RUNTIME DESTINATION bin)
-
Conditional statements (if, elseif, else, endif commands)
if(expression)
#Commands
elseif(expression)
#Commands
else()
#Commands
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
message("Debug build")
endif()
11. Custom commands (add_custom_command command):
add_custom_command(
TARGET target
PRE_BUILD | PRE_LINK | POST_BUILD
COMMAND command1 [ARGS] [WORKING_DIRECTORY dir]
[COMMAND command2 [ARGS]]
[DEPENDS [depend1 [depend2 ...]]]
[COMMENT comment]
[VERBATIM]
)
For example:
add_custom_command(
TARGET MyExecutable POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Build completed."
)
Variables and Cache
CMake uses variables to store and pass information, which can be defined and used in the CMakeLists.txt file. Variables can be divided into regular variables and cache variables.
Variable Definition and Usage
Defining a variable:
set(MY_VAR "Hello World")
Using a variable:
message(STATUS "Variable MY_VAR is ${MY_VAR}")
Cache Variables
Cache variables are stored in CMake’s cache file, and users can modify these values during CMake configuration. Cache variables are typically used for user-input settings, such as compilation options and paths.
Defining a cache variable:
set(MY_CACHE_VAR "DefaultValue" CACHE STRING "A cache variable")
Using a cache variable:
message(STATUS "Cache variable MY_CACHE_VAR is ${MY_CACHE_VAR}")
Finding Libraries and Packages
CMake can automatically detect and configure external libraries and packages using the find_package() directive.
Commonly used to find system-installed libraries or third-party libraries.
find_package() directive
Basic usage:
find_package(Boost REQUIRED)
Specify version:
find_package(Boost 1.80 REQUIRED)
Find libraries and specify paths:
find_package(OpenCV REQUIRED PATHS /path/to/opencv)
Using the found libraries:
target_link_libraries(MyExecutable Boost::Boost)
Setting include directories and link directories:
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
Using third-party libraries
Assuming you want to use the Boost library in your project, the CMakeLists.txt file might look like this:
cmake_minimum_required(VERSION 3.10)
project(MyProject CXX)
# Find Boost library
find_package(Boost REQUIRED)
# Add source files
add_executable(MyExecutable main.cpp)
# Link Boost library
target_link_libraries(MyExecutable Boost::Boost)
File Tree
my_project/
├── CMakeLists.txt
├── src/
│ ├── main.cpp
│ ├── module1.cpp
│ └── module1.hpp
├── include/
│ └── my_project/
│ └── module2.hpp
└── build/
A simple CMakeLists.txt template file example:
# Set minimum version required
cmake_minimum_required(VERSION 3.20)
# Define project name and version
project(CMAKE_Learn VERSION 1.0)
# Set C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Find all source files
file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.c")
file(GLOB_RECURSE HEADERS "include/**/*.hpp" "include/**/*.h")
# Add include directories
include_directories(include)
# Create executable
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
# Link libraries, here add
# target_link_libraries(${PROJECT_NAME} PRIVATE needed_library)
# Header-only library
breUtils
target_link_directories(${PROJECT_NAME} PRIVATE /home/breeze/cpp/a_forwork/BreUtils)
# ffmpeg
target_link_directories(${PROJECT_NAME} PRIVATE /usr/local/lib)
target_link_libraries(${PROJECT_NAME} PRIVATE avcodec avformat avutil swscale swresample avfilter avdevice postproc)
# boost
target_link_directories(${PROJECT_NAME} PRIVATE /usr/local/lib)
target_link_libraries(${PROJECT_NAME} PRIVATE boost_system boost_filesystem)
# libjsoncpp
find_package(jsoncpp CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE jsoncpp_lib)
# mysqlcppconn
# set(MYSQL_INCLUDE_DIR /usr/include/mysql-cppconn)
# set(MYSQL_LIBRARY /usr/lib/x86_64-linux-gnu/libmysqlcppconn.so.10)
find_package(mysql-concpp REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE mysqlcppconn)
# macOS
if(APPLE) enable_language(OBJCXX) # Add system libraries and frameworks target_link_libraries(${PROJECT_NAME} PRIVATE "-framework Foundation" )endif()
# Windows
if(WIN32) # Add Windows-specific settings or librariesendif()
# Linux
if(UNIX AND NOT APPLE) # Add Linux-specific settings or librariesendif()
# Install targets
# install(TARGETS ${PROJECT_NAME} DESTINATION bin)
# install(DIRECTORY include/ DESTINATION include/${PROJECT_NAME})
-
CMake Official Website https://cmake.org/CMake -
Official Documentation: https://cmake.org/cmake/help/latest/guide/tutorial/index.html -
Rookie: https://www.runoob.com/cmake/cmake-tutorial.html