CMake:从函数内定义范围访问变量

CMake: access variable in defining scope from within a function

我在 cmake 中创建了一个带有子项目的项目。在子项目中,我有一个函数想要从其定义范围(而不是父项目范围)访问变量。

这是我的文件夹结构:

/project
|-- CMakeLists.txt
'-- /sub
    '-- CMakeLists.txt

外CMakeLists.txt:

project(mainproject)
cmake_minimum_required(VERSION 3.17)
add_subdirectory(sub)
message("in parent scope: ${V}")
test()

内CMakeLists.txt:

project(subproject)
cmake_minimum_required(VERSION 3.17)
set(V "hello")
message("defining scope: ${V}")

function(test)
    message("function scope: ${V}")
endfunction()

我得到的输出:

defining scope: hello
parent scope: 
function scope: 
-- Configuring done
-- Generating done

我怀疑 cmake 根本不支持闭包,但文档中有这个页面: CMAKE_CURRENT_FUNCTION_LIST_DIR

set(_THIS_MODULE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")

function(foo)
  configure_file(
    "${_THIS_MODULE_BASE_DIR}/some.template.in"
    some.output
  )
endfunction()

这几乎正是我的用例,也是我所做的,但它不起作用。

我在这里错过了什么?

请注意,我可以使用 set(V "hello" PARENT_SCOPE),但我不想污染父范围。

感谢任何帮助!

CMake 中没有“闭包”语义。任何变量的取消引用都使用 当前范围 中的变量。也就是说,如果您从顶层 CMakeLists.txt 调用 test 函数,变量 V 将在该脚本的范围内搜索,而不是从 sub/CMakeLists.txt 的范围内搜索定义给定函数。

只有像 CMAKE_CURRENT_FUNCTION_LIST_DIR or CMAKE_CURRENT_FUNCTION 这样的 特殊 变量是该规则的例外:它们根据它们被取消引用的位置(文件、行、函数)展开。

让你感到困惑的代码示例

set(_THIS_MODULE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")

function(foo)
  configure_file(
    "${_THIS_MODULE_BASE_DIR}/some.template.in"
    some.output
  )
endfunction()

用于 CMake module 就像 foo.cmake.

模块包含在 include 命令中:

include(foo)
...
foo()

add_subdirectory 不同,它不引入范围(有关变量范围的更多信息是 here)。 因此变量 _THIS_MODULE_BASE_DIR 对函数 foo 的调用者 可见 。 (如果另一个模块使用相同的变量名,那么一个变量会默默地重新定义另一个)。


为了使您的代码正常工作,您需要使 V 变量 对函数的调用者 可见。例如,您可以使用 PARENT 或 CACHE 选项设置变量,或者使用全局 属性 而不是变量。

或者,您可以将 test 函数的定义从 sub/CMakeLists.txt 移动到模块 test.cmake,并通过 include.