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 using set(...)
, and once to set it at its 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 (not a perfect analogy since processes can't affect the environments of their parent processes).
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()
You can also set global properties using set_property(GLOBAL ...)
. The way of using properties is a little bit clunky with having to read it into a variable and then modify the variable and then write the variable back to the property if you want to do modifications, but it might be more preferable than doing a long chain of set(... PARENT_SCOPE)
if you really can't just set the variable at the highest scope.
${CMAKE_CURRENT_SOURCE_DIR}/foo.cpp
instead of onlyfoo.cpp
because cmake is now in the parent scope. – Sharpedged