Merge topic 'clang-libstdcpp-3.31' into release-3.31

802f261d62 experimental/CXXModules: recycle the UUID
c88f3ea1e4 Clang/CXXImportStd: support `-stdlib=libstdc++`
ba5c9703b1 Experimental: recycle the `import std` UUID
9cad48c6cb gcc: support `import std`
acbada3df6 Tests/RunCMake: handle C++26 support where needed

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !10778
This commit is contained in:
Brad King
2025-05-14 15:31:47 -04:00
15 changed files with 181 additions and 32 deletions

View File

@@ -63,7 +63,7 @@ In order to activate support for ``import std`` in C++23 and newer targets,
set
* variable ``CMAKE_EXPERIMENTAL_CXX_IMPORT_STD`` to
* value ``0e5b6991-d74f-4b3d-a41c-cf096e0b2508``.
* value ``d0edc3af-4c50-42ea-a356-e2862fe7a444``.
This UUID may change in future versions of CMake. Be sure to use the value
documented here by the source tree of the version of CMake with which you are

View File

@@ -92,7 +92,7 @@ Compilers which CMake natively supports module dependency scanning include:
Support for ``import std`` is limited to the following toolchain and standard
library combinations:
* Clang 18.1.2 and newer with ``-stdlib=libc++``
* Clang 18.1.2 and newer with ``-stdlib=libc++`` or ``-stdlib=libstdc++``
* MSVC toolset 14.36 and newer (provided with Visual Studio 17.6 Preview 2 and
newer)

View File

