Skip to content

Make CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR refer to subdirectory's root and introduce CMAKE_ROOT_SOURCE_DIR and CMAKE_ROOT_BINARY_DIR variables

Currently, CMake is used to include dependencies within a project in the build output to great effect (namely with Ninja, which speeds up dependency + top level application speeds quite a bit by creating a single graph with all nested dependencies!)

However, there comes a few problems with file namespacing. Right now, CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR refer to the top level CMake project directories and their generated locations, respectively. This causes problems with dependencies loaded in via add_subdirectory() that use CMAKE_SOURCE_DIR and rely on it to point to their top level locations.

Currently, the 'proper' way to address this would be to substitute such variables out in lieu of CMAKE_CURRENT_SOURCE_DIR and CMAKE_CURRENT_BINARY_DIR -- however, this doesn't solve the problem in many cases, and legacy build scripts (e.g. WebKit's CMake system) that are extensive and aren't likely to be changed by the maintainers will still suffer from being included as dependencies.

Such dependencies will break their builds if included as subdirectory projects.


I propose the following:

  • CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR change to refer to the current "subdirectory" root - that is, projects that are referred to directly via the cmake command behave the same, but projects initialized via add_subdirectory no longer refer to the parent project's root directory.
  • Two new variables, CMAKE_ROOT_SOURCE_DIR and CMAKE_ROOT_BINARY_DIR, be introduced that function identically to the current CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR.
  • add_subdirectory() changes its functionality to set CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR to point to the root of the subdirectory being included.

These changes would only break projects that explicitly rely upon a parent project's directory hierarchy via the CMAKE_SOURCE_DIR or CMAKE_BINARY_DIR variables, in which case replacing such occurrences with CMAKE_ROOT_SOURCE_DIR and CMAKE_ROOT_BINARY_DIR would be the fix.

CMAKE_CURRENT_SOURCE_DIR and CMAKE_CURRENT_BINARY_DIR would remain unchanged.

These changes would only affect calls to add_subdirectory, not include().


For example, if I have projects Foo and Bar and I build them in a directory called build:

/
    CMakeLists.txt
    foo.c
    bar/
        CMakeLists.txt
        bar.c
        bar.h
        sub-bar/
            sub-bar.cmake
            sub-bar.c
# /CMakeLists.txt
project (Foo)
add_subdirectory (bar)
add_library (foo "${CMAKE_SOURCE_DIR}/foo.c")
# /bar/CMakeLists.txt
project (Bar)
add_library (bar "${CMAKE_SOURCE_DIR}/bar.c")
include (sub-bar)
# /bar/sub-bar/sub-bar.cmake
include_directories (${CMAKE_SOURCE_DIR})
add_library (subbar "${CMAKE_CURRENT_SOURCE_DIR}/sub-bar.c")

The variables would be set to:

# Foo
CMAKE_SOURCE_DIR=/
CMAKE_CURRENT_SOURCE_DIR=/
CMAKE_ROOT_SOURCE_DIR=/
CMAKE_BINARY_DIR=/build/
CMAKE_CURRENT_BINARY_DIR=/build/
CMAKE_ROOT_BINARY_DIR=/build/

# Bar
CMAKE_SOURCE_DIR=/bar/
CMAKE_CURRENT_SOURCE_DIR=/bar/
CMAKE_ROOT_SOURCE_DIR=/
CMAKE_BINARY_DIR=/build/bar/
CMAKE_CURRENT_BINARY_DIR=/build/bar/
CMAKE_ROOT_BINARY_DIR=/build/

# Bar/sub-bar
CMAKE_SOURCE_DIR=/bar/
CMAKE_CURRENT_SOURCE_DIR=/bar/sub-bar/
CMAKE_ROOT_SOURCE_DIR=/
CMAKE_BINARY_DIR=/build/bar/
CMAKE_CURRENT_BINARY_DIR=/build/bar/sub-bar/
CMAKE_ROOT_BINARY_DIR=/build/
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information