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