fileapi: Extend codemodel targets with language standard

This commit is contained in:
Justin Goshi 2020-06-18 15:43:08 -07:00 committed by Brad King
parent ba835874a4
commit 7d6861f367
13 changed files with 360 additions and 3 deletions

View File

@ -869,6 +869,24 @@ with members:
A string specifying the language (e.g. ``C``, ``CXX``, ``Fortran``)
of the toolchain is used to compile the source file.
``languageStandard``
Optional member that is present when the language standard is set
explicitly (e.g. via :prop_tgt:`CXX_STANDARD`) or implicitly by
compile features. Each entry is a JSON object with two members:
``backtraces``
Optional member that is present when a CMake language backtrace to
the ``<LANG>_STANDARD`` setting is available. If the language
standard was set implicitly by compile features those are used as
the backtrace(s). It's possible for multiple compile features to
require the same language standard so there could be multiple
backtraces. The value is a JSON array with each entry being an
unsigned integer 0-based index into the ``backtraceGraph``
member's ``nodes`` array.
``standard``
String representing the language standard.
``compileCommandFragments``
Optional member that is present when fragments of the compiler command
line invocation are available. The value is a JSON array of entries

View File

@ -665,7 +665,7 @@ std::string cmFileAPI::NoSupportedVersion(
// The "codemodel" object kind.
static unsigned int const CodeModelV2Minor = 1;
static unsigned int const CodeModelV2Minor = 2;
void cmFileAPI::BuildClientRequestCodeModel(
ClientRequest& r, std::vector<RequestVersion> const& versions)

View File

@ -277,6 +277,7 @@ struct CompileData
std::string Language;
std::string Sysroot;
JBT<std::string> LanguageStandard;
std::vector<JBT<std::string>> Flags;
std::vector<JBT<std::string>> Defines;
std::vector<JBT<std::string>> PrecompileHeaders;
@ -287,6 +288,7 @@ struct CompileData
return (l.Language == r.Language && l.Sysroot == r.Sysroot &&
l.Flags == r.Flags && l.Defines == r.Defines &&
l.PrecompileHeaders == r.PrecompileHeaders &&
l.LanguageStandard == r.LanguageStandard &&
l.Includes == r.Includes);
}
};
@ -320,6 +322,10 @@ struct hash<CompileData>
result = result ^ hash<std::string>()(i.Value) ^
hash<Json::ArrayIndex>()(i.Backtrace.Index);
}
if (!in.LanguageStandard.Value.empty()) {
result = result ^ hash<std::string>()(in.LanguageStandard.Value) ^
hash<Json::ArrayIndex>()(in.LanguageStandard.Backtrace.Index);
}
return result;
}
};
@ -377,6 +383,7 @@ class Target
Json::Value DumpCompileData(CompileData const& cd);
Json::Value DumpInclude(CompileData::IncludeEntry const& inc);
Json::Value DumpPrecompileHeader(JBT<std::string> const& header);
Json::Value DumpLanguageStandard(JBT<std::string> const& standard);
Json::Value DumpDefine(JBT<std::string> const& def);
Json::Value DumpSources();
Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
@ -838,6 +845,11 @@ void Target::ProcessLanguage(std::string const& lang)
for (BT<std::string> const& pch : precompileHeaders) {
cd.PrecompileHeaders.emplace_back(this->ToJBT(pch));
}
BT<std::string> const* languageStandard =
this->GT->GetLanguageStandardProperty(lang, this->Config);
if (languageStandard) {
cd.LanguageStandard = this->ToJBT(*languageStandard);
}
}
Json::ArrayIndex Target::AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si)
@ -996,6 +1008,9 @@ CompileData Target::MergeCompileData(CompileData const& fd)
// All compile groups share the precompile headers of the target.
cd.PrecompileHeaders = td.PrecompileHeaders;
// All compile groups share the language standard of the target.
cd.LanguageStandard = td.LanguageStandard;
// Use target-wide flags followed by source-specific flags.
cd.Flags.reserve(td.Flags.size() + fd.Flags.size());
cd.Flags.insert(cd.Flags.end(), td.Flags.begin(), td.Flags.end());
@ -1153,6 +1168,10 @@ Json::Value Target::DumpCompileData(CompileData const& cd)
}
result["precompileHeaders"] = std::move(precompileHeaders);
}
if (!cd.LanguageStandard.Value.empty()) {
result["languageStandard"] =
this->DumpLanguageStandard(cd.LanguageStandard);
}
return result;
}
@ -1176,6 +1195,23 @@ Json::Value Target::DumpPrecompileHeader(JBT<std::string> const& header)
return precompileHeader;
}
Json::Value Target::DumpLanguageStandard(JBT<std::string> const& standard)
{
Json::Value languageStandard = Json::objectValue;
languageStandard["standard"] = standard.Value;
if (standard.Backtrace) {
// Only one backtrace is currently stored for a given language standard,
// but we represent this as an array because it's possible for multiple
// compile features to set the same language standard value. Representing
// this as an array will allow things to just work once we support storing
// multiple backtraces for a language standard value.
Json::Value backtraces = Json::arrayValue;
backtraces.append(standard.Backtrace.Index);
languageStandard["backtraces"] = backtraces;
}
return languageStandard;
}
Json::Value Target::DumpDefine(JBT<std::string> const& def)
{
Json::Value define = Json::objectValue;

View File

@ -1 +1 @@
^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":1}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":true,"version":{.*}}$
^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":2}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":true,"version":{.*}}$

