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.