CMake - set指令

文章目录

一、指令格式

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. 设置普通变量

文件结构:
CMake - set指令

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}")

运行结果:
CMake - set指令

从运行结果来看,子目录把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}")

运行结果:
CMake - set指令
从运行结果来看,子目录的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}")

运行结果:
CMake - set指令

(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}")

运行结果:
CMake - set指令
从运行结果来看,和之前 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}")

运行结果:
CMake - set指令
从运行结果来看,宏macro()不需要加PARENT_SCOPE就能修改宏外面的变量值。


1.5 include()

在根目录新建一个cmake的文件夹,增加一个custom.cmake的文件
CMake - set指令
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}")

运行结果:
CMake - set指令
从运行结果来看,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 .运行结果:
CMake - set指令
从运行结果来看,设置Cache变量不带FORCE是改变不了变量值的。


再次执行cmake .. 运行结果:
CMake - set指令
从运行结果上看:

  • 在设置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}")

运行结果:
CMake - set指令

结论:

  • 修改环境变量只在当前CMakeList.txt中有效,而没有真正改变操作系统中的环境变量的值;
  • 在子目录的CMakeLists.txt中查看此环境变量的值,也是修改后的值。
上一篇:安装cmake


下一篇:mac搭建cmake+Qt+ffmpeg开发环境