前面我们学习了CMakeLists.txt基本构建流程。现在从基础的变量开始学习。
一、变量的类型
根据变量的作用域和生命周期类型,CMake变量分为三种主要类型
| 变量类型 | 定义方式 | 作用域 | 生命周期 | 典型用途 |
|---|---|---|---|---|
| 普通变量 | set(var value) | 当前作用域(函数/目录) | 作用域结束时销毁 | 临时存储中间值、局部配置 |
| 缓存变量 | set(var value CACHE ...) | 全局作用域 | 持久化到 CMakeCache.txt | 用户可配置选项(如安装路径) |
| 环境变量 | $ENV{var} | 进程环境变量 | 进程生命周期 | 读取系统环境(如PATH) |
二、变量的定义与操作
普通变量
定义和赋值
定义主要是通过set命令设置的
set命令基本语法如下
set(<variable> <value>... [PARENT_SCOPE])
<variable>:这是要设置的变量名称。变量名通常采用大写字母,不过大小写均可,只是为了增强可读性和遵循一定的规范,一般用大写。<value>...:代表要赋给变量的值。可以是单个值,也可以是多个值,多个值之间用空格分隔。[PARENT_SCOPE]:这是一个可选参数。若指定了该参数,变量将会被设置在父作用域中,而非当前作用域。
SET(HELLO “Hello World”)#定义普通变量
SET(MY_LIST a b c)#定义列表变量
message(STATUS "HELLO:${HELLO}")
message(STATUS "MY_LIST:${MY_LIST}")
作用域规则:
- 在函数、宏或子目录中使用
set(),默认仅影响当前作用域。 - 目录作用域:在
add_subdirectory()进入子目录时,父目录的变量会拷贝到子目录作用域,但子目录的修改不会影响父目录。
输出
cmake -B build
-- HELLO:Hello World
-- MY_LIST:a;b;c
列表打印的时候打印的是一个整体。如果我们想挨个遍历。则可以用foreach
foreach(item ${MY_LIST})
message("List item: ${item}")
endforeach()
此时的输出就是
List item: a
List item: b
List item: c
foreach语句暂时知道可以打印列表就好。后面在详细介绍。
缓存变量
定义与类型
set(<variable> <value> CACHE <type> <docstring> [FORCE])
例如
set(MY_CACHE_VARIABLE "first value" CACHE STRING "A cached variable")
STRING 表示变量的类型,后面的字符串是对该变量的描述。
message(STATUS "MY_CACHE_VARIABLE:${MY_CACHE_VARIABLE}")
输出
-- MY_CACHE_VARIABLE:first value
当使用 CACHE 关键字时,变量会被存储在 CMake 的缓存中。这样一来,用户在运行 CMake 时可以通过 -D 选项来修改这个变量的值。
cmake -DMY_CACHE_VARIABLE="new value" ..
当执行上面语句后。再cmake -B build
输出
-- MY_CACHE_VARIABLE:new value
后续MY_CACHE_VARIABLE变量如果没有通过-D改变。就一直不变。
若缓存变量已存在,再次运行 set(... CACHE ...) 不会覆盖旧值,除非使用 FORCE 。
当然如果删除了整个build文件夹。MY_CACHE_VARIABLE又会恢复成最新的那个first value值。
常见变量类型及示例
1. STRING 类型
STRING 类型用于存储任意字符串值,是最常用的类型之一。
cmake
set(MY_STRING_VARIABLE "default value" CACHE STRING "This is a string cache variable")
message("Value of MY_STRING_VARIABLE: ${MY_STRING_VARIABLE}")
在上述代码中,定义了一个名为 MY_STRING_VARIABLE 的缓存变量,初始值为 "default value",类型为 STRING,并给出了相应的描述信息。之后使用 message 命令输出该变量的值。
2. BOOL 类型
BOOL 类型用于存储布尔值,通常用于控制某些特性的开关。
set(MY_BOOL_VARIABLE ON CACHE BOOL "Enable or disable a certain feature")
if(MY_BOOL_VARIABLE)
message("Feature is enabled.")
else()
message("Feature is disabled.")
endif()
这里定义了一个名为 MY_BOOL_VARIABLE 的缓存变量,初始值为 ON,表示启用某个特性。通过 if 语句根据该变量的值输出不同的信息。
3. FILEPATH 类型
FILEPATH 类型用于存储文件路径,在 CMake GUI 中会提供文件选择对话框。
set(MY_FILE_VARIABLE "" CACHE FILEPATH "Select a file")
message("Selected file: ${MY_FILE_VARIABLE}")
此代码定义了一个名为 MY_FILE_VARIABLE 的缓存变量,初始值为空,类型为 FILEPATH。用户可以在 CMake GUI 中选择一个文件来设置该变量的值。
4. PATH 类型
PATH 类型用于存储目录路径,在 CMake GUI 中会提供目录选择对话框。
set(MY_PATH_VARIABLE "" CACHE PATH "Select a directory")
message("Selected directory: ${MY_PATH_VARIABLE}")
这里定义了一个名为 MY_PATH_VARIABLE 的缓存变量,初始值为空,类型为 PATH。用户可以在 CMake GUI 中选择一个目录来设置该变量的值。
作用域
缓存变量具有全局作用域,在整个 CMake 项目中都可以访问。
缓存变量的优先级:
-
缓存变量会覆盖普通变量(同名时),但可以通过
FORCE强制覆盖缓存变量:set(USE_GPU OFF CACHE BOOL "Override cache" FORCE)
3. 环境变量
环境变量的概念
环境变量是操作系统层面的一种全局变量,在不同的操作系统中都有相应的实现。例如在 Linux 和 macOS 系统中,环境变量可以通过 export 命令设置;在 Windows 系统中,可以通过系统属性或命令提示符中的 set 命令设置。这些环境变量在系统的不同进程和程序中都可以被访问和使用,CMake 也不例外。
在 CMake 中,可以使用 $ENV{<variable>} 语法来访问环境变量,其中 <variable> 是环境变量的名称
-
设置临时设置环境变量,这种设置只在当前 CMake 运行期间有效
set(ENV{MY_VARIABLE} "Hello, CMake!") -
读取环境变量:
message("MY_VARIABLE is: $ENV{MY_VARIABLE}") -
修改系统环境变量:
set(ENV{LD_LIBRARY_PATH} "/opt/libs:$ENV{LD_LIBRARY_PATH}") # 仅在当前 CMake 进程生效
这种设置方式只会影响当前 CMake 进程及其子进程,不会对系统的全局环境变量产生持久影响。
常见应用场景
配置依赖库路径
当项目依赖一些外部库时,这些库的安装路径可能在不同的机器上有所不同。可以通过环境变量来指定这些库的路径,从而提高项目的可移植性。例如:
# 读取环境变量指定的库路径
set(LIB_PATH $ENV{MY_LIB_PATH})
if(LIB_PATH)
include_directories(${LIB_PATH}/include)
link_directories(${LIB_PATH}/lib)
else()
message(FATAL_ERROR "未设置 MY_LIB_PATH 环境变量,请设置该变量指向依赖库的安装路径。")
endif()
控制构建行为
可以通过环境变量来控制 CMake 的构建行为,比如选择不同的构建类型(Debug 或 Release)。示例如下:
# 根据环境变量选择构建类型
set(BUILD_TYPE $ENV{BUILD_TYPE})
if(NOT BUILD_TYPE)
set(BUILD_TYPE "Release")
endif()
set(CMAKE_BUILD_TYPE ${BUILD_TYPE})
message(STATUS "当前构建类型为: ${CMAKE_BUILD_TYPE}")
注意事项
- 可移植性:不同操作系统设置和使用环境变量的方式可能有所不同,在编写跨平台的 CMake 脚本时需要注意这一点。
- 安全性:由于环境变量可以被用户手动修改,在使用环境变量时要确保进行必要的验证和错误处理,避免因为环境变量设置错误而导致构建失败。
三 、CMake内部变量
在 CMake 中,内部变量扮演着非常重要的角色,它们能够帮助开发者对项目的构建过程进行灵活的配置和控制。以下从常见的内部变量类型
| 变量名 | 变量说明 |
|---|---|
| PROJECT_NAME | 返回通过PROJECT指令定义的项目名称 |
| PROJECT_SOURCE_DIR | CMake源码地址,即cmake命令后指定的地址 |
| PROJECT_BINARY_DIR | 运行cmake命令的目录,通常是PROJECT_SOURCE_DIR下的build目录 |
| CMAKE_MODULE_PATH | 定义自己的cmake模块所在的路径 |
| CMAKE_CURRENT_SOURCE_DIR | 当前处理的CMakeLists.txt所在的路径 |
| CMAKE_CURRENT_LIST_DIR | 当前文件夹路径 |
| CMAKE_CURRENT_LIST_FILE | 输出调用这个变量的CMakeLists.txt的完整路径 |
| CMAKE_CURRENT_LIST_LINE | 输出这个变量所在的行 |
| CMAKE_RUNTIME_OUTPUT_DIRECTORY | 生成可执行文件路径 |
| CMAKE_LIBRARY_OUTPUT_DIRECTORY | 生成库的文件夹路径 |
| CMAKE_BUILD_TYPE | 指定基于make的生成器的构建类型(Release,Debug) |
| CMAKE_C_FLAGS | *.C文件编译选项,如 -std=c99 -O3 -march=native |
| CMAKE_CXX_FLAGS | *.CPP文件编译选项,如 -std=c++11 -O3 -march=native |
| CMAKE_CURRENT_BINARY_DIR | target编译目录 |
| CMAKE_INCLUDE_PATH | 环境变量,非cmake变量 |
| CMAKE_LIBRARY_PATH | 环境变量 |
| CMAKE_STATIC_LIBRARY_PREFIX | 静态库前缀, Linux下默认为lib |
| CMAKE_STATIC_LIBRARY_SUFFIX | 静态库后缀,Linux下默认为.a |
| CMAKE_SHARED_LIBRARY_PREFIX | 动态库前缀,Linux下默认为lib |
| CMAKE_SHARED_LIBRARY_SUFFIX | 动态库后缀,Linux下默认为.so |
| BUILD_SHARED_LIBS | 如果为ON,则add_library默认创建共享库 |
| CMAKE_INSTALL_PREFIX | 配置安装路径,默认为/usr/local |
| CMAKE_ABSOLUTE_DESTINATION_FILES | 安装文件列表时使用ABSOLUTE DESTINATION 路径 |
| CMAKE_AUTOMOC_RELAXED_MODE | 在严格和宽松的automoc模式间切换 |
| CMAKE_BACKWARDS_COMPATIBILITY | 构建工程所需要的CMake版本 |
| CMAKE_COLOR_MAKEFILE | 开启时,使用Makefile产生器会产生彩色输出 |
| CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS | 用来控制IF ELSE语句的书写方式 |