1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00
Files
CMake/Modules/Compiler/GNU-CXX-CXXImportStd.cmake
Ben Boeckel 2b85541e39 cxximportstd: support setting the import std metadata location
Some deployments may not be able to discover the metadata file reliably
(e.g., custom `clang` builds on macOS while using the SDK's stdlib or
distribution bugs). Allow users to force the location so that
compiler-driven detection doesn't have to bend over backwards for
unforeseen bugs.
2025-09-11 18:03:00 -04:00

139 lines
6.1 KiB
CMake

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 ()
if (CMAKE_CXX_STDLIB_MODULES_JSON)
set(_gnu_libstdcxx_modules_json_file "${CMAKE_CXX_STDLIB_MODULES_JSON}")
else ()
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 ()
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 ()