@@ -315,8 +315,9 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
set(CMAKE_${lang}_STANDARD_LIBRARY "")
if ("x${lang}" STREQUAL "xCXX" AND
EXISTS "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${lang}-DetectStdlib.h" AND
"x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xClang" AND
"x${CMAKE_${lang}_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xClang" AND
"x${CMAKE_${lang}_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") OR
("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xGNU"))
# See #20851 for a proper abstraction for this.
execute_process(
COMMAND "${CMAKE_${lang}_COMPILER}"

View File

@@ -1,7 +1,11 @@
function (_cmake_cxx_import_std std variable)
if (NOT CMAKE_CXX_STANDARD_LIBRARY STREQUAL "libc++")
if (CMAKE_CXX_STANDARD_LIBRARY STREQUAL "libc++")
set(_clang_modules_json_impl "libc++")
elseif (CMAKE_CXX_STANDARD_LIBRARY STREQUAL "libstdc++")
set(_clang_modules_json_impl "libstdc++")
else ()
set("${variable}"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"Only `libc++` is supported\")\n"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"Only `libc++` and `libstdc++` are supported\")\n"
PARENT_SCOPE)
return ()
endif ()
@@ -10,7 +14,7 @@ function (_cmake_cxx_import_std std variable)
COMMAND
"${CMAKE_CXX_COMPILER}"
${CMAKE_CXX_COMPILER_ID_ARG1}
-print-file-name=libc++.modules.json
"-print-file-name=${_clang_modules_json_impl}.modules.json"
OUTPUT_VARIABLE _clang_libcxx_modules_json_file
ERROR_VARIABLE _clang_libcxx_modules_json_file_err
RESULT_VARIABLE _clang_libcxx_modules_json_file_res
@@ -18,7 +22,7 @@ function (_cmake_cxx_import_std std variable)
ERROR_STRIP_TRAILING_WHITESPACE)
if (_clang_libcxx_modules_json_file_res)
set("${variable}"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"Could not find `libc++.modules.json` resource\")\n"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"Could not find `${_clang_modules_json_impl}.modules.json` resource\")\n"
PARENT_SCOPE)
return ()
endif ()
@@ -26,17 +30,18 @@ function (_cmake_cxx_import_std std variable)
# Without this file, we do not have modules installed.
if (NOT EXISTS "${_clang_libcxx_modules_json_file}")
set("${variable}"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"`libc++.modules.json` resource does not exist\")\n"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"`${_clang_modules_json_impl}.modules.json` resource does not exist\")\n"
PARENT_SCOPE)
return ()
endif ()
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "18.1.2")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "18.1.2" AND
CMAKE_CXX_STANDARD_LIBRARY STREQUAL "libc++")
# The original PR had a key spelling mismatch internally. Do not support it
# and instead require a release known to have the fix.
# https://github.com/llvm/llvm-project/pull/83036
set("${variable}"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"LLVM 18.1.2 is required for `libc++.modules.json` format fix\")\n"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"LLVM 18.1.2 is required for `${_clang_modules_json_impl}.modules.json` format fix\")\n"
PARENT_SCOPE)
return ()
endif ()
@@ -91,9 +96,15 @@ function (_cmake_cxx_import_std std variable)
string(JSON _clang_modules_json_module_source GET "${_clang_modules_json_module}" "source-path")
string(JSON _clang_modules_json_module_is_stdlib GET "${_clang_modules_json_module}" "is-std-library")
string(JSON _clang_modules_json_module_local_arguments GET "${_clang_modules_json_module}" "local-arguments")
string(JSON _clang_modules_json_module_nsystem_include_directories LENGTH "${_clang_modules_json_module_local_arguments}" "system-include-directories")
string(JSON _clang_modules_json_module_local_arguments ERROR_VARIABLE _clang_modules_json_module_local_arguments_error GET "${_clang_modules_json_module}" "local-arguments")
string(JSON _clang_modules_json_module_nsystem_include_directories ERROR_VARIABLE _clang_modules_json_module_nsystem_include_directories_error LENGTH "${_clang_modules_json_module_local_arguments}" "system-include-directories")
if (_clang_modules_json_module_local_arguments_error)
set(_clang_modules_json_module_local_arguments "")
endif ()
if (_clang_modules_json_module_nsystem_include_directories_error)
set(_clang_modules_json_module_nsystem_include_directories 0)
endif ()
if (NOT IS_ABSOLUTE "${_clang_modules_json_module_source}")
string(PREPEND _clang_modules_json_module_source "${_clang_modules_dir}/")
endif ()
@@ -104,16 +115,18 @@ function (_cmake_cxx_import_std std variable)
set(_clang_modules_is_stdlib 1)
endif ()
math(EXPR _clang_modules_json_module_nsystem_include_directories_range "${_clang_modules_json_module_nsystem_include_directories} - 1")
foreach (_clang_modules_json_modules_system_include_directories_idx RANGE 0 "${_clang_modules_json_module_nsystem_include_directories_range}")
string(JSON _clang_modules_json_module_system_include_directory GET "${_clang_modules_json_module_local_arguments}" "system-include-directories" "${_clang_modules_json_modules_system_include_directories_idx}")
if (_clang_modules_json_module_nsystem_include_directories)
math(EXPR _clang_modules_json_module_nsystem_include_directories_range "${_clang_modules_json_module_nsystem_include_directories} - 1")
foreach (_clang_modules_json_modules_system_include_directories_idx RANGE 0 "${_clang_modules_json_module_nsystem_include_directories_range}")
string(JSON _clang_modules_json_module_system_include_directory GET "${_clang_modules_json_module_local_arguments}" "system-include-directories" "${_clang_modules_json_modules_system_include_directories_idx}")
if (NOT IS_ABSOLUTE "${_clang_modules_json_module_system_include_directory}")
string(PREPEND _clang_modules_json_module_system_include_directory "${_clang_modules_dir}/")
endif ()
list(APPEND _clang_modules_include_dirs_list
"${_clang_modules_json_module_system_include_directory}")
endforeach ()
if (NOT IS_ABSOLUTE "${_clang_modules_json_module_system_include_directory}")
string(PREPEND _clang_modules_json_module_system_include_directory "${_clang_modules_dir}/")
endif ()
list(APPEND _clang_modules_include_dirs_list
"${_clang_modules_json_module_system_include_directory}")
endforeach ()
endif ()
endforeach ()
# Split the paths into basedirs and module paths.

View File