View File

@ -12,7 +12,7 @@ def read_codemodel_json_data(filename):
def check_objects(o, g):
assert is_list(o)
assert len(o) == 1
check_index_object(o[0], "codemodel", 2, 1, check_object_codemodel(g))
check_index_object(o[0], "codemodel", 2, 2, check_object_codemodel(g))
def check_backtrace(t, b, backtrace):
btg = t["backtraceGraph"]
@ -42,6 +42,16 @@ def check_backtrace(t, b, backtrace):
assert b is None
def check_backtraces(t, actual, expected):
assert is_list(actual)
assert is_list(expected)
assert len(actual) == len(expected)
i = 0
while i < len(actual):
check_backtrace(t, actual[i], expected[i])
i += 1
def check_directory(c):
def _check(actual, expected):
assert is_dict(actual)
@ -421,6 +431,19 @@ def check_target(c):
missing_exception=lambda e: "Precompile header: %s" % e["header"],
extra_exception=lambda a: "Precompile header: %s" % a["header"])
if "languageStandard" in expected:
expected_keys.append("languageStandard")
def check_language_standard(actual, expected):
assert is_dict(actual)
expected_keys = ["backtraces", "standard"]
assert actual["standard"] == expected["standard"]
check_backtraces(obj, actual["backtraces"], expected["backtraces"])
assert sorted(actual.keys()) == sorted(expected_keys)
check_language_standard(actual["languageStandard"], expected["languageStandard"])
if expected["defines"] is not None:
expected_keys.append("defines")
@ -544,6 +567,8 @@ def gen_check_targets(c, g, inSource):
read_codemodel_json_data("targets/zero_check_cxx.json"),
read_codemodel_json_data("targets/cxx_lib.json"),
read_codemodel_json_data("targets/cxx_exe.json"),
read_codemodel_json_data("targets/cxx_standard_compile_feature_exe.json"),
read_codemodel_json_data("targets/cxx_standard_exe.json"),
read_codemodel_json_data("targets/cxx_shared_lib.json"),
read_codemodel_json_data("targets/cxx_shared_exe.json"),
read_codemodel_json_data("targets/cxx_static_lib.json"),
@ -592,6 +617,12 @@ def gen_check_targets(c, g, inSource):
e["sources"] = precompile_header_data["sources"]
e["sourceGroups"] = precompile_header_data["sourceGroups"]
if os.path.exists(os.path.join(reply_dir, "..", "..", "..", "..", "cxx", "cxx_std_11.txt")):
for e in expected:
if e["name"] == "cxx_standard_compile_feature_exe":
language_standard_data = read_codemodel_json_data("targets/cxx_standard_compile_feature_exe_languagestandard.json")
e["compileGroups"][0]["languageStandard"] = language_standard_data["languageStandard"]
if not os.path.exists(os.path.join(reply_dir, "..", "..", "..", "..", "ipo_enabled.txt")):
for e in expected:
try:

