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

Posted

技术标签:

【中文标题】CMake:从函数内定义范围中的访问变量【英文标题】:CMake: access variable in defining scope from within a function 【发布时间】:2021-12-22 23:53:24 【问题描述】:

我在 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),但我不想污染父作用域。

任何帮助表示赞赏!

【问题讨论】:

【参考方案1】:

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

只有像CMAKE_CURRENT_FUNCTION_LIST_DIR 或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 模块,例如 foo.cmake

模块包含在 include 命令中:

include(foo)
...
foo()

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


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

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

【讨论】:

以上是关于CMake:从函数内定义范围中的访问变量的主要内容,如果未能解决你的问题,请参考以下文章

在函数中创建类并访问在包含函数范围内定义的函数

从java访问包内定义的类型

Javascript命名空间 - 如何根据命名导出函数范围内定义的函数和变量?

成员变量与局部变量

变量已在范围内定义?

JavaScript 作用域和作用域链