@@ -0,0 +1,134 @@
function (_cmake_cxx_import_std std variable)
if (NOT CMAKE_CXX_STANDARD_LIBRARY STREQUAL "libstdc++")
set("${variable}"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"Only `libstdc++` is supported\")\n"
PARENT_SCOPE)
return ()
endif ()
execute_process(
COMMAND
"${CMAKE_CXX_COMPILER}"
${CMAKE_CXX_COMPILER_ID_ARG1}
-print-file-name=libstdc++.modules.json
OUTPUT_VARIABLE _gnu_libstdcxx_modules_json_file
ERROR_VARIABLE _gnu_libstdcxx_modules_json_file_err
RESULT_VARIABLE _gnu_libstdcxx_modules_json_file_res
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE)
if (_gnu_libstdcxx_modules_json_file_res)
set("${variable}"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"Could not find `libstdc++.modules.json` resource\")\n"
PARENT_SCOPE)
return ()
endif ()
# Without this file, we do not have modules installed.
if (NOT EXISTS "${_gnu_libstdcxx_modules_json_file}")
set("${variable}"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"`libstdc++.modules.json` resource does not exist\")\n"
PARENT_SCOPE)
return ()
endif ()
file(READ "${_gnu_libstdcxx_modules_json_file}" _gnu_libstdcxx_modules_json)
string(JSON _gnu_modules_json_version GET "${_gnu_libstdcxx_modules_json}" "version")
string(JSON _gnu_modules_json_revision GET "${_gnu_libstdcxx_modules_json}" "revision")
# Require version 1.
if (NOT _gnu_modules_json_version EQUAL "1")
set("${variable}"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"`libstdc++.modules.json` version ${_gnu_modules_json_version}.${_gnu_modules_json_revision} is not recognized\")\n"
PARENT_SCOPE)
return ()
endif ()
string(JSON _gnu_modules_json_nmodules LENGTH "${_gnu_libstdcxx_modules_json}" "modules")
# Don't declare the target without any modules.
if (NOT _gnu_modules_json_nmodules)
set("${variable}"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"`libstdc++.modules.json` does not list any available modules\")\n"
PARENT_SCOPE)
return ()
endif ()
# Declare the target.
set(_gnu_libstdcxx_target "")
string(APPEND _gnu_libstdcxx_target
"add_library(__CMAKE::CXX${std} IMPORTED INTERFACE)\n")
string(APPEND _gnu_libstdcxx_target
"target_compile_features(__CMAKE::CXX${std} INTERFACE cxx_std_${std})\n")
set(_gnu_modules_is_stdlib 0)
set(_gnu_modules_include_dirs_list "")
set(_gnu_modules_module_paths "")
get_filename_component(_gnu_modules_dir "${_gnu_libstdcxx_modules_json_file}" DIRECTORY)
# Add module sources.
math(EXPR _gnu_modules_json_nmodules_range "${_gnu_modules_json_nmodules} - 1")
foreach (_gnu_modules_json_modules_idx RANGE 0 "${_gnu_modules_json_nmodules_range}")
string(JSON _gnu_modules_json_module GET "${_gnu_libstdcxx_modules_json}" "modules" "${_gnu_modules_json_modules_idx}")
string(JSON _gnu_modules_json_module_source GET "${_gnu_modules_json_module}" "source-path")
string(JSON _gnu_modules_json_module_is_stdlib GET "${_gnu_modules_json_module}" "is-std-library")
string(JSON _gnu_modules_json_module_local_arguments ERROR_VARIABLE _gnu_modules_json_module_local_arguments_error GET "${_gnu_modules_json_module}" "local-arguments")
string(JSON _gnu_modules_json_module_nsystem_include_directories ERROR_VARIABLE _gnu_modules_json_module_nsystem_include_directories_error LENGTH "${_gnu_modules_json_module_local_arguments}" "system-include-directories")
if (_gnu_modules_json_module_local_arguments_error STREQUAL "NOTFOUND")
set(_gnu_modules_json_module_local_arguments "")
endif ()
if (_gnu_modules_json_module_nsystem_include_directories_error STREQUAL "NOTFOUND")
set(_gnu_modules_json_module_nsystem_include_directories 0)
endif ()
if (NOT IS_ABSOLUTE "${_gnu_modules_json_module_source}")
string(PREPEND _gnu_modules_json_module_source "${_gnu_modules_dir}/")
endif ()
list(APPEND _gnu_modules_module_paths
"${_gnu_modules_json_module_source}")
if (_gnu_modules_json_module_is_stdlib)
set(_gnu_modules_is_stdlib 1)
endif ()
if (_gnu_modules_json_module_nsystem_include_directories)
math(EXPR _gnu_modules_json_module_nsystem_include_directories_range "${_gnu_modules_json_module_nsystem_include_directories} - 1")
foreach (_gnu_modules_json_modules_system_include_directories_idx RANGE 0 "${_gnu_modules_json_module_nsystem_include_directories_range}")
string(JSON _gnu_modules_json_module_system_include_directory GET "${_gnu_modules_json_module_local_arguments}" "system-include-directories" "${_gnu_modules_json_modules_system_include_directories_idx}")
if (NOT IS_ABSOLUTE "${_gnu_modules_json_module_system_include_directory}")
string(PREPEND _gnu_modules_json_module_system_include_directory "${_gnu_modules_dir}/")
endif ()
list(APPEND _gnu_modules_include_dirs_list
"${_gnu_modules_json_module_system_include_directory}")
endforeach ()
endif ()
endforeach ()
# Split the paths into basedirs and module paths.
set(_gnu_modules_base_dirs_list "")
set(_gnu_modules_files "")
foreach (_gnu_modules_module_path IN LISTS _gnu_modules_module_paths)
get_filename_component(_gnu_module_dir "${_gnu_modules_module_path}" DIRECTORY)
list(APPEND _gnu_modules_base_dirs_list
"${_gnu_module_dir}")
string(APPEND _gnu_modules_files
" \"${_gnu_modules_module_path}\"")
endforeach ()
list(REMOVE_DUPLICATES _gnu_modules_base_dirs_list)
set(_gnu_modules_base_dirs "")
foreach (_gnu_modules_base_dir IN LISTS _gnu_modules_base_dirs_list)
string(APPEND _gnu_modules_base_dirs
" \"${_gnu_modules_base_dir}\"")
endforeach ()
# Create the file set for the modules.
string(APPEND _gnu_libstdcxx_target
"target_sources(__CMAKE::CXX${std}
INTERFACE
FILE_SET std TYPE CXX_MODULES
BASE_DIRS ${_gnu_modules_base_dirs}
FILES ${_gnu_modules_files})\n")
set("${variable}" "${_gnu_libstdcxx_target}" PARENT_SCOPE)
endfunction ()