View File

@ -7,6 +7,8 @@
"^ALL_BUILD::@a56b12a3f5c0529fb296$",
"^ZERO_CHECK::@a56b12a3f5c0529fb296$",
"^cxx_exe::@a56b12a3f5c0529fb296$",
"^cxx_standard_compile_feature_exe::@a56b12a3f5c0529fb296$",
"^cxx_standard_exe::@a56b12a3f5c0529fb296$",
"^cxx_lib::@a56b12a3f5c0529fb296$",
"^cxx_shared_exe::@a56b12a3f5c0529fb296$",
"^cxx_shared_lib::@a56b12a3f5c0529fb296$",

View File

@ -10,6 +10,8 @@
"^ZERO_CHECK::@a56b12a3f5c0529fb296$",
"^cxx_lib::@a56b12a3f5c0529fb296$",
"^cxx_exe::@a56b12a3f5c0529fb296$",
"^cxx_standard_compile_feature_exe::@a56b12a3f5c0529fb296$",
"^cxx_standard_exe::@a56b12a3f5c0529fb296$",
"^cxx_shared_lib::@a56b12a3f5c0529fb296$",
"^cxx_shared_exe::@a56b12a3f5c0529fb296$",
"^cxx_static_lib::@a56b12a3f5c0529fb296$",

View File

