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:从函数内定义范围中的访问变量的主要内容,如果未能解决你的问题,请参考以下文章