Introduction
CMake variables like CMAKE_SOURCE_DIR
are predefined variables in CMake that provide information about the build and source directory structure.
Directory Variables
CMAKE_SOURCE_DIR
:- Represents the top-level directory containing the root
CMakeLists.txt
file.
- Represents the top-level directory containing the root
CMAKE_BINARY_DIR
:- Refers to the top-level build directory where CMake generates the build files.
PROJECT_SOURCE_DIR
:- Refers to the source directory of the current project (set by
project()
inCMakeLists.txt
). - If there are multiple nested projects, this variable changes for each.
- Refers to the source directory of the current project (set by
PROJECT_BINARY_DIR
:- Refers to the binary directory of the current project.
- Similar to
CMAKE_BINARY_DIR
, but specific to the scope of the project.
CMAKE_CURRENT_SOURCE_DIR
:- Represents the directory containing the
CMakeLists.txt
file currently being processed. - Different from
CMAKE_SOURCE_DIR
, as it reflects the current directory in a hierarchical project.
- Represents the directory containing the
CMAKE_CURRENT_BINARY_DIR
:- Points to the build directory corresponding to the
CMAKE_CURRENT_SOURCE_DIR
.
- Points to the build directory corresponding to the
CMAKE_CURRENT_LIST_DIR
- Points to the directory where the currently executed CMakeLists.txt or *.cmake file resides.
- It is useful when you need to include or reference files relative to the location of the current script.
CMAKE_CURRENT_LIST_DIR VS CMAKE_CURRENT_SOURCE_DIR
The short answer is when include(a_file)
, they are different inside a_file
. To show that I run an experiment where different cases can happen.
The example project has this structure:
Example
|
|___ sub
| |___ CMakeLists.txt
|
|___ modules
| |___ mod.cmake
|
|___ CMakeLists.txt
The main CMake file is shown below, where a subdirectory added, a function and a macro are called and a module loaded.
# Example/CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(myExample LANGUAGES CXX)
message("CMAKE_CURRENT_LIST_DIR=" ${CMAKE_CURRENT_LIST_DIR})
message("CMAKE_CURRENT_SOURCE_DIR=" ${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(sub)
include(${CMAKE_CURRENT_SOURCE_DIR}"/modules/mod.cmake")
printFunc()
printMacro()
The other CMake file is:
# sub/CMakeLists.txt
message("in sub_dir")
message("CMAKE_CURRENT_LIST_DIR=" ${CMAKE_CURRENT_LIST_DIR})
message("CMAKE_CURRENT_SOURCE_DIR=" ${CMAKE_CURRENT_SOURCE_DIR})
The module is:
message("in module")
message("CMAKE_CURRENT_LIST_DIR=" ${CMAKE_CURRENT_LIST_DIR})
message("CMAKE_CURRENT_SOURCE_DIR=" ${CMAKE_CURRENT_SOURCE_DIR})
function(printFunc)
message("in function")
message("CMAKE_CURRENT_LIST_DIR=" ${CMAKE_CURRENT_LIST_DIR})
message("CMAKE_CURRENT_SOURCE_DIR=" ${CMAKE_CURRENT_SOURCE_DIR})
endfunction()
macro(printMacro)
message("in macro")
message("CMAKE_CURRENT_LIST_DIR=" ${CMAKE_CURRENT_LIST_DIR})
message("CMAKE_CURRENT_SOURCE_DIR=" ${CMAKE_CURRENT_SOURCE_DIR})
endmacro()
The results are:
CMAKE_CURRENT_LIST_DIR=path/to/Example
CMAKE_CURRENT_SOURCE_DIR=path/to/Example
in sub_dir
CMAKE_CURRENT_LIST_DIR=path/to/Example/sub
CMAKE_CURRENT_SOURCE_DIR=path/to/Example/sub
in module
CMAKE_CURRENT_LIST_DIR=path/to/Example/modules
CMAKE_CURRENT_SOURCE_DIR=path/to/Example
in function
CMAKE_CURRENT_LIST_DIR=path/to/Example
CMAKE_CURRENT_SOURCE_DIR=path/to/Example
in macro
CMAKE_CURRENT_LIST_DIR=path/to/Example
CMAKE_CURRENT_SOURCE_DIR=path/to/Example
Therefore, both are almost acting the same except when Include()
is called and CMake moves into the included file. There is another subtle difference that is a consequence of the previous point: CMAKE_CURRENT_LIST_DIR
can be set to a directory that doesn’t contain any CMakeLists.txt file.
We also learn that inside a function or macro both CMAKE_CURRENT_LIST_DIR
and CMAKE_CURRENT_SOURCE_DIR
are set to the caller directory not where function or macro are defined.