引言
CMake 版本取自于 3.21.2。
set
set 用来将给定的值保存到常规变量、缓存条目、环境变量中。命令的签名中,占位符 <value>...
用于指定 0 个或者多个参数。如果多个参数被指定,那么它们将会以 ;
连接起来作为实际的参数。如果没有任何参数被指定,那么该变量就会被注销(类似于 unset
命令)。
Set Normal Variable
1 | set(<variable> <value>... [PARENT_SCOPE]) |
在当前函数或者目录范围内设置指定值到变量中。
如果使用了 PARENT_SCOPE
选项,意味着该变量的作用域会传递到上一层(即上一层目录或者当前函数的调用者),变量的先前状态在当前作用域中保持不变(换句话说如果变量先前未定义,那么现在也仍然未定义,反之亦然)。
📚Tips
每一个新的目录或者函数都会创建一个新的作用域,普通变量的作用域,如果不指定 PARENT_SCOPE 选项,只能从外层往内层传递。
示例
函数内部定义变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22cmake_minimum_required(VERSION 3.21.2)
project(SET_TEST)
function(test_set_fn value)
set(VAL_IN_FN ${value} PARENT_SCOPE)
set(VAL_IN_FN_DEFAULT_SCOPE ${value})
message(STATUS "the val in fn is : ${VAL_IN_FN}")
message(STATUS "the val with default scope in fn is : ${VAL_IN_FN_DEFAULT_SCOPE}")
endfunction(test_set_fn)
test_set_fn("hello")
message(STATUS "the val out of the fn is : ${VAL_IN_FN}")
message(STATUS "the val with default scope out of fn is : ${VAL_IN_FN_DEFAULT_SCOPE}")
---output:
-- the val in fn is :
-- the val with default scope in fn is : hello
-- the val out of the fn is : hello
-- the val with default scope out of fn is :我们在函数 test_set_fn 中定义两个变量:具有
PARENT_SCOPE
作用域的 VAL_IN_FN 以及默认作用域的 VAL_IN_FN_DEFAULT_SCOPE。我们在函数内部输出两个变量的值,在函数外部输出两个变量。通过结果我们发现,当指定
PARENT_SCOPE
时,函数内部无法显示该值,而函数调用所在的文件可以访问。对于具有默认作用域的变量,却相反。当然,如果不调用函数的话,那两个变量都没有。
在函数内部调用函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34cmake_minimum_required(VERSION 3.21.2)
project(SET_TEST)
function(test_set_fn value)
set(VAL_IN_FN ${value} PARENT_SCOPE)
set(VAL_IN_FN_DEFAULT_SCOPE ${value})
message(STATUS "the val in fn is : ${VAL_IN_FN}")
message(STATUS "the val with default scope in fn is : ${VAL_IN_FN_DEFAULT_SCOPE}")
endfunction(test_set_fn)
function(print)
test_set_fn("hello")
message(STATUS "-----------------------")
message(STATUS "print : the val out of the fn is : ${VAL_IN_FN}")
message(STATUS "print :the val with default scope out of fn is : ${VAL_IN_FN_DEFAULT_SCOPE}")
endfunction(print)
print()
message(STATUS "-----------------------")
message(STATUS "the val out of the fn is : ${VAL_IN_FN}")
message(STATUS "the val with default scope out of fn is : ${VAL_IN_FN_DEFAULT_SCOPE}")
---output:
-- the val in fn is :
-- the val with default scope in fn is : hello
-- -----------------------
-- print : the val out of the fn is : hello
-- print :the val with default scope out of fn is :
-- -----------------------
-- the val out of the fn is :
-- the val with default scope out of fn is :本次,我们定义另外一个函数
print
并在该函数中调用test_set_fn
,同时我们也在该函数中输出两个变量。通过对结果分析,我们发现test_set_fn
函数内部与之前保持一致,只有默认作用域的可以访问。而在当前文件中两个变量都获取不到,但是在print
函数内部却可以访问到具有PARENT_SCOPE
作用域的变量。也就是说,当变量在函数中声明为
PARENT_SCOPE
时,只会传递给该函数的调用者,如果调用者是一个函数,那么会传递给该函数,如果该调用者是目录,则会传递给当前目录。路径中的变量传递
父级 CMakeLists.txt
1
2
3
4
5
6
7cmake_minimum_required(VERSION 3.21.2)
project(SET_TEST)
add_subdirectory(src)
message(STATUS "the val in directory is : ${VAL_IN_DIRECTORY}")
message(STATUS "the val with default scope is : ${VAL_IN_DIRECTORY_DEFAULT_SCOPE}")子级 CMakeLists.txt
1
2message(STATUS "sub: the val in directory is : ${VAL_IN_DIRECTORY}")
message(STATUS "sub : the val with default scope is : ${VAL_IN_DIRECTORY_DEFAULT_SCOPE}")输出:
1
2
3
4-- sub: the val in directory is :
-- sub : the val with default scope is : hello
-- the val in directory is : hello
-- the val with default scope is :变量的获取必须要在
add_subdirectory
之后获取。在父级目录中可以获取PARENT_SCOPE
的变量而获取不到默认作用域的变量,在子目中中则相反。Set Cache Entry
1
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
设置缓存条目
<variable>
为<value>
,除非使用选项FORCE
,否则默认情况下缓存条目的值不会被覆盖。<type>
必须指定为以下几种类型:
- BOOL
布尔值 ON/OFF,CMake 的 GUI 界面对此类缓存条目会提供一个复选框。 - FILEPATH
文件路径,CMake 的 GUI 界面对此类缓存条目会提供一个文件选择框。 - PATH
目录路径,CMake 的 GUI 界面对此类缓存条目会提供一个目录选择框。 - STRING
文本行,CMake 的 GUI 界面对此类缓存条目会提供一个文本框(对应 STRING )或下拉选择框(对应 STRINGS)。 - INTERNAL
文本行,但是只用于内部,不对外呈现。主要用于运行过程中存储变量,因此使用该type
意味着使用FORCE
。
<docstring>
必须指定为一行文本,用于提供向 CMake 的 GUI 界面展示选项的快速摘要。
如果在调用之前缓存条目不存在或给定了 FORCE 选项,则缓存条目将设置为给定值。
注意事项:
- 如果变量先前未定义或者使用了 FORCE 选项,则缓存条目会直接被赋值。
- 可以在使用 CMake 构建的使用通过 -D 选项来给缓存条目赋值,这样 CMakeLists.txt 内的 set 命令只会为缓存条目添加类型。
- 如果变量类型是目录或者文件路径,通过 -D 选项传入的若只是相对路径,那么 set 会给这个相对路径前添加当前的工作目录以变成绝对路径(如果已经是绝对路径则不会处理)。
📚Tips
如果有相同名字的常规变量存在,那么是不能直接获取缓存条目的。如果把策略 CMP0126 设置为 OLD,那么当前作用域内绑定的常规变量都会被删除。
Set Environment Variable
1 | set(ENV{<variable>} [<value>]) |
设置环境变量,之后调用 $ENV{<variable>}
将返回新值。
注意事项
环境变量设置的几个注意事项:
- 该命令设置的环境变量只在当前的 CMake 进程生效,既不会影响调用者的环境变量,也不会影响系统环境变量。
- 如果
<value>
为空或者ENV{<variable>}
后没有参数,则该命令会清除掉当前环境变量的值。 <value>
之后额外的参数会被忽略。