Unexpected behavior of the GENERATED source file property and CMP0118

The policy CMP0118 states that the GENERATED source file property is now visible in all directory scopes, not just the one it was set in. Now consider the following minimal example:

# CMP0118/CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(CMP0118 LANGUAGES NONE)
set(_test_file "${CMAKE_BINARY_DIR}/subdir/test.txt")
add_subdirectory(subdir)
get_source_file_property(_generated "${_test_file}" GENERATED)
message(STATUS "[${CMAKE_CURRENT_SOURCE_DIR}] GENERATED = ${_generated}")
get_property(_generated SOURCE "${_test_file}" PROPERTY GENERATED)
message(STATUS "[${CMAKE_CURRENT_SOURCE_DIR}] GENERATED = ${_generated}")
get_source_file_property(_generated "${_test_file}" DIRECTORY subdir GENERATED)
message(STATUS "[${CMAKE_CURRENT_SOURCE_DIR}] GENERATED = ${_generated}")
get_property(_generated SOURCE "${_test_file}" DIRECTORY subdir PROPERTY GENERATED)
message(STATUS "[${CMAKE_CURRENT_SOURCE_DIR}] GENERATED = ${_generated}")

# CMP0118/subdir/CMakeLists.txt
add_custom_command(
  OUTPUT "${_test_file}"
  COMMAND ${CMAKE_COMMAND} -E touch "${_test_file}"
  COMMENT "Generating ${_test_file}"
)
add_custom_target(test ALL DEPENDS "${_test_file}")
get_source_file_property(_generated "${_test_file}" GENERATED)
message(STATUS "[${CMAKE_CURRENT_SOURCE_DIR}] GENERATED = ${_generated}")
get_property(_generated SOURCE "${_test_file}" PROPERTY GENERATED)
message(STATUS "[${CMAKE_CURRENT_SOURCE_DIR}] GENERATED = ${_generated}")

When I run this, I get this output:

-- [C:/.../CMP0118/subdir] GENERATED = 1
-- [C:/.../CMP0118/subdir] GENERATED = 1
-- [C:/.../CMP0118] GENERATED = NOTFOUND
-- [C:/.../CMP0118] GENERATED = 0
-- [C:/.../CMP0118] GENERATED = 1
-- [C:/.../CMP0118] GENERATED = 1

What I expected:

-- [C:/.../CMP0118/subdir] GENERATED = 1
-- [C:/.../CMP0118/subdir] GENERATED = 1
-- [C:/.../CMP0118] GENERATED = 1
-- [C:/.../CMP0118] GENERATED = 1
-- [C:/.../CMP0118] GENERATED = 1
-- [C:/.../CMP0118] GENERATED = 1

I expected this, because the documentation says thinks like the GENERATED property was “visible in all directories”, “globally visible” or “can be set and retrieved from any directory scope”. I did not at all expect that I had to use the DIRECTORY option of get[_source_file]_property() to specify the scope in order to read a “globally visible” property. So either this is a bug and the GENERATED property should actually be retrievable the way I read the documentation (from any scope; without specifying the DIRECTORY) or the documentation could be much more clear about this.

Also, I think the documentation of CMP0118 has a small mistake:

Unlike many policies, CMake version 3.21.0 does not warn when this policy is not set and simply uses OLD behavior with regard to visibility of the GENERATED property.

It should say that the NEW behavior is the default, not the OLD one, right? I checked with cmake_policy(GET CMP0118) and it returned NEW as expected.

No, the NEW behavior is “the default” in your case because you said your minimum version is 3.21 and that declares that you are not relying upon any behaviors specific to older versions.

That said, I’m not familiar with this policy, so those questions are for someone else. @dbahadir?

I get that the minimum version of 3.21 is the reason why the policy is set to NEW. But since we apparently read that sentence in different ways, I’m going to explain my point further.

The sentence before states: “Use the cmake_policy() command to set it to OLD or NEW explicitly”. So the “when this policy is not set” sounds like “if not set explicitly with cmake_policy() CMake 3.21 uses the OLD behavior”.

So maybe it is just written confusingly and should say “[…] does not warn then this policy is not enabled (set to OLD explicity) and simplay uses the OLD behavior […]” or something similar.

The documentation for cmake_minimum_required describes how it sets up policies. I suppose the documentation in each policy could be clearer.

Also see Behavior of where CMP0118's value is used is ambiguous for further problems with the GENERATED property and policy CMP0118.