Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variables set with PARENT_SCOPE are empty in the corresponding child scope. Why?

Tags:

Consider the following minimal example:

. ├── bar │   └── CMakeLists.txt └── CMakeLists.txt 

where ./CMakeLists.txt is

project( foo ) cmake_minimum_required( VERSION 2.8 )  set( FOO "Exists in both, parent AND in child scope." )  add_subdirectory( bar ) message( STATUS "Variable BAR in ./     = ${BAR}" ) message( STATUS "Variable FOO in ./     = ${FOO}" ) 

and ./bar/CMakeLists.txt is

set( BAR "Exists in parent scope only." PARENT_SCOPE ) message( STATUS "Variable BAR in ./bar/ = ${BAR}" ) 

The relevant part of the output of cmake is this:

... -- Variable BAR in ./bar/ = -- Variable FOO in ./bar/ = Exists in both, parent AND in child scope. -- Variable BAR in ./     = Exists in parent scope only. -- Variable FOO in ./     = Exists in both, parent AND in child scope. ... 

Since the variable BAR is placed into the parent scope I would expect it to be available in the current child scope as well (and in those that follow) -- just like the variable FOO, which is defined the parent scope to begin with. But as can be seen in the above lines the variable BAR is empty in ./bar/CMakeLists.txt, which lead me to the following questions:

Why is the modified parent scope not immediately accessible in the child scope, ./bar/? Can this be mitigated? If yes, how? And if no, what is a work-around? Or am I completely missing something obvious?

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, i.e. target_include_directories( my_target PUBLIC bar_INCLUDE_DIR ).

like image 577
nils Avatar asked Apr 27 '15 10:04

nils


1 Answers

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() 
like image 182
Peter Avatar answered Oct 22 '22 02:10

Peter