Difference between CMAKE_CURRENT_SOURCE_DIR and CMAKE_CURRENT_LIST_DIR

From the Wiki:

CMAKE_CURRENT_SOURCE_DIR this is the directory where the currently processed CMakeLists.txt is located in

CMAKE_CURRENT_LIST_DIR (since 2.8.3) this is the directory of the listfile currently being processed.

From the Docs:

CMAKE_CURRENT_SOURCE_DIR: The path to the source directory currently being processed. This the full path to the source directory that is currently being processed by cmake.

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.

Under what circumstances would these variables hold different values?


Solution 1:

The variables CMAKE_CURRENT_SOURCE_DIR and CMAKE_CURRENT_LIST_DIR may refer to different directories for a CMake list file that is included by another file with the include command. E.g., if a CMakeLists.txt is present in a directory project and contains the following directive

include(src/CMakeLists.txt)

then while src/CMakeLists.txt is being processed CMAKE_CURRENT_LIST_DIR will refer to project/src whereas CMAKE_CURRENT_SOURCE_DIR still points to the outer directory project.

CMAKE_CURRENT_LIST_DIR comes in handy when you need to locate resource files like template files or batch scripts that are located next to the CMakeLists.txt file currently being processed.


Note: When using the add_subdirectory() command rather than include(), the behavior is different, and when src/CMakeLists.txt is being processed, both variables will point to project/src.

Solution 2:

Definitions

CMAKE_SOURCE_DIR: Topmost folder(source directory) that contains a CMakeList.txt file. The value never changes in different scopes.

PROJECT_SOURCE_DIR: The nearest folder that contains CMakeList.txt file, with its own scope, that contains project() command.

CMAKE_CURRENT_SOURCE_DIR: The nearest folder that contains CMakeList.txt file with its own scope. (File do not need to contain project() command)

CMAKE_CURRENT_LIST_DIR: The folder that contains currently processed CMakeList.txt or .cmake file.

What I mean by its own scope is related to scoping rules. While include(file) command is not creating a new scope, add_subdirectory is creating a new scope which affects the PROJECT_SOURCE_DIR and CMAKE_CURRENT_SOURCE_DIR values.

Example

Let project structure be like below:

A/
=> CMakeList.txt
=> B/
   => CMakeList.txt

and let us assume we are printing all cmake variables by putting message command to CMakeList.txt file in subfolder B.

  • If CMakeList.txt in folder A contains a line include("B/CMakeList.txt"), then

CMAKE_SOURCE_DIR will be source directory which is "path to project/A".

PROJECT_SOURCE_DIR will be "path to project/A", because include command does not create a new scope and the nearest CMakeList.txt file that has its own scope and contains project command is in folder A.

CMAKE_CURRENT_SOURCE_DIR will be "path to project/A", because include command does not create a new scope and the nearest CMakeList.txt file that has its own scope is in folder A.

CMAKE_CURRENT_LIST_DIR will be "path to project/A/B", because currently processed file is in subfolder B.

  • If CMakeList.txt contains a line add_subdirectory("./B"), then

CMAKE_SOURCE_DIR will be source directory which is "path to project/A".

PROJECT_SOURCE_DIR will be "path to project/A/B", because add_subdirectory command creates a new scope and the nearest CMakeList.txt file that has its own scope and contains project command is in subfolder B.

CMAKE_CURRENT_SOURCE_DIR will be "path to project/A/B", because add_subdirectory command creates a new scope and the nearest CMakeList.txt file that has its own scope is in subfolder B.

CMAKE_CURRENT_LIST_DIR will be "path to project/A/B", because currently processed file is in subfolder B.

Reference: https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/Useful-Variables