目录
1.CMakeLists.txt基本结构
CMakeLists.txt 是 CMake 构建系统的核心配置文件,采用命令式语法组织项目结构和编译流程。主要用于定义项目的构建规则、依赖关系、编译选项等。每个 CMake 项目通常都有一个或多个 CMakeLists.txt 文件。
一个完整的 CMakeLists.txt 通常包含以下部分:
cpp
# 1. CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)
# 2. 项目信息
project(MyProject VERSION 1.0.0 LANGUAGES CXX)
# 3. 全局配置(可选)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # 生成 compile_commands.json
# 4. 查找依赖(可选)
find_package(Threads REQUIRED)
find_package(Boost 1.70 COMPONENTS system REQUIRED)
# 5. 添加子目录(可选)
add_subdirectory(src)
add_subdirectory(tests)
# 6. 定义目标(可执行文件或库)
add_executable(myapp main.cpp)
add_library(mylib STATIC src/lib.cpp src/utils.cpp)
# 7. 配置目标属性
target_include_directories(mylib PUBLIC include)
target_link_libraries(myapp PRIVATE mylib Threads::Threads)
target_compile_definitions(myapp PRIVATE DEBUG_MODE=1)
# 8. 安装规则(可选)
install(TARGETS myapp DESTINATION bin)
install(FILES include/mylib.h DESTINATION include)
# 9. 测试配置(可选)
enable_testing()
add_test(NAME MyTest COMMAND myapp_test)
2.核心语法规则
1.命令格式
cpp
command(arg1 arg2 ...) # 命令名不区分大小写,但参数区分
- 命令和参数用空格或括号分隔。
- 参数可用双引号括起(如包含空格时):
set(NAME "My Project")
。
2.变量引用
cpp
set(SOURCE_FILES main.cpp src/foo.cpp)
add_executable(myapp ${SOURCE_FILES}) # 使用 ${} 引用变量
- 变量作用域:当前目录及子目录,可用
PARENT_SCOPE
提升作用域。
3.注释
cpp
# 单行注释
4.条件语句
cpp
if(WIN32)
set(PLATFORM_LIBS ws2_32)
else()
set(PLATFORM_LIBS pthread)
endif()
target_link_libraries(myapp PRIVATE ${PLATFORM_LIBS})
- 条件表达式:
WIN32
、APPLE
、UNIX
、DEFINED var
、NOT
、AND
、OR
等。
5.循环
cpp
foreach(file IN LISTS source_files)
message("Processing file: ${file}")
endforeach()
6.函数和宏
cpp
# 函数(有独立作用域)
function(print_info name)
message("Project name: ${name}")
endfunction()
# 宏(直接替换)
macro(add_example name)
add_executable(${name} examples/${name}.cpp)
endmacro()
print_info(${PROJECT_NAME})
add_example(example1)
3.关键命令详解
1.项目设置
cmake_minimum_required(VERSION <version>)
:指定所需的最低 CMake 版本。project(<name> [VERSION <ver>] [LANGUAGES <langs>])
:定义项目名称、版本和支持的语言。
示例如下:
cpp
#1
cmake_minimum_required(VERSION 3.10)
#2
project(MyProject CXX)
2.目标定义
add_executable(<name> <sources>)
:创建可执行文件。add_library(<name> [STATIC|SHARED|MODULE] <sources>)
:创建库(静态 / 共享 / 模块)。add_custom_target(<name> [COMMAND <cmd>] [DEPENDS <deps>])
:创建自定义目标(如构建脚本)。
示例代码:
cpp
#1
add_executable(MyExecutable main.cpp other_file.cpp)
#2
add_library(MyLibrary STATIC library.cpp)
#3
add_library(MyLibrary SHARED library.cpp)
3.依赖管理
find_package(<package> [REQUIRED] [VERSION <ver>])
:查找并导入外部包。add_subdirectory(<dir>)
:添加子目录中的 CMakeLists.txt。target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <libs>)
:链接库到目标。
include_directories(<dirs>...)
示例代码:
cpp
#1
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network)
find_package(Qt${QT_VERSION_MAJOR} CONFIG REQUIRED COMPONENTS Widgets Network)
#2
add_subdirectory(tutorial)
#3
target_link_libraries(QSimpleUpdater PUBLIC Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Widgets PRIVATE Qt${QT_VERSION_MAJOR}::Network)
#4
include_directories(${PROJECT_SOURCE_DIR}/include)
4.编译选项
target_include_directories(<target> <PRIVATE|PUBLIC|INTERFACE> <dirs>)
:添加头文件搜索路径。target_compile_definitions(<target> <PRIVATE|PUBLIC|INTERFACE> <defs>)
:添加编译定义(如-DDEBUG
)。target_compile_options(<target> <PRIVATE|PUBLIC|INTERFACE> <options>)
:添加编译选项(如-Wall
)。
示例代码:
cpp
#1
target_include_directories(QSimpleUpdater PUBLIC include)
5.安装规则
cpp
install(TARGETS target1 [target2 ...]
[RUNTIME DESTINATION dir]
[LIBRARY DESTINATION dir]
[ARCHIVE DESTINATION dir]
[INCLUDES DESTINATION [dir ...]]
[PRIVATE_HEADER DESTINATION dir]
[PUBLIC_HEADER DESTINATION dir])
示例代码:
cpp
#1
install(TARGETS <targets>
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static)
install(FILES <files> DESTINATION include)
install(DIRECTORY <dir> DESTINATION share)
#2
install(TARGETS MyExecutable RUNTIME DESTINATION bin)
6.自定义命令 (add_custom_command 命令)
cpp
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]
)
示例代码:
cpp
add_custom_command(
TARGET MyExecutable POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Build completed."
)
7.测试配置
cpp
enable_testing()
add_test(NAME <test_name> COMMAND <executable> <args>)
add_test(NAME <test_name> WORKING_DIRECTORY <dir> COMMAND <cmd>)
4.常用预定义变量
1. 项目信息
变量名 | 描述 | 示例值 |
---|---|---|
PROJECT_NAME |
当前项目名称 | MyProject |
PROJECT_VERSION |
项目版本(通过 project() 设置) |
1.2.3 |
PROJECT_SOURCE_DIR |
当前项目的源目录 | /path/to/myproject |
PROJECT_BINARY_DIR |
当前项目的构建目录 | /path/to/myproject/build |
2.路径相关
变量名 | 描述 | 示例值 |
---|---|---|
CMAKE_SOURCE_DIR |
顶级 CMakeLists.txt 所在目录 | /path/to/myproject |
CMAKE_BINARY_DIR |
顶级构建目录 | /path/to/myproject/build |
CMAKE_CURRENT_SOURCE_DIR |
当前 CMakeLists.txt 所在目录 | /path/to/myproject/src |
CMAKE_CURRENT_BINARY_DIR |
当前构建目录 | /path/to/myproject/build/src |
CMAKE_INSTALL_PREFIX |
安装路径前缀 | /usr/local (默认) |
LIBRARY_OUTPUT_PATH | 库文件输出的默认路径 | 库路径不设置的话,默认放在BINARY_DIR下,即构建时执行cmake命令的目录下 |
3.构建配置
变量名 | 描述 | 示例值 |
---|---|---|
CMAKE_BUILD_TYPE |
构建类型 | Debug , Release , RelWithDebInfo |
CMAKE_C_COMPILER |
C 编译器路径 | /usr/bin/gcc |
CMAKE_CXX_COMPILER |
C++ 编译器路径 | /usr/bin/g++ |
CMAKE_CXX_STANDARD |
C++ 标准版本 | 11 , 14 , 17 , 20 |
CMAKE_GENERATOR |
当前使用的生成器 | Unix Makefiles , Ninja |
CMAKE_C_STANDARD_REQUIRED | * ON :若编译器不支持指定的 C 标准,CMake 会终止配置并报错。 * OFF (默认):若编译器不支持,CMake 会尝试降级到兼容版本(可能导致意外行为)。 |
set(CMAKE_C_STANDARD 11) # 指定 C 语言标准为 C11 set(CMAKE_C_STANDARD_REQUIRED ON) # 强制要求此标准 |
CMAKE_CXX_STANDARD_REQUIRED | * ON :若编译器不支持指定的 C++ 标准,CMake 会终止配置并报错。 * OFF (默认):若编译器不支持,CMake 会尝试降级到兼容版本(可能导致意外行为)。 |
set(CMAKE_CXX_STANDARD 20) # 指定 C++ 标准为 C++20 set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制要求此标准 |
CMAKE_DEBUG_POSTFIX | cpp 设置调试版本后缀 |
set(CMAKE_DEBUG_POSTFIX d) |
4.系统信息
变量名 | 描述 | 示例值 |
---|---|---|
CMAKE_SYSTEM_NAME |
操作系统名称 | Linux , Windows , Darwin |
CMAKE_SYSTEM_VERSION |
系统版本 | 10.0 (Windows) |
CMAKE_HOST_SYSTEM_PROCESSOR |
处理器架构 | x86_64 , arm64 |
5.目标属性(Target Properties)
通过 set_target_properties
或 get_target_property
操作,影响特定目标的行为。
常用属性
属性名 | 描述 | 设置命令 |
---|---|---|
OUTPUT_NAME |
输出文件名 | set_target_properties(myapp PROPERTIES OUTPUT_NAME "custom_name") |
VERSION |
库版本号 | set_target_properties(mylib PROPERTIES VERSION "1.2.3") |
SOVERSION |
共享库 API 版本 | set_target_properties(mylib PROPERTIES SOVERSION "1") |
COMPILE_DEFINITIONS |
编译定义(如 -DDEBUG ) |
target_compile_definitions(myapp PRIVATE DEBUG) |
INCLUDE_DIRECTORIES |
头文件搜索路径 | target_include_directories(myapp PUBLIC include) |
LINK_LIBRARIES |
链接库 | target_link_libraries(myapp PRIVATE pthread) |
POSITION_INDEPENDENT_CODE |
是否生成位置无关代码(共享库必需) | set_target_properties(mylib PROPERTIES POSITION_INDEPENDENT_CODE ON) |
5.变量和缓存
CMake 使用变量来存储和传递信息,这些变量可以在 CMakeLists.txt 文件中定义和使用。
变量可以分为普通变量和缓存变量。
1.变量定义与使用
定义变量:
cpp
set(MY_VAR "Hello World")
使用变量:
cpp
message(STATUS "Variable MY_VAR is ${MY_VAR}")
2.缓存变量
缓存变量存储在 CMake 的缓存文件中,用户可以在 CMake 配置时修改这些值。缓存变量通常用于用户输入的设置,用户可通过命令行(-D
)或 CMake GUI 修改,例如编译选项和路径。
定义缓存变量:
cpp
set(MY_CACHE_VAR "DefaultValue" CACHE STRING "A cache variable")
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries")
set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation directory")
使用缓存变量:
cpp
message(STATUS "Cache variable MY_CACHE_VAR is ${MY_CACHE_VAR}")
3.环境变量
- 访问方式 :
$ENV{VARIABLE_NAME}
- 修改方式 :
set(ENV{VARIABLE_NAME} value)
cpp
message("PATH: $ENV{PATH}") # 读取环境变量
set(ENV{MY_LIB_PATH} "${CMAKE_SOURCE_DIR}/libs") # 设置环境变量
6.变量作用域与传递
- 默认作用域:当前目录及子目录。
- 提升作用域 :
PARENT_SCOPE
参数。
cpp
# 在子目录 CMakeLists.txt 中
set(CHILD_VAR "value" PARENT_SCOPE) # 将变量传递到父目录
7.注意事项
1.模块化结构
cpp
project/
├── CMakeLists.txt # 顶级配置
├── src/ # 源代码
│ └── CMakeLists.txt
├── include/ # 公共头文件
├── tests/ # 测试代码
│ └── CMakeLists.txt
├── examples/ # 示例
└── CMakeModules/ # 自定义 CMake 模块
2.使用现代 CMake 模式
- 优先使用
target_*
命令(如target_include_directories
)而非全局设置。 - 通过
PUBLIC/PRIVATE/INTERFACE
明确依赖范围。
3.避免硬编码路径
cpp
# 不好的做法
include_directories("/usr/local/include/mylib")
# 好的做法
find_package(MyLib REQUIRED)
target_link_libraries(myapp PRIVATE MyLib::MyLib)
4.添加版本控制
cpp
project(MyProject VERSION 1.2.3)
configure_file(version.h.in version.h)
target_include_directories(myapp PRIVATE ${CMAKE_BINARY_DIR})
掌握 CMakeLists.txt 的结构和语法是高效管理 C/C++ 项目的关键,合理组织文件可大幅提升项目的可维护性和跨平台兼容性。
相关链接
- CMake 官网 CMake - Upgrade Your Software Build System
- CMake 官方文档:CMake Tutorial --- CMake 4.0.2 Documentation
- CMake 源码:https://github.com/Kitware/CMake
- CMake 源码:Sign in · GitLab