1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
function (_cmake_cxx_import_std std variable)
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++` and `libstdc++` are supported\")\n"
PARENT_SCOPE)
return ()
endif ()
execute_process(
COMMAND
"${CMAKE_CXX_COMPILER}"
${CMAKE_CXX_COMPILER_ID_ARG1}
"-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
OUTPUT_STRIP_TRAILING_WHITESPACE
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 `${_clang_modules_json_impl}.modules.json` resource\")\n"
PARENT_SCOPE)
return ()
endif ()
# 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 \"`${_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" 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 `${_clang_modules_json_impl}.modules.json` format fix\")\n"
PARENT_SCOPE)
return ()
endif ()
file(READ "${_clang_libcxx_modules_json_file}" _clang_libcxx_modules_json)
string(JSON _clang_modules_json_version GET "${_clang_libcxx_modules_json}" "version")
string(JSON _clang_modules_json_revision GET "${_clang_libcxx_modules_json}" "revision")
# Require version 1.
if (NOT _clang_modules_json_version EQUAL "1")
set("${variable}"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"`libc++.modules.json` version ${_clang_modules_json_version}.${_clang_modules_json_revision} is not recognized\")\n"
PARENT_SCOPE)
return ()
endif ()
string(JSON _clang_modules_json_nmodules LENGTH "${_clang_libcxx_modules_json}" "modules")
# Don't declare the target without any modules.
if (NOT _clang_modules_json_nmodules)
set("${variable}"
"set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"`libc++.modules.json` does not list any available modules\")\n"
PARENT_SCOPE)
return ()
endif ()
# Declare the target.
set(_clang_libcxx_target "")
# Clang 18 does not provide the module initializer for the `std` modules.
# Create a static library to hold these. Hope that Clang 19 can provide this,
# but never run the code.
string(APPEND _clang_libcxx_target
"add_library(__cmake_cxx${std} STATIC)\n")
string(APPEND _clang_libcxx_target
"target_sources(__cmake_cxx${std} INTERFACE \"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>:$<TARGET_OBJECTS:__cmake_cxx${std}>>\")\n")
string(APPEND _clang_libcxx_target
"set_property(TARGET __cmake_cxx${std} PROPERTY EXCLUDE_FROM_ALL 1)\n")
string(APPEND _clang_libcxx_target
"set_property(TARGET __cmake_cxx${std} PROPERTY CXX_SCAN_FOR_MODULES 1)\n")
string(APPEND _clang_libcxx_target
"set_property(TARGET __cmake_cxx${std} PROPERTY CXX_MODULE_STD 0)\n")
string(APPEND _clang_libcxx_target
"target_compile_features(__cmake_cxx${std} PUBLIC cxx_std_${std})\n")
set(_clang_modules_is_stdlib 0)
set(_clang_modules_include_dirs_list "")
set(_clang_modules_module_paths "")
get_filename_component(_clang_modules_dir "${_clang_libcxx_modules_json_file}" DIRECTORY)
# Add module sources.
math(EXPR _clang_modules_json_nmodules_range "${_clang_modules_json_nmodules} - 1")
foreach (_clang_modules_json_modules_idx RANGE 0 "${_clang_modules_json_nmodules_range}")
string(JSON _clang_modules_json_module GET "${_clang_libcxx_modules_json}" "modules" "${_clang_modules_json_modules_idx}")
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 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 ()
list(APPEND _clang_modules_module_paths
"${_clang_modules_json_module_source}")
if (_clang_modules_json_module_is_stdlib)
set(_clang_modules_is_stdlib 1)
endif ()
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.
set(_clang_modules_base_dirs_list "")
set(_clang_modules_files "")
foreach (_clang_modules_module_path IN LISTS _clang_modules_module_paths)
get_filename_component(_clang_module_dir "${_clang_modules_module_path}" DIRECTORY)
list(APPEND _clang_modules_base_dirs_list
"${_clang_module_dir}")
string(APPEND _clang_modules_files
" \"${_clang_modules_module_path}\"")
endforeach ()
list(REMOVE_DUPLICATES _clang_modules_base_dirs_list)
set(_clang_modules_base_dirs "")
foreach (_clang_modules_base_dir IN LISTS _clang_modules_base_dirs_list)
string(APPEND _clang_modules_base_dirs
" \"${_clang_modules_base_dir}\"")
endforeach ()
# If we have a standard library module, suppress warnings about reserved
# module names.
if (_clang_modules_is_stdlib)
string(APPEND _clang_libcxx_target
"target_compile_options(__cmake_cxx${std} PRIVATE -Wno-reserved-module-identifier)\n")
endif ()
# Set up include directories.
list(REMOVE_DUPLICATES _clang_modules_include_dirs_list)
set(_clang_modules_include_dirs "")
foreach (_clang_modules_include_dir IN LISTS _clang_modules_include_dirs_list)
string(APPEND _clang_modules_include_dirs
" \"${_clang_modules_include_dir}\"")
endforeach ()
string(APPEND _clang_libcxx_target
"target_include_directories(__cmake_cxx${std} PRIVATE ${_clang_modules_include_dirs})\n")
# Create the file set for the modules.
string(APPEND _clang_libcxx_target
"target_sources(__cmake_cxx${std}
PUBLIC
FILE_SET std TYPE CXX_MODULES
BASE_DIRS ${_clang_modules_base_dirs}
FILES ${_clang_modules_files})\n")
# Wrap the `__cmake_cxx${std}` target in a check.
string(PREPEND _clang_libcxx_target
"if (NOT TARGET \"__cmake_cxx${std}\")\n")
string(APPEND _clang_libcxx_target
"endif ()\n")
string(APPEND _clang_libcxx_target
"add_library(__CMAKE::CXX${std} ALIAS __cmake_cxx${std})\n")
set("${variable}" "${_clang_libcxx_target}" PARENT_SCOPE)
endfunction ()
|