Variables set with PARENT_SCOPE are empty in the corresponding child scope. Why?
Peter explained well the reason for this behaviour.
A workaround I usually use in this case is to set a cached variable, which will be visible everywhere:
set(BAR "Visible everywhere"
CACHE INTERNAL ""
)
INTERNAL
is to make it not visible from cmake-gui. INTERNAL
implies FORCE
, making sure it gets updated if you change something for example in your folder structure. The empty string is a description string, that you might want to fill if you believe it's necessary.
Note, though, that the correct approach is attaching properties to targets whenever possible, like using target_incude_directories
, and propagate them to other targets by setting dependencies.
I do not see anything that is not consistent with the SET command documentation
If PARENT_SCOPE is present, the variable will be set in the scope above the current scope. Each new directory or function creates a new scope. This command will set the value of a variable into the parent directory or calling function (whichever is applicable to the case at hand).
./bar/CMakeLists.txt
set( BAR "This is bar." PARENT_SCOPE ) #<-- Variable is set only in the PARENT scope
message( STATUS "Variable BAR in ./bar/ = ${BAR}" ) #<--- Still undefined/empty
You can always do:
set( BAR "This is bar." ) #<-- set in this scope
set( BAR ${BAR} PARENT_SCOPE ) #<-- set in the parent scope too
Grep for PARENT_SCOPE
in the delivered modules in your installation, for example FindGTK2
if(GTK2_${_var}_FOUND)
set(GTK2_LIBRARIES ${GTK2_LIBRARIES} ${GTK2_${_var}_LIBRARY})
set(GTK2_LIBRARIES ${GTK2_LIBRARIES} PARENT_SCOPE)
endif()
If you only need to set a variable both in the local and parent scope, a macro can help reduce duplication:
macro(set_local_and_parent NAME VALUE)
set(${ARGV0} ${ARGV1})
set(${ARGV0} ${ARGV1} PARENT_SCOPE)
endmacro()
Context: my project consists of several executables and libraries. For a library, e.g. bar, I'd like to set a variable bar_INCLUDE_DIR which is added to the include paths of any depending executable.
There is a much better way to do this than to set variables in the parent scope. CMake allows a target to specify include directories, preprocessor symbols etc. that depending targets can use. In your case, you can use target_include_directories.
For example:
target_include_directories(my_target PUBLIC my_inc_dir)