In CMake, how can I find the directory of an inclu

2019-01-25 01:43发布

Suppose my project's CMakeLists.txt includes foo.cmake:

include(foo)

In foo.cmake, i want to know the path of foo.cmake.
How can I do that?

Note that CMAKE_CURRENT_LIST_DIR gives the directory of the including CMakeLists.txt, not that of the included foo.cmake, and is thus not what I want.

Of course, foo.cmake might be included by several projects (i.e., by several CMakeLists.txt files).

标签: file cmake
3条回答
聊天终结者
2楼-- · 2019-01-25 02:14

The include() command searches for modules in ${CMAKE_MODULE_PATH} first and then in CMake Modules dir.

So you can just check for file presence with if(EXISTS ${CMAKE_MODULE_PATH}/foo.cmake) and if(EXISTS ${CMAKE_ROOT}/Modules/foo.cmake).

查看更多
Deceive 欺骗
3楼-- · 2019-01-25 02:26

See CMAKE_CURRENT_LIST_DIR:

Full directory of the listfile currently being processed.

As CMake processes the listfiles in your project this variable will always be set to the directory where the listfile which is currently being processed (CMAKE_CURRENT_LIST_FILE) is located. The value has dynamic scope. When CMake starts processing commands in a source file it sets this variable to the directory where this file is located. When CMake finishes processing commands from the file it restores the previous value. Therefore the value of the variable inside a macro or function is the directory of the file invoking the bottom-most entry on the call stack, not the directory of the file containing the macro or function definition.

Example

I have the following structure:

C:\Work\cmake-test\CMakeLists.txt
C:\Work\cmake-test\subfolder\test.cmake

In my CMakeLists.txt:

include( subfolder/test.cmake )

In my test.cmake:

message( "Current dir: ${CMAKE_CURRENT_LIST_DIR}" )

The result I get when I run CMake from C:\Work\cmake-test is:

Current dir: C:/Work/cmake-test/subfolder

查看更多
祖国的老花朵
4楼-- · 2019-01-25 02:35

People have reported seemingly contradictory facts about how CMAKE_CURRENT_LIST_DIR behaves. Now I know the reason for the confusion:

First, in my Linux environment:

$ cd /path/to/home  
$ mkdir cmake-test  
$ cd cmake-test  
$ mkdir source  
$ mkdir source/subdirectory  
$ mkdir build  

I create these two files:

$ cat source/CMakeLists.txt  
include(subdirectory/foo.cmake)  

$ cat source/subdirectory/foo.cmake  
message("CMAKE_CURRENT_LIST_DIR is ${CMAKE_CURRENT_LIST_DIR}")  

CMake works as reported by Fraser and Robert Dailey:

$ cd build  
$ cmake ../source  
CMAKE_CURRENT_LIST_DIR is /path/to/home/cmake-test/source/subdirectory  
[...]  

However, I add a function to foo.cmake, which I call from 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()  

Then:

$ 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  
[...]  

So, the value of CMAKE_CURRENT_LIST_DIR in foo.cmake is not the same at the time foo.cmake is included and when bar() is called. This is according to the specification of CMAKE_CURRENT_LIST_DIR.

Here is one possible solution for accessing the directory of foo.cmake from within bar():

$ 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()  

after which I get the behavior I was looking for:

$ cmake ../source  
DIR_OF_FOO_CMAKE in bar() is /path/to/home/cmake-test/source/subdirectory  
[...]  
查看更多
登录 后发表回答