[fix] error: module file CMakeFiles/__cmake_cxx23.dir/std.pcm cannot be loaded due to a configuration mismatch with the current compilation #4279 #4582

This commit is contained in:
guoliang 2025-11-01 23:01:22 +08:00
parent 9b479a455e
commit 82ce893a55

View File

@ -5,6 +5,15 @@ if (${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif ()
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-stdlib=libc++)
add_link_options(-stdlib=libc++)
endif()
# Determine if fmt is built as a subproject (using add_subdirectory)
# or if it is the master project.
if (NOT DEFINED FMT_MASTER_PROJECT)
@ -44,21 +53,9 @@ endfunction()
set(FMT_USE_CMAKE_MODULES FALSE)
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.28 AND
CMAKE_GENERATOR STREQUAL "Ninja")
# Tentatively enable CMake FILE_SET module support; the final decision
# (considering the compiler id) will be made after the project() call
# when CMAKE_CXX_COMPILER_ID is known.
set(FMT_USE_CMAKE_MODULES TRUE)
endif ()
# If the project is configured to build the module variant (FMT_MODULE=ON)
# then disable CMake's automatic module scanning early to prevent CMake from
# stopping the generation when the compiler can't discover import graphs
# (common with some compiler+generator combinations such as GCC + Ninja).
# A user can still override CMAKE_CXX_SCAN_FOR_MODULES explicitly if needed.
if (DEFINED FMT_MODULE AND FMT_MODULE)
set(CMAKE_CXX_SCAN_FOR_MODULES OFF CACHE BOOL "Disable CMake module scanning when using manual module precompilation" FORCE)
endif()
# Adds a library compiled with C++20 module support.
# `enabled` is a CMake variables that specifies if modules are enabled.
# If modules are disabled `add_module_library` falls back to creating a
@ -90,24 +87,9 @@ function(add_module_library name)
target_sources(${name} PUBLIC FILE_SET fmt TYPE CXX_MODULES
FILES ${sources})
else()
# Disable CMake's automatic module scanning for this target. We perform
# manual precompilation of module units and propagate module files via
# -fmodule-file, so CMake's scanner is not needed and on some compilers
# it is unavailable which causes generation errors.
set_target_properties(${name} PROPERTIES CXX_SCAN_FOR_MODULES OFF)
# `std` is affected by CMake options and may be higher than C++20.
get_target_property(std ${name} CXX_STANDARD)
# Respect CMAKE_CXX_EXTENSIONS when forming the -std flag used to
# precompile modules. A mismatch between -std=gnu++<ver> and -std=c++<ver>
# can cause "configuration mismatch" errors when loading .pcm files.
if (CMAKE_CXX_EXTENSIONS)
set(std_flag "-std=gnu++${std}")
else()
set(std_flag "-std=c++${std}")
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(pcms)
foreach (src ${sources})
@ -124,9 +106,9 @@ function(add_module_library name)
add_custom_command(
OUTPUT ${pcm}
COMMAND ${CMAKE_CXX_COMPILER}
${std_flag} -x c++-module --precompile -c
-o ${pcm} ${CMAKE_CURRENT_SOURCE_DIR}/${src}
"-I$<JOIN:$<TARGET_PROPERTY:${name},INCLUDE_DIRECTORIES>,;-I>"
-std=c++${std} -x c++-module --precompile -c
-o ${pcm} ${CMAKE_CURRENT_SOURCE_DIR}/${src}
"-I$<JOIN:$<TARGET_PROPERTY:${name},INCLUDE_DIRECTORIES>,;-I>"
# Required by the -I generator expression above.
COMMAND_EXPAND_LISTS
DEPENDS ${src})
@ -141,9 +123,8 @@ function(add_module_library name)
set(sources ${sources} ${pcm} ${CMAKE_CURRENT_BINARY_DIR}/${obj})
add_custom_command(
OUTPUT ${obj}
COMMAND ${CMAKE_CXX_COMPILER} ${std_flag} -c -o ${obj} ${pcm}
"-I$<JOIN:$<TARGET_PROPERTY:${name},INCLUDE_DIRECTORIES>,;-I>"
COMMAND_EXPAND_LISTS
COMMAND ${CMAKE_CXX_COMPILER} $<TARGET_PROPERTY:${name},COMPILE_OPTIONS>
-c -o ${obj} ${pcm}
DEPENDS ${pcm})
endforeach ()
endif ()
@ -204,17 +185,6 @@ if (FMT_TEST AND FMT_MODULE)
# The tests require {fmt} to be compiled as traditional library
message(STATUS "Testing is incompatible with build mode 'module'.")
endif ()
# GCC's module support via -fmodules-ts is experimental and known to be
# unstable in some versions; if the user requested module build but we are
# using GCC, prefer to disable FMT_MODULE to avoid compiler internal errors.
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND FMT_MODULE)
# GCC module support is unstable in some environments. Prefer a non-fatal
# status message so developers are informed but not alarmed; the behavior
# still disables module mode to avoid compiler crashes.
message(STATUS "Disabling FMT_MODULE because GCC's module support is unstable in this environment.")
set(FMT_MODULE OFF CACHE BOOL "Build a module instead of a traditional library." FORCE)
endif()
set(FMT_SYSTEM_HEADERS_ATTRIBUTE "")
if (FMT_SYSTEM_HEADERS)
set(FMT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM)
@ -248,13 +218,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/support/cmake")
include(CheckCXXCompilerFlag)
include(JoinPaths)
# Disable CMake's automatic module scanning on GCC because CMake's import
# graph discovery is not available for some GCC versions/combination and
# causes generation to fail. We perform manual precompilation instead.
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(CMAKE_CXX_SCAN_FOR_MODULES OFF CACHE BOOL "Disable CMake module scanning for GCC; we use manual precompilation" FORCE)
endif()
if (FMT_MASTER_PROJECT AND NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET)
set_verbose(CMAKE_CXX_VISIBILITY_PRESET hidden CACHE STRING
"Preset for the export of private symbols")
@ -262,19 +225,6 @@ if (FMT_MASTER_PROJECT AND NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET)
hidden default)
endif ()
# Decide whether to use CMake's FILE_SET-based module support. We only enable
# it when the generator and CMake version support it and the compiler is not
# GCC (GCC lacks import-graph discovery in many setups). This check must run
# after project() so CMAKE_CXX_COMPILER_ID is available.
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.28 AND
CMAKE_GENERATOR STREQUAL "Ninja" AND
NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(FMT_USE_CMAKE_MODULES TRUE)
else()
set(FMT_USE_CMAKE_MODULES FALSE)
endif()
message(STATUS "FMT_USE_CMAKE_MODULES = ${FMT_USE_CMAKE_MODULES}")
if (FMT_MASTER_PROJECT AND NOT DEFINED CMAKE_VISIBILITY_INLINES_HIDDEN)
set_verbose(CMAKE_VISIBILITY_INLINES_HIDDEN ON CACHE BOOL
"Whether to add a compile flag to hide symbols of inline functions")
@ -590,4 +540,4 @@ if (FMT_MASTER_PROJECT AND EXISTS ${gitignore})
set(CPACK_PACKAGE_NAME fmt)
set(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.md)
include(CPack)
endif ()
endif ()