Jelajahi Sumber

CMakeDetermineCompilerSupport: construct C++ modules targets

Compilers may implement this by implementing a `_cmake_cxx_import_std`
function which takes the standard version as an argument (e.g., `23`)
and creating a target named `CMake::CXX${std}` that represents how
`import std;` should be represented within CMake.
Ben Boeckel 1 tahun lalu
induk
melakukan
f80c60df02

+ 2 - 0
Modules/CMakeCXXCompiler.cmake.in

@@ -91,3 +91,5 @@ set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "@CMAKE_CXX_IMPLICIT_LINK_LIBRARIES@")
 set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES@")
 set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@")
 set(CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR "@CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR@")
+
+@CMAKE_CXX_IMPORT_STD@

+ 14 - 0
Modules/CMakeDetermineCompilerSupport.cmake

@@ -105,6 +105,19 @@ function(cmake_determine_compiler_support lang)
       )
     endif()
 
+    # Create targets for use with `import std;` here.
+    set(CMAKE_CXX_IMPORT_STD "")
+    foreach (_cmake_import_std_version IN ITEMS 23 26)
+      if (CMAKE_CXX${_cmake_import_std_version}_COMPILE_FEATURES)
+        set(_cmake_cxx_import_std "")
+        cmake_create_cxx_import_std("${_cmake_import_std_version}" _cmake_cxx_import_std)
+        if (_cmake_cxx_import_std)
+          string(APPEND CMAKE_CXX_IMPORT_STD "### Imported target for C++${_cmake_import_std_version} standard library\n")
+          string(APPEND CMAKE_CXX_IMPORT_STD "${_cmake_cxx_import_std}\n\n")
+        endif ()
+      endif ()
+    endforeach ()
+
     set(CMAKE_CXX_COMPILE_FEATURES ${CMAKE_CXX_COMPILE_FEATURES} PARENT_SCOPE)
     set(CMAKE_CXX98_COMPILE_FEATURES ${CMAKE_CXX98_COMPILE_FEATURES} PARENT_SCOPE)
     set(CMAKE_CXX11_COMPILE_FEATURES ${CMAKE_CXX11_COMPILE_FEATURES} PARENT_SCOPE)
@@ -113,6 +126,7 @@ function(cmake_determine_compiler_support lang)
     set(CMAKE_CXX20_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES} PARENT_SCOPE)
     set(CMAKE_CXX23_COMPILE_FEATURES ${CMAKE_CXX23_COMPILE_FEATURES} PARENT_SCOPE)
     set(CMAKE_CXX26_COMPILE_FEATURES ${CMAKE_CXX26_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_CXX_IMPORT_STD ${CMAKE_CXX_IMPORT_STD} PARENT_SCOPE)
 
     message(CHECK_PASS "done")
 

+ 35 - 0
Modules/Compiler/CMakeCommonCompilerMacros.cmake

@@ -201,3 +201,38 @@ macro(cmake_record_hip_compile_features)
   _has_compiler_features_hip(11)
   _has_compiler_features_hip(98)
 endmacro()
+
+function(cmake_create_cxx_import_std std variable)
+  set(_cmake_supported_import_std_features
+    # Compilers support `import std` in C++20 as an extension. Skip
+    # for now.
+    # 20
+    23
+    26)
+  list(FIND _cmake_supported_import_std_features "${std}" _cmake_supported_import_std_idx)
+  if (_cmake_supported_import_std_idx EQUAL "-1")
+    return ()
+  endif ()
+  # If the target exists, skip. A toolchain file may have provided it.
+  if (TARGET "__CMAKE::CXX${std}")
+    return ()
+  endif ()
+  # The generator must support imported C++ modules.
+  if (NOT CMAKE_GENERATOR MATCHES "Ninja")
+    return ()
+  endif ()
+  # Check if the compiler understands how to `import std;`.
+  include("${CMAKE_ROOT}/Modules/Compiler/${CMAKE_CXX_COMPILER_ID}-CXX-CXXImportStd.cmake" OPTIONAL RESULT_VARIABLE _cmake_import_std_res)
+  if (NOT _cmake_import_std_res)
+    return ()
+  endif ()
+  if (NOT COMMAND _cmake_cxx_import_std)
+    return ()
+  endif ()
+  _cmake_cxx_import_std("${std}" target_definition)
+  string(CONCAT guarded_target_definition
+    "if (NOT TARGET \"__CMAKE::CXX${std}\")\n"
+    "${target_definition}"
+    "endif ()\n")
+  set("${variable}" "${guarded_target_definition}" PARENT_SCOPE)
+endfunction()