56

假设我的项目CMakeLists.txt包括foo.cmake

include(foo)

foo.cmake,我想知道的路径foo.cmake
我怎样才能做到这一点?

请注意,它CMAKE_CURRENT_LIST_DIR给出了 include 的目录CMakeLists.txt,而不是include 的目录,foo.cmake因此不是我想要的。

当然,foo.cmake可能会被多个项目包含(即,被多个CMakeLists.txt文件)。

4

4 回答 4

81

人们报告了关于 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  
[...]  
于 2012-10-12T07:53:41.257 回答
9

CMAKE_CURRENT_LIST_DIR

当前正在处理的列表文件的完整目录。

当 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

于 2012-10-10T19:40:17.090 回答
9

在 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()
于 2020-05-16T14:32:22.450 回答
2

include()命令首先在 CMake 目录中搜索模块${CMAKE_MODULE_PATH},然后在 CMakeModules目录中搜索。

if(EXISTS ${CMAKE_MODULE_PATH}/foo.cmake)因此,您可以使用和检查文件是否存在if(EXISTS ${CMAKE_ROOT}/Modules/foo.cmake)

于 2012-10-09T14:47:06.007 回答