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

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

  • 一、还在手撸 CMake?Out 啦!
  • 二、什么是 CMake 变量?
  • 三、CMake 变量的设置
  • 四、CMake 变量的使用
  • 五、常见 CMake 变量
  • 六、总结

一、还在手撸 CMake?Out 啦!

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

二、什么是 CMake 变量?

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

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

CMake 变量的作用:

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

    • 项目信息: 项目名称、版本号。
    • 路径信息: 源文件目录、头文件目录、库文件目录。
    • 编译选项: 编译标志 (例如 -Wall, -O2)、链接选项。
  2. 用来控制构建过程的各个方面,例如:

    • 选择编译器: 指定使用哪个 C++ 编译器 (例如 GCC, Clang)。
    • 设置编译选项: 开启或关闭优化、添加调试信息。
    • 指定链接库: 告诉链接器要链接哪些库。
    • 控制安装目录: 指定程序安装到哪个目录。
  3. 避免硬编码,提高构建过程的灵活性和可维护性。只需要修改变量的值,就可以改变构建行为,而无需修改大量的代码。

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_EXECUTABLEADD_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 技术。

参考资源:

  • CMake 官方文档: https://cmake.org/documentation/ (最权威的参考资料)
  • CMake Tutorial: https://cmake.org/cmake/help/latest/guide/tutorial/index.html (CMake 官方提供的入门教程)
  • Effective Modern CMake: https://effectivemoderncmake.com/ (介绍现代 CMake 最佳实践)

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

你可能感兴趣的:(CMake,轻松学,windows,开发语言,c++,学习,linux,c++11,cmake)