filecmake

In CMake, how can I find the directory of an included file?


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).


Solution

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

    So the file structure is as:

    .
    ├── build
    └── source
        ├── CMakeLists.txt
        └── subdirectory
            └── foo.cmake
    

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