Skip to content

Wish: add_subdirectory without creating a new scope

As mentioned in the documentation of the set command, each directory added with add_subdirectory creates a new scope.

The new child scope inherits a copy of the variables defined in its parent scope, and changes to those variables are only visible in the child scope unless the PARENT_SCOPE option is used.

However, I think it's a bit confusing that changes made using the PARENT_SCOPE option ONLY affect the parent scope (and not the copy of the same variable in the child scope).

Let's say a I have a variable LIST_OF_FILES that contains a.cpp and b.cpp, then from a child CMake file I added with add_subdirectory I do:

set(LIST_OF_FILES ${LIST_OF_FILES} first.cpp PARENT_SCOPE)
set(LIST_OF_FILES ${LIST_OF_FILES} second.cpp PARENT_SCOPE)
set(LIST_OF_FILES ${LIST_OF_FILES} third.cpp PARENT_SCOPE)

Counter-intuitively, what I actually get in the original scope is a.cpp b.cpp third.cpp, because the LIST_OF_FILES variable in the child scope was never updated between one set call and the next.

A workaround is to keep the changes in the child scope and only once at the end propagate them to the parent scope:

set(LIST_OF_FILES ${LIST_OF_FILES} first.cpp)
set(LIST_OF_FILES ${LIST_OF_FILES} second.cpp)
set(LIST_OF_FILES ${LIST_OF_FILES} third.cpp)
set(LIST_OF_FILES ${LIST_OF_FILES} PARENT_SCOPE)

IMHO it would make more sense that PARENT_SCOPE modified both the parent and child scopes, but I assume this is a breaking change that might not be possible to make.

So, an alternative solution (and the one I'm proposing here) would be to simplify this use case and add a way to add directories without creating a child scope, so we don't have to think about scopes in the first place. This would be a new option in add_subdirectory, so it would not be a breaking change.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information