CMake 3.29 - 4.2.3 CMAKE_PROJECT__INCLUDE_BEFORE cannot set variables for project(…)

CMAKE_PROJECT__INCLUDE_BEFORE cannot set variables for project(…)

Summary

CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE fails to provide variables for the parameter of project() (e.g. VERSION or DESCRIPTION). Variables set in the include_before script are undefined when project() parses its VERSION argument, despite documentation suggesting the include happens before project().

Here is the minimal example:

# CMakeLists.txt
cmake_minimum_required(VERSION 4.1)

include(CMakePrintHelpers)

variable_watch(TB_VERSION)
variable_watch(PROJECT_VERSION)

list(APPEND CMAKE_PROJECT_test_INCLUDE_BEFORE
     "${CMAKE_CURRENT_SOURCE_DIR}/set_version.cmake")

project(test VERSION ${TB_VERSION})

cmake_print_variables(TB_VERSION PROJECT_VERSION CMAKE_PROJECT_VERSION)
# set_version.cmake
message(STATUS "include_before running...")

set(TB_VERSION "1.2.3")

cmake_print_variables(TB_VERSION)

Log:

❯ cmake .
CMake Debug Log at CMakeLists.txt:11 (project):
  Variable "TB_VERSION" was accessed using UNKNOWN_READ_ACCESS with value "".


-- include_before running...
CMake Debug Log at set_version.cmake:3 (set):
  Variable "TB_VERSION" was accessed using MODIFIED_ACCESS with value
  "1.2.3".
Call Stack (most recent call first):
  CMakeLists.txt:11 (project)


CMake Debug Log at C:/Users/e_gleba/scoop/apps/cmake/current/share/cmake-4.2/Modules/CMakePrintHelpers.cmake:94 (string):    
  Variable "TB_VERSION" was accessed using READ_ACCESS with value "1.2.3".
Call Stack (most recent call first):
  set_version.cmake:5 (cmake_print_variables)
  CMakeLists.txt:11 (project)


-- TB_VERSION="1.2.3"
CMake Warning at CMakeLists.txt:11 (project):
  VERSION keyword not followed by a value or was followed by a value that
  expanded to nothing.


CMake Debug Log at CMakeLists.txt:11 (project):
  Variable "PROJECT_VERSION" was accessed using MODIFIED_ACCESS with value
  "".


CMake Debug Log at C:/Users/e_gleba/scoop/apps/cmake/current/share/cmake-4.2/Modules/CMakePrintHelpers.cmake:94 (string):
  Variable "TB_VERSION" was accessed using READ_ACCESS with value "1.2.3".
Call Stack (most recent call first):
  CMakeLists.txt:13 (cmake_print_variables)


CMake Debug Log at C:/Users/e_gleba/scoop/apps/cmake/current/share/cmake-4.2/Modules/CMakePrintHelpers.cmake:94 (string):    
  Variable "PROJECT_VERSION" was accessed using READ_ACCESS with value "".
Call Stack (most recent call first):
  CMakeLists.txt:13 (cmake_print_variables)


-- TB_VERSION="1.2.3" ; PROJECT_VERSION="" ; CMAKE_PROJECT_VERSION=""
-- Configuring done (0.0s)
-- Generating done (0.1s)
-- Build files have been written to: C:/Users/e_gleba/testbed

This contradicts the documented behavior from “Professional CMake” 22nd edition, which states the code is equivalent to:

# CMake 3.15 or later only
if(DEFINED CMAKE_PROJECT_INCLUDE_BEFORE)
    include(${CMAKE_PROJECT_INCLUDE_BEFORE})
endif()

# CMake 3.17 or later only
if(DEFINED CMAKE_PROJECT_SomeProj_INCLUDE_BEFORE)
    include(${CMAKE_PROJECT_SomeProj_INCLUDE_BEFORE})
endif()

project(SomeProj)

However, manually placing include() before project() does work correctly

1 Like

This was also raised as CMake Issue 27588. As I’ve just answered there, the observed behavior is that described by our official documentation.

@craig.scott please look at the wording in the book.

The wording in the official docs for the project() commands are the most precise and correct (I also wrote the last main update to those). The wording in the Professional CMake book is preceded by the sentence “The effective behavior of these variables is loosely equivalent to the following…”. Note the “loosely” there. The book’s example wasn’t intended to cover all cases, only to give an approximate high-level understanding of the steps. Your example is relying on a more intricate detail about what variables are defined in what order within the project() command’s implementation. I can look at the wording used by the book, but its example isn’t meant to go into the level of detail you’re talking about here.