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
.
我在 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
.