View File

@@ -39,7 +39,7 @@ cmExperimental::FeatureData LookupTable[] = {
false },
// CxxImportStd
{ "CxxImportStd",
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508",
"d0edc3af-4c50-42ea-a356-e2862fe7a444",
"CMAKE_EXPERIMENTAL_CXX_IMPORT_STD",
"CMake's support for `import std;` in C++23 and newer is experimental. It "
"is meant only for experimentation and feedback to CMake developers.",

View File

@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
"d0edc3af-4c50-42ea-a356-e2862fe7a444")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std_export_no_std CXX)

View File

@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
"d0edc3af-4c50-42ea-a356-e2862fe7a444")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std_export_no_std CXX)

View File

@@ -1 +1 @@
((Clang)?module 'std' not found|(MSVC)?could not find module 'std')
((GNU)?fatal error: unknown compiled module interface: no such module|(Clang)?module 'std' not found|(MSVC)?could not find module 'std')

View File

@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
"d0edc3af-4c50-42ea-a356-e2862fe7a444")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std_no_std_property CXX)

View File

@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
"d0edc3af-4c50-42ea-a356-e2862fe7a444")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std_not_in_export CXX)

View File

@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
"d0edc3af-4c50-42ea-a356-e2862fe7a444")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std_not_in_export CXX)

View File

@@ -1,11 +1,12 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
"d0edc3af-4c50-42ea-a356-e2862fe7a444")
cmake_minimum_required(VERSION 3.29)
if (EXPORT_NO_STD)
# Block making C++ `import std` targets.
add_library(__CMAKE::CXX23 IMPORTED INTERFACE)
add_library(__CMAKE::CXX26 IMPORTED INTERFACE)
endif ()
project(cxx_modules_import_std_transitive CXX)

View File

@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
"d0edc3af-4c50-42ea-a356-e2862fe7a444")
cmake_minimum_required(VERSION 3.29)
project(cxx_modules_import_std CXX)

View File

@@ -1,5 +1,5 @@
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
"d0edc3af-4c50-42ea-a356-e2862fe7a444")
cmake_language(GET_EXPERIMENTAL_FEATURE_ENABLED
"CxxImportStd"