0

Based on the thread "cmake variable scope, add_subdirectory", the CMake set command will set the variable in the current scope only, unless the PARENT_SCOPE parameter is specified.

Recently when I was looking at the project command, per CMake doc, variables <PROJECT-NAME>_SOURCE_DIR and <PROJECT-NAME>_BINARY_DIR will be set. But it didn't mention what is the scope of these variables. Can these variable be used in other subdirectory? For example:

|- root | |- CMakeLists.txt // add_subdirectory(proj1); add_subdirectory(proj2) | | | |- proj1 | | |- CMakeLists.txt // project(proj1) | | | |- proj2 | | |- CMakeLists.txt // Does this have access to proj1_SOURCE_DIR or // poj1_BINARY_DIR?

What about variables for other command like Find_Package? What is the scope of the <Module>_FOUND variable? Thanks!

Dreamer
  • 563
  • 1
  • 8
  • 25

2 Answers2

2

I figured out the answer by taking a close look at the cmake source code. The project command is actually setting cache entry at the top level. In this way, $proj1_SOURCE_DIR and $proj1_BINARY_DIR will be available to other sibling scopes.

https://github.com/Kitware/CMake/blob/420874bfaa20772525c60b20d1ee5b6ef5ed9298/Source/cmProjectCommand.cxx#L30-L40

In sum, for command project(proj1), cmake will do: set(proj1_SOURCE_DIR, CACHE STATIC "") set(proj1_BINARY_DIR, CACHE STATIC "")

Unlike regular set(var value), the cache entry could be shared by other sibling scope.

Dreamer
  • 563
  • 1
  • 8
  • 25
1

From the documentation of project:

The top-level CMakeLists.txt file for a project must contain a literal, direct call to the project() command; loading one through the include() command is not sufficient. If no such call exists CMake will implicitly add one to the top that enables the default languages (C and CXX).

So, those variables are already there and propagate scopes down the layout.

Now, the project command should normally be used once in project, since it sets up various flags. If your other sub-projects are also required to be built by themselves as standalone, then a common idiom is to have a check like this:

if(CURRENT_CMAKE_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
  project(foo CXX)

  # other stuff here
endif()

Please note that the PARENT_SCOPE is useful in the context of functions and their call sites.

compor
  • 2,239
  • 1
  • 19
  • 29
  • "The scope for.....So, the proj2 cmake file shouldn't have access to proj1_SOURCE_DIR, etc." I don't think this is true. – Dreamer Dec 10 '17 at 06:49
  • yeah, that wasn't very clear. The truth is that they behave the same as other vars, but they get special treatment on **when** they are defined. Updated my answer to reflect that. Also note, that the order of `add_subdirectory` still plays the usual role. – compor Dec 10 '17 at 11:13
  • Thanks for looking into this. You can take a look at my findings and see if I missed anything. – Dreamer Dec 10 '17 at 18:23