Files
CMake/Modules/Compiler/MSVC-CXX-CXXImportStd.cmake
T
Vito Gamberini fa10dc6c22 Experimental/CXXModules: Implement EcoStd Module Metadata parser
Adds a parser and serializer for the EcoStd Module Metadata format

RFC: https://github.com/ecostd/rfcs/pull/3

This adapts the existing experimental support for import std; to use
the new parser. The CMAKE_CXX_STDLIB_MODULES_JSON is now the canonical
variable for controlling how CMake discovers the stdlib module metadata,
and is used directly by compiler detection.

Toolchains can still override the __CMAKE::CXX## targets if they wish,
either in conjunction with CMAKE_CXX_STDLIB_MODULE_JSON or not. It is
possible to disable automatic detection of
CMAKE_CXX_STDLIB_MODULE_JSON by setting it to the empty string.

When available, the CMAKE_CXX_STDLIB_MODULE_JSON will be used to create
all requested C++ stdlibs which do not already have targets.
2025-11-18 11:39:59 -05:00

105 lines
3.8 KiB
CMake

function (_cmake_cxx_find_modules_json)
if (DEFINED CMAKE_CXX_STDLIB_MODULES_JSON)
return ()
endif ()
find_file(_msvc_modules_json_file
NAME modules.json
HINTS
"$ENV{VCToolsInstallDir}/modules"
PATHS
"$ENV{INCLUDE}"
"${CMAKE_CXX_COMPILER}/../../.."
"${CMAKE_CXX_COMPILER}/../.." # msvc-wine layout
PATH_SUFFIXES
../modules
NO_CACHE)
# Without this file, we do not have modules installed.
if (NOT EXISTS "${_msvc_modules_json_file}")
set(CMAKE_CXX_COMPILER_IMPORT_STD_ERROR_MESSAGE "Could not find `modules.json` resource" PARENT_SCOPE)
return ()
endif ()
file(READ "${_msvc_modules_json_file}" _msvc_modules_json)
string(JSON _msvc_json_modules ERROR_VARIABLE _msvc_json_err GET "${_msvc_modules_json}" "modules")
# This is probably a conforming module metadata file, use it as is
if (_msvc_json_modules)
set(CMAKE_CXX_STDLIB_MODULES_JSON "${_msvc_modules_json_file}" PARENT_SCOPE)
return ()
endif ()
# Otherwise it's a Microsoft STL-style modules.json, check if we recognize it
string(JSON _msvc_json_version GET "${_msvc_modules_json}" "version")
string(JSON _msvc_json_revision GET "${_msvc_modules_json}" "revision")
# Require version 1.
if (NOT _msvc_json_version EQUAL "1")
set(CMAKE_CXX_COMPILER_IMPORT_STD_ERROR_MESSAGE "`modules.json` version ${_msvc_json_version}.${_msvc_json_revision} is not recognized" PARENT_SCOPE)
return ()
endif ()
string(JSON _msvc_json_library GET "${_msvc_modules_json}" "library")
# Bail if we don't understand the library.
if (NOT _msvc_json_library STREQUAL "microsoft/STL")
set(CMAKE_CXX_COMPILER_IMPORT_STD_ERROR_MESSAGE "`modules.json` library `${_msvc_json_library}` is not recognized" PARENT_SCOPE)
return ()
endif ()
string(JSON _msvc_json_sources_len LENGTH "${_msvc_modules_json}" "module-sources")
# Bail if there aren't any sources
if (NOT _msvc_json_sources_len)
set(CMAKE_CXX_COMPILER_IMPORT_STD_ERROR_MESSAGE "`modules.json` does not list any available sources" PARENT_SCOPE)
return ()
endif ()
set(_msvc_module_metadata [=[{
"version": 1,
"revision": 1,
"modules": []
}]=])
cmake_path(GET _msvc_modules_json_file PARENT_PATH _msvc_base_dir)
math(EXPR _msvc_json_sources_len "${_msvc_json_sources_len}-1")
foreach (idx RANGE ${_msvc_json_sources_len})
string(JSON _msvc_source GET "${_msvc_modules_json}" "module-sources" ${idx})
set(_msvc_path ${_msvc_source})
cmake_path(IS_RELATIVE _msvc_path _msvc_is_rel)
if (_msvc_is_rel)
cmake_path(ABSOLUTE_PATH _msvc_path BASE_DIRECTORY "${_msvc_base_dir}")
endif ()
if (_msvc_source MATCHES "std.ixx")
string(JSON _msvc_module_metadata
SET "${_msvc_module_metadata}" "modules" ${idx}
"{
\"logical-name\": \"std\",
\"source-path\": \"${_msvc_path}\",
\"is-std-library\": true
}"
)
elseif (_msvc_source MATCHES "std.compat.ixx")
string(JSON _msvc_module_metadata
SET "${_msvc_module_metadata}" "modules" ${idx}
"{
\"logical-name\": \"std.compat\",
\"source-path\": \"${_msvc_path}\",
\"is-std-library\": true
}"
)
endif ()
endforeach()
string(JSON _msvc_module_metadata_modules_len LENGTH ${_msvc_module_metadata} "modules")
# Bail if we didn't recognize any of the modules
if (NOT _msvc_module_metadata_modules_len)
set(CMAKE_CXX_COMPILER_IMPORT_STD_ERROR_MESSAGE "`modules.json` did not contain any recognized sources (std.ixx, std.compat.ixx)" PARENT_SCOPE)
return ()
endif ()
file(WRITE "${CMAKE_PLATFORM_INFO_DIR}/msvcstl.modules.json" "${_msvc_module_metadata}")
set(CMAKE_CXX_STDLIB_MODULES_JSON "${CMAKE_PLATFORM_INFO_DIR}/msvcstl.modules.json" PARENT_SCOPE)
endfunction ()