CMake 从入门到崩溃2 - 基础语法之CMake变量
CMake 从入门到崩溃2 - 基础语法之CMake变量
CMake 中变量名大小写敏感,且可以由任何字符组成
🔑 最佳实践
仅在当前作用域中使用的本地变量用简短的小写命名,在多个作用域中使用的变量用详细的大写命名
变量评估
CMake 中变量都是“字符串化”的,用 ${}
包裹一个变量会用变量的值来替换它,CMake 将这个解引用的过程称作变量评估(variable evaluation)
变量评估将发生在接受该表达式做参数的命令执行之前,因此如果对列表解引用,那么可能产生多个命令参数
变量解引用可以被嵌套使用,比如
set(var_name var1)
set(${var_name} foo) # same as "set(var1 foo)"
set(${${var_name}}_var bar) # same as "set(foo_var bar)"
解引用一个未设置的变量将结果为空,因此可以这样使用
if(APPLE)
set(extra_sources Apple.cpp MacOS.cpp)
endif()
add_executable(HelloWorld HelloWorld.cpp ${extra_sources})
在 APPLE 以外的平台下执行这段命令将导致 ${extra_sources}
的结果为空,不会将额外参数传递给 add_executable
if语句和变量评估
条件判断中,如果条件是 1
, ON
, YES
, TRUE
, Y
或非零数字则执行该分支
if ("VAR")
message(TRUE)
else()
message(FALSE)
endif()
if ("y")
message(TRUE)
else()
message(FALSE)
endif()
上面两段代码的输出是 FALSE
和 TRUE
条件判断语句会对我们给出的条件做自动评估,但放到引号中的符号会被当做字符串看待,不会执行自动评估
set(var1 OFF)
set(var2 "var1")
if(${var2})
message("hello 1")
endif()
if(var2)
message("hello 2")
endif()
输出为 hello 2
变量类型
缓存下来或通过命令行指定的变量可以有一个相关联的类型,这个类型被 CMake 的 GUI 工具用于显示正确的输入框
变量的类型通常不会影响变量评估,但如果命令行中指定的变量类型为 PATH
或 FILEPATH
,且变量的值为相对路径,那么 CMake 会当它相对于当前工作目录,并将它转换为绝对路径
列表
在 CMake 中列表是分号隔开的字符串,因此不应该在列表元素中使用分号,创建列表的例子
# Creates a list with members a, b, c, and d
set(my_list a b c d)
set(my_list "a;b;c;d")
# Creates a string "a b c d"
set(my_string "a b c d")
列表操作
可以用 list
命令对列表做读取、查找、修改和排序操作
- 对于表示元素下标的参数,可以使用 -1 取最后一个元素,以此类推
列表的列表
因为列表的元素不能包含分号,因此如果要创建列表的列表,你必须创建一系列变量以引用子列表,比如
set(list_of_lists a b c)
set(a 1 2 3)
set(b 4 5 6)
set(c 7 8 9)
遍历列表的列表,打印每个值
foreach(list_name IN LISTS list_of_lists)
foreach(value IN LISTS ${list_name})
message(${value})
endforeach()
endforeach()
先解引用出出子列表的名字,再解引用出子列表元素;这个模式在 CMake 中被广泛使用
- 最常见的例子是 CMake 指定编译器选项时,会使用到
CMAKE_${LANGUAGE}_FLAGS
CMAKE_${LANGUAGE}_FLAGS_${CMAKE_BUILD_TYPE}
环境变量
- 读取环境变量 VAR
$ENV{VAR}
- 判断环境变量是否被定义
if(DEFINED ENV{<name>})
DEFINED
也可以用来检查任意变量是否被定义
🔑 CMake 不会跟踪环境变量的变化,因此不要在你的代码中使用可能被改变的环境变量
设置环境变量
set(ENV{<variable>} [<value>])
只影响当前 CMake 进程,不影响调用 CMake 的进程、整体的系统环境,以及后续的构建和测试进程的环境
如果没有给出 value 参数或 value 参数为空字符串,那么该命令会清除掉现有环境变量的值
Cache 变量
set(MY_FUCKING_CACHE_VAR HELLO_HELLO
CACHE STRING a_fucking_cache_variable)
将导致CMakeCache.txt中产生:
//a_fucking_cache_variable
MY_FUCKING_CACHE_VAR:STRING=HELLO_HELLO
注意,如果 MY_FUCKING_CACHE_VAR
已经存在于 CACHE 中了,那么 set 操作不会产生任何效果,除非你指定 FORCE
选项,但这往往意味着你 CMake 项目的设计有问题
🔑 最佳实践
由于 Cache 变量的全局性,你应该在变量名的前面加上项目名前缀以避免冲突
运行 CMake 时,如果传递 -D
选项,CMake 会用它创建或修改 Cache 变量
- 比如执行
cmake .. -DMY_FUCKING_CACHE_VAR=RUN
后,再打开CMakeCache.txt
,就会发现变量的值变为了 RUN - 一般在 CMake 文件中通过
set(...CACHE)
设置某个选项的默认值,让用户用-D
传进来他们的自定义值- 由于
-D
写入 Cache 变量先于我们的 CMake 文件解析,因此不加FORCE
的 set 命令不会再去修改-D
写入的 Cache 内容
- 由于
- 如果有很多变量都要通过
-D
来设置,可以将它们放到一个单独的文件里,并用-C
选项加载
Cache 变量和普通变量的交互
- 用
${VAR}
做变量评估时,CMake 会优先去寻找叫这个名字的普通变量,找不到才会去找 Cache 变量 - 显式地指定读取 Cache 变量:
$CACHE{VAR}
- 设置 Cache 变量时,如果当前作用域下有同名普通变量,则该普通变量会被移除
- 这个移除普通变量的行为在 CMake3.21 里被标记为废弃(CMP0126)
Option
option
命令可以用来创建一个布尔值 Cache 项,供用户选择是 ON
还是 OFF
option(<variable> "<help_text>" [value])
本文来自博客园,作者:路过的摸鱼侠,转载请注明原文链接:https://www.cnblogs.com/ljx-null/p/15941313.html