文章目录
一、指令格式
1. 设置普通变量
set(<variable> <value>... [PARENT_SCOPE])
-
variable
:只能有一个; -
value
:可以有0个,1个或多个,当value值为空时,方法同unset,用于取消设置的值; -
PARENT_SCOPE(父作用域)
:作用域,除PARENT_SCOPE外还有function scope(方法作用域)和directory scope(目录作用域)。
2. 设置缓存变量
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
-
variable
:只能有一个 -
value
:可以有0个,1个或多个,当value值为空时,方法同unset,用于取消设置的值 -
CACHE
:关键字,说明是缓存变量设置 -
type(类型)
:必须为以下中的一种:- BOOL:有ON/OFF,两种取值
- FILEPATH:文件的全路径
- PATH:目录路径
- STRING:字符串
- INTERNAL:字符串
-
docstring
:总结性文字(字符串) -
[FORCE]
:变量名相同,第二次调用set方法时,第一次的value将会被覆盖
3. 设置环境变量
set(ENV{<variable>} [<value>])
-
variable
:只能有一个 -
value
:一般来说,只有一个,为空时,将清除之前设置的变量值,多个时,取值最近的一个,之后的值将被忽略
二、示例
1. 设置普通变量
文件结构:
1.1 子目录未改变根目录的变量的值
根目录的CMakeLists.txt:
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(sample_005 LANGUAGES CXX)
message("根目录的 CMakeLists.txt 文件")
set(MY_CUSTOM_VAL 123)
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
add_subdirectory(subsrc)
message("回到根目录")
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
子目录的CMakeLists.txt:
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(sample_005 LANGUAGES CXX)
message(" 子目录的 CMakeLists.txt 文件")
message(" 子目录修改变量之前 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
set(MY_CUSTOM_VAL 234)
message(" 子目录修改变量之后 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
运行结果:
从运行结果来看,子目录把MY_CUSTOM_VAL
的值设置为了234
,但是只在子目录有效,未改变根目录该变量的值,根目录的MY_CUSTOM_VAL
的值仍为了123
.
1.2 子目录改变根目录的变量的值
根目录CMakeLists.txt不变。
子目录CMakeLists.txt如下:
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(sample_005 LANGUAGES CXX)
message(" 子目录的 CMakeLists.txt 文件")
message(" 子目录修改变量之前 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
set(MY_CUSTOM_VAL 234 PARENT_SCOPE)
message(" 子目录修改变量之后 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
运行结果:
从运行结果来看,子目录的set
指令只修改了根目录的MY_CUSTOM_VAL
的值,而子目录仍然使用的更改之前的值.
以上两个例子得出结论:
-
set
指令不加PARENT_SCOPE
则修改的是当前CMakeLists的变量的值; -
set
指令加PARENT_SCOPE
则修改的是上一级目录中CMakeLists的变量的值,而当前CMakeLists中该变量的值不变。
1.3 function() 作用域使用set指令
(1)根目录CMakeLists.txt,set
指令不加PARENT_SCOPE
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(sample_005 LANGUAGES CXX)
message("根目录的 CMakeLists.txt 文件")
set(MY_CUSTOM_VAL 123)
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
function(func1)
message(" function func1 修改变量之前 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
set(MY_CUSTOM_VAL 234)
message(" function func1 修改变量之后 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
endfunction(func1)
func1()
message("回到根目录")
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
运行结果:
(2)根目录CMakeLists.txt,set
指令加PARENT_SCOPE
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(sample_005 LANGUAGES CXX)
message("根目录的 CMakeLists.txt 文件")
set(MY_CUSTOM_VAL 123)
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
# 定义一个函数func1
function(func1)
message(" function func1 修改变量之前 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
set(MY_CUSTOM_VAL 234 PARENT_SCOPE)
message(" function func1 修改变量之后 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
endfunction(func1)
# 调用函数func1
func1()
message("回到根目录")
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
运行结果:
从运行结果来看,和之前 1.1 和 1.2 这两个例子结论一样。
所以,PARENT_SCOPE
修改的是上一级作用域变量的值
1.4 macro() 宏使用set指令
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(sample_005 LANGUAGES CXX)
message("根目录的 CMakeLists.txt 文件")
set(MY_CUSTOM_VAL 123)
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
# 宏定义testmcro
macro(testmcro)
message(" macro testmcro 修改变量之前 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
set(MY_CUSTOM_VAL 234)
message(" macro testmcro 修改变量之后 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
endmacro(testmcro)
# 调用宏testmcro
testmcro()
message("回到根目录")
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
运行结果:
从运行结果来看,宏macro()
不需要加PARENT_SCOPE
就能修改宏外面的变量值。
1.5 include()
在根目录新建一个cmake
的文件夹,增加一个custom.cmake
的文件custom.cmake
的文件内容:
message(" 进入cmake目录下的custom.cmake文件")
message(" custom.cmake文件修改变量之前 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
set(MY_CUSTOM_VAL 234)
message(" custom.cmake文件修改变量之后 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
根目录下的CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(sample_005 LANGUAGES CXX)
message("根目录的 CMakeLists.txt 文件")
set(MY_CUSTOM_VAL 123)
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
# 使用include的添加.cmake文件
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
include(custom) # 从 CMAKE_MODULE_PATH 包含的路径中搜索 custom.cmake 文件
message("回到根目录")
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
运行结果:
从运行结果来看,custom.cmake
文件虽然在下一级目录,但是在custom.cmake
文件里面不需要添加PARENT_SCOPE
就能修改根目录下的CMakeLists.txt文件中的变量。
1.6 结论:
- 使用
add_subdirectory()
添加子目录的CMakeLists 或者 使用function()
,变量的作用域改变了,如果要修改上一级作用域的变量则需要加PARENT_SCOPE
; - 使用
macro()
或者include()
未改变变量的作用域,不用加PARENT_SCOPE
就能改变外面的变量值; - 通过
include()
和macro()
相当于把这两部分包含的代码直接加入根目录 CMakeLists.txt 文件中去执行,相当于他们是一个整体。
2. 设置缓存变量
根目录下的CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(sample_005 LANGUAGES CXX)
message("根目录的 CMakeLists.txt 文件")
# Cache变量
message("设置Cache变量之前 filePath = ${filePath}")
set(filePath ${PROJECT_SOURCE_DIR}/CMakeLists.txt CACHE FILEPATH " file path")
message("设置Cache变量之后 filePath = ${filePath}")
set(filePath ${PROJECT_SOURCE_DIR}/subsrc/CMakeLists.txt CACHE FILEPATH " file path")
message("设置Cache变量[不带FORCE]之后 filePath = ${filePath}")
set(filePath ${PROJECT_SOURCE_DIR}/cmake/custom.cmake CACHE FILEPATH " file path" FORCE)
message("设置Cache变量[带FORCE]之后 filePath = ${filePath}")
message("回到根目录")
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
第一次执行cmake .
运行结果:
从运行结果来看,设置Cache变量不带FORCE
是改变不了变量值的。
再次执行cmake ..
运行结果:
从运行结果上看:
- 在设置Cache变量之前,此变量就有值了,说明此变量的值被报存在一个缓存文件中;
- 此Cache变量的值在第一次执行
cmake ..
后保存在了一个名为CMakeCache.txt
文件中; - 删除
CMakeCache.txt
文件可以删掉此缓存变量。
3. 修改环境变量
在Ubuntu系统的~/.bashrc
文件中添加了一个自定义的环境变量TEXT_ENV_VAL
根目录下的CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(sample_005 LANGUAGES CXX)
message("根目录的 CMakeLists.txt 文件")
# 设置环境变量
message("环境变量修改之前 TEXT_ENV_VAL = $ENV{TEXT_ENV_VAL}")
set(ENV{TEXT_ENV_VAL} /usr/local/text_c)
message("环境变量修改之后 TEXT_ENV_VAL = $ENV{TEXT_ENV_VAL}")
message("回到根目录")
message("根目录的 MY_CUSTOM_VAL = ${MY_CUSTOM_VAL}")
运行结果:
结论:
- 修改环境变量只在当前CMakeList.txt中有效,而没有真正改变操作系统中的环境变量的值;
- 在子目录的CMakeLists.txt中查看此环境变量的值,也是修改后的值。