Scanning Control in 3.28 for module dependencies

I don’t understand the behavior of CMake scanning control.

My CmakeLists.txt is modification of example from here

cmake_minimum_required(VERSION 3.26)
project(std_module_example CXX)

set(CMAKE_CXX_FLAGS "-lstdc++ -fuse-ld=lld -v")

set(CMAKE_CXX_STANDARD 20)
add_library(foo)
target_sources(foo
  PUBLIC
    FILE_SET cxx_modules TYPE CXX_MODULES FILES
    foo.cxx
)


add_executable(hello main.cxx)
target_link_libraries(hello PRIVATE foo)

#set_target_properties(hello PROPERTIES CXX_SCAN_FOR_MODULES on)

According to cmake-cxxmodules(7) main.cxx will be scanned or not by the following rule:

  1. If the source file belongs to a file set of type CXX_MODULES, it will be scanned.

  2. If the target does not use at least C++ 20, it will not be scanned.

  3. If the source file is not the language CXX, it will not be scanned.

  4. If the CXX_SCAN_FOR_MODULES source file property is set, its value will be used.

  5. If the CXX_SCAN_FOR_MODULES target property is set, its value will be used. Set the CMAKE_CXX_SCAN_FOR_MODULES variable to initialize this property on all targets as they are created.

  6. Otherwise, the source file will be scanned. See policy CMP0155.

In my case:

  1. It does not belong to this set. Go for the next one
  2. I hope set(CMAKE_CXX_STANDARD 20) will be applied to all target and sources, Go for next one
  3. I hope the language is CXX since project(std_module_example CXX), Go for next one
  4. Value is not set. Go for the next one
  5. Value is not set. Go for the next one
  6. File should be scanned.

However, if I build my project it fails to find imported module.

But, if I uncomment the last line everything will work perfectly.

Where is the flow in my logic?

If I use cmake_minimum_required(VERSION 3.28) everything works fine. I forgot that it is not just a version checker.