import std appears to be broken in release 4.0.2

I attempted to upgrade to 4.0.2 but found that my modules projects using import std are now unbuildable. I’m using Visual Studio Community 17.15.0 Preview 4.0 + Ninja.

After fiddling across a large-scale project with a number of C++ module deps, I went ahead and tried a minimal project to confirm, and it too was unbuildable. The CMakeLists for the minimal project looks like this:

cmake_minimum_required(VERSION 4.0.2)
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444")

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_MODULE_STD 1)
project(minimal LANGUAGES CXX)

add_executable(minimal)
target_sources(minimal
        PUBLIC
        FILE_SET cxx_modules TYPE CXX_MODULES FILES
        main.ixx
)

I fiddled with various configurations (one call before another - i.e. sets before project(...) and after it, - different hashes for CMAKE_EXPERIMENTAL_CXX_IMPORT_STD, etc.). Regardless, the result is always this error:

CMake Error in CMakeLists.txt:
  The "CXX_MODULE_STD" property on the target "minimal" requires that the
  "__CMAKE::CXX23" target exist, but it was not provided by the toolchain.
  Reason:

    Experimental `import std` support not enabled when detecting toolchain; it must be set before `CXX` is enabled (usually a `project()` call)

Rolling back to 3.31.7 is the only way I could get things to build again.

The UUID for 4.0.2 is different (because the set of features changed). It is a9e1cf81-9932-4810-974b-6eccaf14e457 for 4.0.2.

That was the problem. Where is the UUID for the current version documented?

The UUID I was using was the one on this page: CMake/Help/dev/experimental.rst at master · Kitware/CMake

But that one is apparently out of date.

1 Like

In the Help/dev/experimental.rst file of the version you’re using (change master to v4.0.1 in the URL). If you build master, it is correct. It was most recently bumped because CMake learned to support clang -stdlib=libstdc++ and import std;. 4.0.1 lacks it, so it uses an older UUID.

I just tried both CMake 4.0.2 and 4.2.3 with correct UUIDs from needed tag tree but still have the same issue. And I set it before project as said in docs.
I use it like this:

# root CMakeLists.txt
cmake_minimum_required (VERSION 4.2.3)
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444")
set(CMAKE_CXX_MODULE_STD ON)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_SCAN_FOR_MODULES ON)
set(CMAKE_POSITION_INDEPENDENT_CODE OFF)

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

project (my_project LANGUAGES CXX)

add_subdirectory(utils)
# library.cmake
function(add_library_target TARGET_NAME)

    set(CMAKE_CXX_STANDARD 23)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)


    project(${TARGET_NAME} LANGUAGES CXX)
    add_library(${TARGET_NAME})

    file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
        src/*.cpp
        src/*.c
    )

    file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS
        include/*.hpp
        include/*.h
    )

    file(GLOB_RECURSE MODULES CONFIGURE_DEPENDS
        modules/*.cppm
    )

    target_sources(${TARGET_NAME} PUBLIC FILE_SET modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES ${MODULES})
    target_sources(${TARGET_NAME} PUBLIC FILE_SET headers TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR} FILES ${HEADERS})
    target_sources(${TARGET_NAME} PRIVATE ${SOURCES})

    # Enable compiled MSVC STD module
    target_compile_options(${TARGET_NAME} PRIVATE
        /EHsc
        "SHELL:/reference \"std=$ENV{STD_MODULE_DIR}/std.ifc\""
        "SHELL:/reference \"std.compat=$ENV{STD_MODULE_DIR}/std.compat.ifc\""
    )
    target_link_libraries(${TARGET_NAME} PRIVATE "$ENV{STD_MODULE_DIR}/std.obj")
    target_link_libraries(${TARGET_NAME} PRIVATE "$ENV{STD_MODULE_DIR}/std.compat.obj")
    target_compile_options(${TARGET_NAME} PRIVATE
        /wd5050
    )

    target_compile_features(${TARGET_NAME} PRIVATE cxx_std_23 INTERFACE cxx_std_23)

    target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

endfunction()

# utils/CMakeLists.txt
include(${CMAKE_SOURCE_DIR}/cmake/library.cmake)

set(LIB utils)

# Find dependencies

find_package(Boost REQUIRED COMPONENTS lockfree)

# Link library

add_library_target(${LIB})

target_link_libraries(${LIB} PUBLIC p7)
target_link_libraries(${LIB} PRIVATE Boost::lockfree)

I also tried to set it inside library.cmake in the function begining . Actually, it builds ok even without CMAKE_CXX_MODULE_STD so I’m not sure do I really need it?

Well, when you do this, you’re telling the compiler how to satisfy import std without CMake knowing about it. Not having to do this is kind of the point of the import std feature in CMake.

1 Like