在CMake中,如何找到包含文件的目录?

时间:2012-10-09 14:33:09

标签: file cmake

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

include(foo)

foo.cmake中,我想知道foo.cmake的路径。
我该怎么做?

请注意,CMAKE_CURRENT_LIST_DIR会提供包含CMakeLists.txt的目录,而不是包含foo.cmake的目录,因此不是我想要的。

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

4 个答案:

答案 0 :(得分:50)

人们已经报道了关于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}")  

CMake按照Fraser和Robert Dailey的报道工作:

$ 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中CMAKE_CURRENT_LIST_DIR的值在包含foo.cmake时和调用bar()时不一样。这是根据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  
[...]  

答案 1 :(得分:6)

请参阅CMAKE_CURRENT_LIST_DIR

  

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

     

当CMake处理项目中的listfile时,这个变量会   始终设置为当前listfile的目录   正在处理(CMAKE_CURRENT_LIST_FILE)。价值有   动态范围。当CMake开始处理源文件中的命令时   它将此变量设置为此文件所在的目录。   当CMake完成从文件处理命令时,它将恢复   以前的价值。因此宏或内部变量的值   function是调用最底部条目的文件的目录   在调用堆栈上,而不是包含宏的文件的目录   或功能定义。

实施例

我有以下结构:

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}" )

C:\Work\cmake-test运行CMake时得到的结果是:

  

当前目录:C:/ Work / cmake-test /子文件夹

答案 2 :(得分:3)

在CMake 3.17中,您have a new variable可用,称为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()

答案 3 :(得分:1)

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

因此,您只需使用if(EXISTS ${CMAKE_MODULE_PATH}/foo.cmake)if(EXISTS ${CMAKE_ROOT}/Modules/foo.cmake)检查文件状态。