【003】5 分钟搞懂 CMake 变量:零基础也能学会的构建技巧

文章正文
发布时间:2025-05-13 09:25

5 分钟搞懂 CMake 变量:零基础也能学会的构建技巧

一、还在手撸 CMake?Out 啦!

还在手动修改 CMakeLists.txt? 每次改个路径、换个编译器都要改半天? 那你就 Out 啦!
CMake 变量:让你解放双手,只需要修改一个变量,就能轻松切换编译选项、调整目标平台,甚至是更换编译器!就像给你的代码加上了“遥控器”,想怎么改就怎么改,而且还不容易出错!
5 分钟,从小白到入门: 这篇教程就是你的 CMake 变量入门指南,保证你 5 分钟就能上手,彻底告别手动修改的苦逼日子!

二、什么是 CMake 变量?

CMake 变量就是用来存储信息,并在构建过程中被 CMake 调用的!最简单的理解,CMake 变量就是一个名字,对应着一个值。CMake 在构建项目的时候,会根据这些变量的值来做出相应的操作。

比如可以把项目名称记录在一个名为 PROJECT_NAME 的变量里,然后在构建的时候引用它。

CMake 变量的作用:

可以用来存储各种信息,例如:

项目信息: 项目名称、版本号。

路径信息: 源文件目录、头文件目录、库文件目录。

编译选项: 编译标志 (例如 -Wall, -O2)、链接选项。

用来控制构建过程的各个方面,例如:

选择编译器: 指定使用哪个 C++ 编译器 (例如 GCC, Clang)。

设置编译选项: 开启或关闭优化、添加调试信息。

指定链接库: 告诉链接器要链接哪些库。

控制安装目录: 指定程序安装到哪个目录。

避免硬编码,提高构建过程的灵活性和可维护性。只需要修改变量的值,就可以改变构建行为,而无需修改大量的代码。

CMake 变量的类型:

类型描述示例常用场景
字符串 (STRING)   一段文本,可以包含任何字符。   MY_NAME = "张三", SRC_FILE = "main.cpp"   存储文本信息,例如文件名、路径、项目名称。  
列表 (LIST)   一组字符串,用分号 ; 分隔。   SRC_FILES = "main.cpp;utils.cpp"   存储一组文件路径、库名称、编译选项。  
布尔值 (BOOL)   真 (TRUE, ON, 1, YES) 或 假 (FALSE, OFF, 0, NO)。   ENABLE_FEATURE = TRUE   启用或禁用某个功能、选项。  
路径 (PATH)   表示文件或目录的路径。   INSTALL_DIR = "/usr/local/bin"   存储文件或目录的路径,方便引用。  

注意:

CMake 对大小写不敏感 (变量名除外)。

CMake 会自动推断变量的类型,也可以显式指定。

这只是最常用的几种类型,CMake 还有其他更复杂的类型。

三、CMake 变量的设置

使用 SET() 命令设置变量。语法:

SET(变量名 变量值 [FORCE])

变量名: 变量的名称 (大小写不敏感,但建议大写)。

变量值: 变量的值,可以是一个字符串、列表或布尔值。

FORCE: (可选) 如果变量已经存在,则强制覆盖其值。

示例:

SET(MY_VARIABLE "Hello CMake") # 设置一个字符串变量 SET(SRC_FILES "main.cpp;utils.cpp") # 设置一个列表变量 SET(ENABLE_FEATURE TRUE) # 设置一个布尔变量 # 设置一个CACHE变量,类型为PATH SET(INSTALL_PREFIX "/usr/local" CACHE PATH "安装路径")

CMake 变量有不同的作用域,决定了它们在 CMakeLists.txt 文件中的可见性和生命周期。

全局变量:

在顶级 CMakeLists.txt 文件中使用 SET() 设置的变量,默认情况下是全局变量。

全局变量在整个 CMake 项目中都可见 (包括子目录)。

全局变量的值可以在任何 CMakeLists.txt 文件中被修改。

函数/目录变量 (局部变量):

在函数或宏内部使用 SET(变量名 ...) 设置的变量,作用域仅限于该函数或宏内部。 函数或宏执行完毕后,这些变量就会失效。

在 add_subdirectory() 命令创建的子目录中的 CMakeLists.txt 文件中,也可以设置只在该目录及其子目录下有效的变量。这些变量不会影响父目录中的同名变量。

重要区别:

全局变量影响整个项目。

局部变量只影响函数/宏/目录内部。

四、CMake 变量的使用

使用 ${} 可以展开变量的值。这是在 CMake 中获取变量值的标准方法。语法: ${变量名}
示例:

SET(MY_VARIABLE "Hello CMake") MESSAGE(STATUS "变量 MY_VARIABLE 的值为:${MY_VARIABLE}")

在编译选项中使用变量:

SET(MY_DEFINE "ENABLE_FEATURE") ADD_DEFINITIONS(-D${MY_DEFINE}) #相当于 -DENABLE_FEATURE

或者,如果想要定义一个字符串值:

SET(MY_STRING_VALUE "My String") ADD_DEFINITIONS(-DSTRING_VALUE="${MY_STRING_VALUE}") # 相当于 -DSTRING_VALUE="My String"

注意:如果变量包含空格或者特殊字符,使用双引号 "..." 包裹 ${MY_STRING_VALUE}。

在源文件路径中使用变量:

SET(MY_SOURCE_FILE "main") #存储不带后缀的文件名 ADD_EXECUTABLE(my_program src/${MY_SOURCE_FILE}.cpp)

假如目录结构如下:

MyProject/ ├── CMakeLists.txt └── src/ ├── main.cpp └── utils.cpp

示例,变量在 ADD_EXECUTABLE 或 ADD_LIBRARY 中的使用:

