mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
fileapi: Test import std target references in codemodel
Add a regression test for the File API codemodel graph produced for an import std target. The test verifies that emitted target references, including those to the CMake-provided stdlib target, resolve to targets present in the codemodel. Closes: #27890
This commit is contained in:
@@ -437,7 +437,10 @@ endif()
|
||||
add_RunCMake_test(FileAPI -DPython_EXECUTABLE=${Python_EXECUTABLE}
|
||||
-DCMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}
|
||||
-DCMAKE_CXX_SIMULATE_ID=${CMAKE_CXX_SIMULATE_ID}
|
||||
-DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA})
|
||||
-DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA}
|
||||
-DCMake_TEST_MODULE_COMPILATION=${CMake_TEST_MODULE_COMPILATION}
|
||||
-DCMake_TEST_MODULE_COMPILATION_RULES=${CMake_TEST_MODULE_COMPILATION_RULES}
|
||||
-DCMake_TEST_CXX_STDLIB_MODULES_JSON=${CMake_TEST_CXX_STDLIB_MODULES_JSON})
|
||||
if(CMAKE_GENERATOR MATCHES "Make|Ninja|FASTBuild")
|
||||
add_RunCMake_test(Instrumentation -DPython_EXECUTABLE=${Python_EXECUTABLE}
|
||||
-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
|
||||
|
||||
@@ -164,3 +164,77 @@ run_object(cmakeFiles-v1)
|
||||
run_object(toolchains-v1)
|
||||
run_object(toolchains-v1 -DTOOLCHAINSV1_COMPILERARGS=1)
|
||||
run_object(toolchains-v1 -DTOOLCHAINSV1_COMPILERARGS=2)
|
||||
|
||||
function(run_import_std_codemodel_test)
|
||||
if(NOT CMake_TEST_MODULE_COMPILATION)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(stdlib_custom_json)
|
||||
if(CMake_TEST_CXX_STDLIB_MODULES_JSON)
|
||||
list(APPEND stdlib_custom_json
|
||||
-DCMAKE_CXX_STDLIB_MODULES_JSON=${CMake_TEST_CXX_STDLIB_MODULES_JSON})
|
||||
endif()
|
||||
|
||||
run_cmake(codemodel-v2-import-std-Inspect ${stdlib_custom_json})
|
||||
include("${RunCMake_BINARY_DIR}/codemodel-v2-import-std-Inspect-build/info.cmake")
|
||||
|
||||
if(RunCMake_GENERATOR MATCHES "Ninja")
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_MAKE_PROGRAM}" --version
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE ninja_version
|
||||
ERROR_VARIABLE err
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
if(res)
|
||||
message(WARNING
|
||||
"Failed to determine `ninja` version: ${err}")
|
||||
set(ninja_version "0")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(generator_supports_cxx_modules 0)
|
||||
if(RunCMake_GENERATOR MATCHES "Ninja" AND
|
||||
ninja_version VERSION_GREATER_EQUAL "1.11" AND
|
||||
"cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
|
||||
set(generator_supports_cxx_modules 1)
|
||||
endif()
|
||||
|
||||
if(RunCMake_GENERATOR MATCHES "Visual Studio" AND
|
||||
CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "19.34")
|
||||
set(generator_supports_cxx_modules 1)
|
||||
endif()
|
||||
|
||||
if(NOT generator_supports_cxx_modules)
|
||||
return()
|
||||
endif()
|
||||
|
||||
string(REPLACE "," ";" cxx_module_features "${CMake_TEST_MODULE_COMPILATION}")
|
||||
if(RunCMake_GENERATOR MATCHES "Ninja")
|
||||
list(APPEND cxx_module_features
|
||||
"ninja")
|
||||
endif()
|
||||
|
||||
if(NOT "import_std23" IN_LIST cxx_module_features OR
|
||||
NOT "cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(RunCMake_TEST_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/codemodel-v2-import-std")
|
||||
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/codemodel-v2-import-std-build")
|
||||
|
||||
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
set(RunCMake_TEST_OPTIONS -DCMAKE_CONFIGURATION_TYPES=Debug)
|
||||
else()
|
||||
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
|
||||
endif()
|
||||
|
||||
list(APPEND RunCMake_TEST_OPTIONS
|
||||
${stdlib_custom_json}
|
||||
"-DCMake_TEST_MODULE_COMPILATION_RULES=${CMake_TEST_MODULE_COMPILATION_RULES}")
|
||||
run_cmake(codemodel-v2-import-std)
|
||||
endfunction()
|
||||
|
||||
run_import_std_codemodel_test()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/../CXXModulesCompile/Inspect.cmake")
|
||||
@@ -0,0 +1,10 @@
|
||||
set(expect
|
||||
reply
|
||||
reply/codemodel-v2-[0-9a-f]+\\.json
|
||||
.*
|
||||
reply/index-[0-9.T-]+\\.json
|
||||
.*
|
||||
)
|
||||
check_api("^${expect}$")
|
||||
|
||||
check_python(codemodel-v2-import-std index)
|
||||
@@ -0,0 +1,140 @@
|
||||
from check_index import *
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
def read_json(filename):
|
||||
with open(os.path.join(reply_dir, filename)) as f:
|
||||
return json.load(f)
|
||||
|
||||
def check_target_id(target_ids, std_target_ids, state, target_file, context, target_id):
|
||||
assert target_id in target_ids, \
|
||||
"Target '%s' has dangling %s target id '%s'." % (target_file, context, target_id)
|
||||
|
||||
if target_id in std_target_ids:
|
||||
state["referenced_std_target"] = True
|
||||
|
||||
def collect_target_ids(codemodel):
|
||||
target_ids = set()
|
||||
target_json_files = set()
|
||||
std_target_ids = set()
|
||||
seen_main_target = False
|
||||
seen_std_target = False
|
||||
|
||||
assert is_list(codemodel["configurations"])
|
||||
assert len(codemodel["configurations"]) > 0
|
||||
|
||||
for configuration in codemodel["configurations"]:
|
||||
for target_list_name in ("targets", "abstractTargets"):
|
||||
for target in configuration[target_list_name]:
|
||||
assert is_dict(target)
|
||||
target_id = target["id"]
|
||||
target_ids.add(target_id)
|
||||
target_json_files.add(target["jsonFile"])
|
||||
|
||||
if target["name"] == "main":
|
||||
seen_main_target = True
|
||||
if target["name"] == "@cmake_cxx_std":
|
||||
seen_std_target = True
|
||||
std_target_ids.add(target_id)
|
||||
|
||||
assert seen_main_target, "The File API codemodel did not report the user target 'main'."
|
||||
assert seen_std_target, \
|
||||
"The File API codemodel did not report the import std target '@cmake_cxx_std'."
|
||||
|
||||
return target_ids, target_json_files, std_target_ids
|
||||
|
||||
def check_target_references(codemodel):
|
||||
target_ids, target_json_files, std_target_ids = collect_target_ids(codemodel)
|
||||
target_id_reference_fields = (
|
||||
"dependencies",
|
||||
"compileDependencies",
|
||||
"interfaceCompileDependencies",
|
||||
"objectDependencies",
|
||||
"orderDependencies",
|
||||
)
|
||||
link_reference_fields = (
|
||||
"linkLibraries",
|
||||
"interfaceLinkLibraries",
|
||||
)
|
||||
state = {
|
||||
"referenced_std_target": False,
|
||||
}
|
||||
|
||||
for target_json_file in sorted(target_json_files):
|
||||
target = read_json(target_json_file)
|
||||
for target_reference_field in target_id_reference_fields:
|
||||
if target_reference_field not in target:
|
||||
continue
|
||||
|
||||
assert is_list(target[target_reference_field])
|
||||
for reference in target[target_reference_field]:
|
||||
assert is_dict(reference)
|
||||
check_target_id(
|
||||
target_ids,
|
||||
std_target_ids,
|
||||
state,
|
||||
target_json_file,
|
||||
target_reference_field,
|
||||
reference["id"])
|
||||
|
||||
if "fromDependency" in reference:
|
||||
assert is_dict(reference["fromDependency"])
|
||||
assert sorted(reference["fromDependency"].keys()) == ["id"]
|
||||
check_target_id(
|
||||
target_ids,
|
||||
std_target_ids,
|
||||
state,
|
||||
target_json_file,
|
||||
target_reference_field + ".fromDependency",
|
||||
reference["fromDependency"]["id"])
|
||||
|
||||
for target_reference_field in link_reference_fields:
|
||||
if target_reference_field not in target:
|
||||
continue
|
||||
|
||||
assert is_list(target[target_reference_field])
|
||||
for reference in target[target_reference_field]:
|
||||
assert is_dict(reference)
|
||||
has_id = "id" in reference
|
||||
has_fragment = "fragment" in reference
|
||||
assert has_id != has_fragment
|
||||
|
||||
if has_id:
|
||||
check_target_id(
|
||||
target_ids,
|
||||
std_target_ids,
|
||||
state,
|
||||
target_json_file,
|
||||
target_reference_field,
|
||||
reference["id"])
|
||||
|
||||
if "fromDependency" in reference:
|
||||
assert is_dict(reference["fromDependency"])
|
||||
assert sorted(reference["fromDependency"].keys()) == ["id"]
|
||||
check_target_id(
|
||||
target_ids,
|
||||
std_target_ids,
|
||||
state,
|
||||
target_json_file,
|
||||
target_reference_field + ".fromDependency",
|
||||
reference["fromDependency"]["id"])
|
||||
|
||||
assert state["referenced_std_target"], \
|
||||
"The File API codemodel did not reference '@cmake_cxx_std' from any target relationship."
|
||||
|
||||
assert is_dict(index)
|
||||
assert sorted(index.keys()) == ["cmake", "objects", "reply"]
|
||||
assert is_list(index["objects"])
|
||||
|
||||
codemodel_index = None
|
||||
for index_object in index["objects"]:
|
||||
if index_object["kind"] == "codemodel":
|
||||
codemodel_index = index_object
|
||||
break
|
||||
|
||||
assert codemodel_index is not None, "No codemodel object found in File API index."
|
||||
assert codemodel_index["version"]["major"] == 2
|
||||
|
||||
codemodel = read_json(codemodel_index["jsonFile"])
|
||||
check_target_references(codemodel)
|
||||
@@ -0,0 +1,12 @@
|
||||
CMake Warning \(experimental\) at [^
|
||||
]*/Modules/Compiler/CMakeCommonCompilerMacros\.cmake:[0-9]* \(cmake_language\):
|
||||
CMake's support for `import std;` in C\+\+23 and newer is experimental\. It
|
||||
is meant only for experimentation and feedback to CMake developers\.
|
||||
Call Stack \(most recent call first\):
|
||||
[^
|
||||
]*/Modules/CMakeDetermineCompilerSupport\.cmake:[0-9]* \(cmake_cxx_find_modules_json\)
|
||||
[^
|
||||
]*/Modules/CMakeTestCXXCompiler\.cmake:[0-9]* \(CMAKE_DETERMINE_COMPILER_SUPPORT\)
|
||||
CMakeLists\.txt:[0-9]* \(project\)
|
||||
This warning is for project developers\. Use -Wno-author or -Wno-experimental
|
||||
to suppress it\.
|
||||
@@ -0,0 +1,15 @@
|
||||
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
|
||||
"f35a9ac6-8463-4d38-8eec-5d6008153e7d")
|
||||
|
||||
cmake_minimum_required(VERSION 3.29)
|
||||
project(codemodel_v2_import_std CXX)
|
||||
|
||||
cmake_file_api(QUERY API_VERSION 1 CODEMODEL 2)
|
||||
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/../../CXXModulesCompile/cxx-modules-rules.cmake")
|
||||
|
||||
set(CMAKE_CXX_MODULE_STD 1)
|
||||
|
||||
add_executable(main
|
||||
main.cxx)
|
||||
target_compile_features(main PRIVATE cxx_std_23)
|
||||
@@ -0,0 +1,6 @@
|
||||
import std;
|
||||
|
||||
auto main() -> int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user