假设我的项目CMakeLists.txt
包括foo.cmake
:
include(foo)
在foo.cmake
,我想知道的路径foo.cmake
。
我怎样才能做到这一点?
请注意,它CMAKE_CURRENT_LIST_DIR
给出了 include 的目录CMakeLists.txt
,而不是include 的目录,foo.cmake
因此不是我想要的。
当然,foo.cmake
可能会被多个项目包含(即,被多个CMakeLists.txt
文件)。
人们报告了关于 CMAKE_CURRENT_LIST_DIR 行为方式的看似矛盾的事实。现在我知道了混乱的原因:
首先,在我的 Linux 环境中:
$ cd /path/to/home
$ mkdir cmake-test
$ cd cmake-test
$ mkdir source
$ mkdir source/subdirectory
$ mkdir build
我创建了这两个文件:
$ cat source/CMakeLists.txt
include(subdirectory/foo.cmake)
$ cat source/subdirectory/foo.cmake
message("CMAKE_CURRENT_LIST_DIR is ${CMAKE_CURRENT_LIST_DIR}")
按照 Fraser 和 Robert Dailey 的报道,CMake 的工作原理:
$ cd build
$ cmake ../source
CMAKE_CURRENT_LIST_DIR is /path/to/home/cmake-test/source/subdirectory
[...]
但是,我向 foo.cmake 添加了一个函数,我从 CMakeLists.txt 调用它:
$ cat ../source/subdirectory/foo.cmake
message("CMAKE_CURRENT_LIST_DIR is ${CMAKE_CURRENT_LIST_DIR}")
function(bar)
message("CMAKE_CURRENT_LIST_DIR in bar() is ${CMAKE_CURRENT_LIST_DIR}")
endfunction()
$ cat ../source/CMakeLists.txt
include(subdirectory/foo.cmake)
bar()
然后:
$ cmake ../source
CMAKE_CURRENT_LIST_DIR is /path/to/home/cmake-test/source/subdirectory
CMAKE_CURRENT_LIST_DIR in bar() is /path/to/home/cmake-test/source
[...]
因此,在包含 foo.cmake 和调用 bar() 时, foo.cmake 中的 CMAKE_CURRENT_LIST_DIR 的值是不一样的。这是根据 CMAKE_CURRENT_LIST_DIR 的规范。
这是从 bar() 中访问 foo.cmake 目录的一种可能解决方案:
$ cat ../source/subdirectory/foo.cmake
set(DIR_OF_FOO_CMAKE ${CMAKE_CURRENT_LIST_DIR})
function(bar)
message("DIR_OF_FOO_CMAKE in bar() is ${DIR_OF_FOO_CMAKE}")
endfunction()
之后我得到了我正在寻找的行为:
$ cmake ../source
DIR_OF_FOO_CMAKE in bar() is /path/to/home/cmake-test/source/subdirectory
[...]
当前正在处理的列表文件的完整目录。
当 CMake 处理项目中的列表文件时,此变量将始终设置为当前正在处理的列表文件 (CMAKE_CURRENT_LIST_FILE) 所在的目录。该值具有动态范围。当 CMake 开始处理源文件中的命令时,它会将此变量设置为该文件所在的目录。当 CMake 完成处理来自文件的命令时,它会恢复以前的值。因此,宏或函数内的变量值是调用调用堆栈最底部条目的文件的目录,而不是包含宏或函数定义的文件的目录。
我有以下结构:
C:\Work\cmake-test\CMakeLists.txt
C:\Work\cmake-test\subfolder\test.cmake
在我的CMakeLists.txt
:
include( subfolder/test.cmake )
在我的test.cmake
:
message( "Current dir: ${CMAKE_CURRENT_LIST_DIR}" )
我从运行 CMake 时得到的结果C:\Work\cmake-test
是:
当前目录:C:/Work/cmake-test/subfolder
在 CMake 3.17 中,您有一个可用的新变量,称为CMAKE_CURRENT_FUNCTION_LIST_DIR
,可以在函数内部使用。它在函数定义之外是未定义的。
function(foo)
configure_file(
"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/some.template.in"
some.output
)
endfunction()
在 CMake 3.17 之前,CMAKE_CURRENT_FUNCTION_LIST_DIR
功能必须通过以下解决方法来近似CMAKE_CURRENT_LIST_DIR
,取自 CMake 文档:
set(_THIS_MODULE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
function(foo)
configure_file(
"${_THIS_MODULE_BASE_DIR}/some.template.in"
some.output
)
endfunction()
该include()
命令首先在 CMake 目录中搜索模块${CMAKE_MODULE_PATH}
,然后在 CMakeModules
目录中搜索。
if(EXISTS ${CMAKE_MODULE_PATH}/foo.cmake)
因此,您可以使用和检查文件是否存在if(EXISTS ${CMAKE_ROOT}/Modules/foo.cmake)
。