5 分钟搞懂 CMake 变量:零基础也能学会的构建技巧 一、还在手撸 CMake?Out 啦!还在手动修改 CMakeLists.txt? 每次改个路径、换个编译器都要改半天? 那你就 Out 啦! 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_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 技术。 参考资源: |