cmake_minimum_required(VERSION 3.10) project(MyProject) # 设置源文件列表的变量 SET(SOURCE_FILES src/main.cpp src/utils.cpp ) # 设置库的名称的变量 SET(LIBRARY_NAME "mylibrary") # 创建可执行文件 ADD_EXECUTABLE(my_program ${SOURCE_FILES}) # 创建静态库 ADD_LIBRARY(${LIBRARY_NAME} STATIC ${SOURCE_FILES}) # 创建动态库 (共享库) ADD_LIBRARY(${LIBRARY_NAME}_shared SHARED ${SOURCE_FILES})

总结:$ {} 是展开变量值的关键。

五、常见 CMake 变量

项目信息:

变量名描述常见用途备注
PROJECT_NAME   项目的名称,由 project() 命令设置。   显示项目名称,用于生成文件名等。    
PROJECT_VERSION   项目的版本号,由 project() 或 SET() 设置。   显示版本号,用于生成软件包名称等。    
PROJECT_SOURCE_DIR   顶级 CMakeLists.txt 文件所在的目录的绝对路径(项目根目录)。   查找源文件、资源文件等。   也可使用 CMAKE_SOURCE_DIR  
PROJECT_BINARY_DIR   构建目录的绝对路径。CMake 在此目录中生成构建文件。   指定生成的可执行文件、库文件的输出位置。   也可使用 CMAKE_BINARY_DIR  

构建类型和编译器:

变量名描述常见用途备注
CMAKE_BUILD_TYPE   构建类型(Debug, Release, RelWithDebInfo, MinSizeRel)。   根据构建类型设置不同的编译选项。   可以在运行 cmake 命令时使用 -DCMAKE_BUILD_TYPE 设置。  
CMAKE_CXX_COMPILER   C++ 编译器的完整路径。   获取编译器信息。    
CMAKE_C_COMPILER   C 编译器的完整路径。   获取编译器信息。    

安装路径:

变量名描述常见用途备注
CMAKE_INSTALL_PREFIX   安装路径的根目录,由 install() 命令使用。   指定程序安装的根目录。   可以在运行 cmake 命令时使用 -DCMAKE_INSTALL_PREFIX 设置。  
CMAKE_INSTALL_BINDIR   可执行文件安装到的目录 (相对于 CMAKE_INSTALL_PREFIX)。默认为 bin。   指定可执行文件安装的子目录。    
CMAKE_INSTALL_LIBDIR   库文件安装到的目录 (相对于 CMAKE_INSTALL_PREFIX)。默认为 lib。   指定库文件安装的子目录。    
CMAKE_INSTALL_INCLUDEDIR   头文件安装到的目录 (相对于 CMAKE_INSTALL_PREFIX)。默认为 include。   指定头文件安装的子目录。    

编译/链接选项:

变量名描述常见用途备注
CMAKE_CXX_FLAGS   C++ 编译器的编译选项。   添加编译标志,例如 -Wall -Wextra -std=c++11。   一般建议使用 target_compile_options 为特定的目标 (target) 设置编译选项,而不是全局设置。  
CMAKE_C_FLAGS   C 编译器的编译选项。   添加编译标志,例如 -Wall -Wextra。   一般建议使用 target_compile_options 为特定的目标 (target) 设置编译选项,而不是全局设置。  
CMAKE_EXE_LINKER_FLAGS   可执行文件的链接器选项。   添加链接器标志,例如 -L/path/to/library。   一般建议使用 target_link_libraries 为特定的目标 (target) 设置链接器选项,而不是全局设置。  
CMAKE_SHARED_LINKER_FLAGS   共享库的链接器选项。   添加链接器标志。   一般建议使用 target_link_libraries 为特定的目标 (target) 设置链接器选项,而不是全局设置。  

系统信息和特性

变量名描述常见用途备注
CMAKE_SYSTEM_NAME   操作系统名称 (例如 Linux, Windows, Darwin)。   编写平台相关的代码。    
CMAKE_SYSTEM_VERSION   操作系统版本。   编写操作系统版本相关的代码。    
CMAKE_SYSTEM_PROCESSOR   处理器架构 (例如 x86_64, arm64)。   编写处理器架构相关的代码。    

其他有用的变量:

变量名描述常见用途备注
CMAKE_CURRENT_SOURCE_DIR   当前处理的 CMakeLists.txt 文件所在的目录的绝对路径。   在子目录中查找文件。    
CMAKE_MODULE_PATH   CMake 模块的搜索路径。   指定查找自定义 CMake 模块的路径。    
BUILD_SHARED_LIBS   如果设置为 TRUE,则所有库都将构建为共享库。   统一构建共享库或静态库。   可以在运行 cmake 命令时使用 -DBUILD_SHARED_LIBS=ON 设置。  
CMAKE_EXPORT_COMPILE_COMMANDS   如果设置为 TRUE,则 CMake 将生成一个 compile_commands.json 文件,其中包含构建项目所需的所有编译命令。   方便代码编辑器和静态分析工具使用。    

更多内容查阅 CMake 官方文档以获取更完整的变量列表和详细信息:https://cmake.org/documentation/

尽量使用 target_* 系列命令 (例如 target_compile_options, target_link_libraries) 为特定的构建目标设置属性,而不是全局设置 CMAKE_* 变量,以避免不必要的副作用。

六、总结

本文深入探讨了 CMake 变量,CMake 变量是 CMake 构建系统中的核心组成部分,它们控制着项目的配置、构建和安装过程。

CMake 变量用于存储各种信息,例如项目名称、版本号、编译器路径、编译选项、安装路径等等。通过实践,能够更好地理解 CMake 变量的作用,并掌握更高级的 CMake 技术。

参考资源:

在这里插入图片描述

首页
评论
分享
Top