浏览代码

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 <[email protected]>
Merge-request: !10778
Brad King 5 月之前
父节点
当前提交
0883fac39a

+ 1 - 1
Help/dev/experimental.rst

@@ -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

+ 1 - 1
Help/manual/cmake-cxxmodules.7.rst

@@ -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)
 

+ 3 - 2
Modules/CMakeDetermineCompilerId.cmake

@@ -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}"

+ 32 - 19
Modules/Compiler/Clang-CXX-CXXImportStd.cmake

@@ -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 (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 (_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 ()
+    endif ()
   endforeach ()
 
   # Split the paths into basedirs and module paths.

+ 134 - 0
Modules/Compiler/GNU-CXX-CXXImportStd.cmake

@@ -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 ()

+ 1 - 1
Source/cmExperimental.cxx

@@ -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.",

+ 1 - 1
Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/CMakeLists.txt

@@ -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)

+ 1 - 1
Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/CMakeLists.txt

@@ -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)

+ 1 - 1
Tests/RunCMake/CXXModules/examples/import-std-no-std-property-build-stdout.txt

@@ -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')

+ 1 - 1
Tests/RunCMake/CXXModules/examples/import-std-no-std-property/CMakeLists.txt

@@ -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)

+ 1 - 1
Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/CMakeLists.txt

@@ -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)

+ 1 - 1
Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/CMakeLists.txt

@@ -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)

+ 2 - 1
Tests/RunCMake/CXXModules/examples/import-std-transitive/CMakeLists.txt

@@ -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)

+ 1 - 1
Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt

@@ -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)

+ 1 - 1
Tests/RunCMake/cmake_language/Experimental/CxxImportStd-set.cmake

@@ -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"