Variables in CMake are directory, function, and block scoped. add_subdirectory
creates a new directory "child scope". You can set a variable in the parent scope of a given scope by using the PARENT_SCOPE
argument of the set
command.
In your specific use-case with trying to set source files for a target, if your cmake_minimum_version
is greater than or equal to 3.1, you can (and probably should) instead be using target_sources
to add sources to a target after the target has been defined/declared.
Note that if you want a variable to be set at a given scope and the parent scope, you need to call set
twice- once to set it at that scope, and once to set it at its parent scope.
If you want to "modify" the value of a variable in a deeper scope and make that modification visible to a parent scope, you also need to additionally pass the modified value up to the parent scope using set(... PARENT_SCOPE)
.
Think of each scope as inheriting copies of all the CMake variables of the parent scope. If you know how environment variables with OS processes work, some of that kind of intuition can be pretty useful here.
To pass a variable value up multiple scopes, you need to do set(... PARENT_SCOPE)
in a chain to pass it up each scope. So if possible, it's much less hassle to just set the value of a variable at the highest scope that it's needed in.
If a parent directory scope isn't guaranteed to exist, you can check that CMAKE_SOURCE_DIR
is not equal to the CMAKE_CURRENT_SOURCE_DIR
, like so:
if(NOT ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}"))
set(foo "hello world!" PARENT_SCOPE)
endif()