@ -79,6 +79,14 @@
"id": "^cxx_exe::@a56b12a3f5c0529fb296$",
"backtrace": null
},
{
"id": "^cxx_standard_compile_feature_exe::@a56b12a3f5c0529fb296$",
"backtrace": null
},
{
"id": "^cxx_standard_exe::@a56b12a3f5c0529fb296$",
"backtrace": null
},
{
"id": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
"backtrace": null

View File

@ -115,6 +115,14 @@
"id": "^cxx_exe::@a56b12a3f5c0529fb296$",
"backtrace": null
},
{
"id": "^cxx_standard_compile_feature_exe::@a56b12a3f5c0529fb296$",
"backtrace": null
},
{
"id": "^cxx_standard_exe::@a56b12a3f5c0529fb296$",
"backtrace": null
},
{
"id": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
"backtrace": null

View File

@ -0,0 +1,110 @@
{
"name": "cxx_standard_compile_feature_exe",
"id": "^cxx_standard_compile_feature_exe::@a56b12a3f5c0529fb296$",
"directorySource": "^cxx$",
"projectName": "Cxx",
"type": "EXECUTABLE",
"isGeneratorProvided": null,
"sources": [
{
"path": "^empty\\.cxx$",
"isGenerated": null,
"sourceGroupName": "Source Files",
"compileGroupLanguage": "CXX",
"backtrace": [
{
"file": "^cxx/CMakeLists\\.txt$",
"line": 26,
"command": "add_executable",
"hasParent": true
},
{
"file": "^cxx/CMakeLists\\.txt$",
"line": null,
"command": null,
"hasParent": false
}
]
}
],
"sourceGroups": [
{
"name": "Source Files",
"sourcePaths": [
"^empty\\.cxx$"
]
}
],
"compileGroups": [
{
"language": "CXX",
"languageStandard" :
{
"backtraces": [
[
{
"file": "^cxx/CMakeLists\\.txt$",
"line": 27,
"command": "set_property",
"hasParent": true
},
{
"file": "^cxx/CMakeLists\\.txt$",
"line": null,
"command": null,
"hasParent": false
}
]
],
"standard" : "98"
},
"sourcePaths": [
"^empty\\.cxx$"
],
"includes": null,
"defines": null,
"compileCommandFragments": null
}
],
"backtrace": [
{
"file": "^cxx/CMakeLists\\.txt$",
"line": 26,
"command": "add_executable",
"hasParent": true
},
{
"file": "^cxx/CMakeLists\\.txt$",
"line": null,
"command": null,
"hasParent": false
}
],
"folder": null,
"nameOnDisk": "^cxx_standard_compile_feature_exe(\\.exe)?$",
"artifacts": [
{
"path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_standard_compile_feature_exe(\\.exe)?$",
"_dllExtra": false
},
{
"path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_standard_compile_feature_exe\\.pdb$",
"_dllExtra": true
}
],
"build": "^cxx$",
"source": "^cxx$",
"install": null,
"link": {
"language": "CXX",
"lto": null,
"commandFragments": null
},
"archive": null,
"dependencies": [
{
"id": "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
"backtrace": null
}
]
}

View File

@ -0,0 +1,22 @@
{
"languageStandard" :
{
"backtraces": [
[
{
"file": "^cxx/CMakeLists\\.txt$",
"line": 29,
"command": "target_compile_features",
"hasParent": true
},
{
"file": "^cxx/CMakeLists\\.txt$",
"line": null,
"command": null,
"hasParent": false
}
]
],
"standard" : "11"
}
}

View File

@ -0,0 +1,110 @@
{
"name": "cxx_standard_exe",
"id": "^cxx_standard_exe::@a56b12a3f5c0529fb296$",
"directorySource": "^cxx$",
"projectName": "Cxx",
"type": "EXECUTABLE",
"isGeneratorProvided": null,
"sources": [
{
"path": "^empty\\.cxx$",
"isGenerated": null,
"sourceGroupName": "Source Files",
"compileGroupLanguage": "CXX",
"backtrace": [
{
"file": "^cxx/CMakeLists\\.txt$",
"line": 23,
"command": "add_executable",
"hasParent": true
},
{
"file": "^cxx/CMakeLists\\.txt$",
"line": null,
"command": null,
"hasParent": false
}
]
}
],
"sourceGroups": [
{
"name": "Source Files",
"sourcePaths": [
"^empty\\.cxx$"
]
}
],
"compileGroups": [
{
"language": "CXX",
"languageStandard" :
{
"backtraces": [
[
{
"file": "^cxx/CMakeLists\\.txt$",
"line": 24,
"command": "set_property",
"hasParent": true
},
{
"file": "^cxx/CMakeLists\\.txt$",
"line": null,
"command": null,
"hasParent": false
}
]
],
"standard" : "17"
},
"sourcePaths": [
"^empty\\.cxx$"
],
"includes": null,
"defines": null,
"compileCommandFragments": null
}
],
"backtrace": [
{
"file": "^cxx/CMakeLists\\.txt$",
"line": 23,
"command": "add_executable",
"hasParent": true
},
{
"file": "^cxx/CMakeLists\\.txt$",
"line": null,
"command": null,
"hasParent": false
}
],
"folder": null,
"nameOnDisk": "^cxx_standard_exe(\\.exe)?$",
"artifacts": [
{
"path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_standard_exe(\\.exe)?$",
"_dllExtra": false
},
{
"path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_standard_exe\\.pdb$",
"_dllExtra": true
}
],
"build": "^cxx$",
"source": "^cxx$",
"install": null,
"link": {
"language": "CXX",
"lto": null,
"commandFragments": null
},
"archive": null,
"dependencies": [
{
"id": "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
"backtrace": null
}
]
}

View File

@ -19,3 +19,13 @@ target_link_options(cxx_exe PUBLIC TargetLinkOptions)
target_link_directories(cxx_exe PUBLIC "${CMAKE_BINARY_DIR}/TargetLinkDir")
target_precompile_headers(cxx_exe PUBLIC ../empty.h)
add_executable(cxx_standard_exe ../empty.cxx)
set_property(TARGET cxx_standard_exe PROPERTY CXX_STANDARD 17)
add_executable(cxx_standard_compile_feature_exe ../empty.cxx)
set_property(TARGET cxx_standard_compile_feature_exe PROPERTY CXX_STANDARD 98)
if(CMAKE_CXX_STANDARD_DEFAULT AND DEFINED CMAKE_CXX11_STANDARD_COMPILE_OPTION)
target_compile_features(cxx_standard_compile_feature_exe PRIVATE cxx_std_11)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx_std_11.txt" "")
endif()