From e43486a63919b64fd2eef5d60c9fca1cea83ca94 Mon Sep 17 00:00:00 2001 From: Justin Goshi Date: Thu, 18 Jun 2020 15:42:15 -0700 Subject: cmGeneratorTarget: Clarify name of language property lookup helper --- Source/cmGeneratorTarget.cxx | 14 ++++++++------ Source/cmGeneratorTarget.h | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 1f66a9f..d537be7 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -959,16 +959,17 @@ cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang, return this->Target->GetProperty(cmStrCat(lang, "_STANDARD")); } -cmProp cmGeneratorTarget::GetLanguageStandardProperty(std::string const& lang, - const char* suffix) const +cmProp cmGeneratorTarget::GetPropertyWithPairedLanguageSupport( + std::string const& lang, const char* suffix) const { cmProp propertyValue = this->Target->GetProperty(cmStrCat(lang, suffix)); if (propertyValue == nullptr) { // Check if we should use the value set by another language. if (lang == "OBJC") { - propertyValue = this->GetLanguageStandardProperty("C", suffix); + propertyValue = this->GetPropertyWithPairedLanguageSupport("C", suffix); } else if (lang == "OBJCXX" || lang == "CUDA") { - propertyValue = this->GetLanguageStandardProperty("CXX", suffix); + propertyValue = + this->GetPropertyWithPairedLanguageSupport("CXX", suffix); } } return propertyValue; @@ -976,13 +977,14 @@ cmProp cmGeneratorTarget::GetLanguageStandardProperty(std::string const& lang, cmProp cmGeneratorTarget::GetLanguageExtensions(std::string const& lang) const { - return this->GetLanguageStandardProperty(lang, "_EXTENSIONS"); + return this->GetPropertyWithPairedLanguageSupport(lang, "_EXTENSIONS"); } bool cmGeneratorTarget::GetLanguageStandardRequired( std::string const& lang) const { - cmProp p = this->GetLanguageStandardProperty(lang, "_STANDARD_REQUIRED"); + cmProp p = + this->GetPropertyWithPairedLanguageSupport(lang, "_STANDARD_REQUIRED"); return p && cmIsOn(*p); } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index a71e64c..cd53611 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1052,8 +1052,8 @@ private: mutable std::map LanguageStandardMap; - cmProp GetLanguageStandardProperty(std::string const& lang, - const char* suffix) const; + cmProp GetPropertyWithPairedLanguageSupport(std::string const& lang, + const char* suffix) const; public: const std::vector& GetLinkImplementationClosure( -- cgit v0.12 From ba835874a43599bcc5ee2f8321662eb34fb341aa Mon Sep 17 00:00:00 2001 From: Justin Goshi Date: Thu, 18 Jun 2020 15:42:15 -0700 Subject: Add backtrace support for language standard --- Source/cmGeneratorTarget.cxx | 37 +++++++++++++++++------- Source/cmGeneratorTarget.h | 5 +++- Source/cmMakefile.cxx | 6 ++-- Source/cmTarget.cxx | 69 ++++++++++++++++++++++++++++++++++++++++++++ Source/cmTarget.h | 7 +++++ 5 files changed, 109 insertions(+), 15 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index d537be7..992682f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -947,8 +947,8 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const return it != this->ExplicitObjectName.end(); } -cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang, - std::string const& config) const +BT const* cmGeneratorTarget::GetLanguageStandardProperty( + std::string const& lang, std::string const& config) const { std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang); auto langStandardIter = this->LanguageStandardMap.find(key); @@ -956,7 +956,21 @@ cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang, return &langStandardIter->second; } - return this->Target->GetProperty(cmStrCat(lang, "_STANDARD")); + return this->Target->GetLanguageStandardProperty( + cmStrCat(lang, "_STANDARD")); +} + +cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang, + std::string const& config) const +{ + BT const* languageStandard = + this->GetLanguageStandardProperty(lang, config); + + if (languageStandard) { + return &(languageStandard->Value); + } + + return nullptr; } cmProp cmGeneratorTarget::GetPropertyWithPairedLanguageSupport( @@ -4469,7 +4483,8 @@ bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const } if (!newRequiredStandard.empty()) { - this->LanguageStandardMap[key] = newRequiredStandard; + this->LanguageStandardMap[key] = + BT(newRequiredStandard, f.Backtrace); } } @@ -4480,15 +4495,15 @@ bool cmGeneratorTarget::ComputeCompileFeatures( std::string const& config, std::set const& languagePairs) const { for (const auto& language : languagePairs) { - cmProp generatorTargetLanguageStandard = - this->GetLanguageStandard(language.first, config); + BT const* generatorTargetLanguageStandard = + this->GetLanguageStandardProperty(language.first, config); if (!generatorTargetLanguageStandard) { // If the standard isn't explicitly set we copy it over from the // specified paired language. std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', language.first); - cmProp standardToCopy = - this->GetLanguageStandard(language.second, config); + BT const* standardToCopy = + this->GetLanguageStandardProperty(language.second, config); if (standardToCopy != nullptr) { this->LanguageStandardMap[key] = *standardToCopy; generatorTargetLanguageStandard = &this->LanguageStandardMap[key]; @@ -4496,7 +4511,7 @@ bool cmGeneratorTarget::ComputeCompileFeatures( cmProp defaultStandard = this->Makefile->GetDef( cmStrCat("CMAKE_", language.second, "_STANDARD_DEFAULT")); if (defaultStandard != nullptr) { - this->LanguageStandardMap[key] = *defaultStandard; + this->LanguageStandardMap[key] = BT(*defaultStandard); generatorTargetLanguageStandard = &this->LanguageStandardMap[key]; } } @@ -4504,8 +4519,8 @@ bool cmGeneratorTarget::ComputeCompileFeatures( // Custom updates for the CUDA standard. if (generatorTargetLanguageStandard != nullptr && language.first == "CUDA") { - if (*generatorTargetLanguageStandard == "98") { - this->LanguageStandardMap[key] = "03"; + if (generatorTargetLanguageStandard->Value == "98") { + this->LanguageStandardMap[key].Value = "03"; } } } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index cd53611..20f3a07 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -148,6 +148,9 @@ public: bool HasExplicitObjectName(cmSourceFile const* file) const; void AddExplicitObjectName(cmSourceFile const* sf); + BT const* GetLanguageStandardProperty( + std::string const& lang, std::string const& config) const; + cmProp GetLanguageStandard(std::string const& lang, std::string const& config) const; @@ -1050,7 +1053,7 @@ private: bool GetRPATH(const std::string& config, const std::string& prop, std::string& rpath) const; - mutable std::map LanguageStandardMap; + mutable std::map> LanguageStandardMap; cmProp GetPropertyWithPairedLanguageSupport(std::string const& lang, const char* suffix) const; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 1f1c06a..3161e38 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -5070,7 +5070,7 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard, error)) { if (!newRequiredStandard.empty()) { - target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard); + target->SetLanguageStandardProperty(lang, newRequiredStandard, feature); } return true; } @@ -5251,7 +5251,7 @@ bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target, target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard, error)) { if (!newRequiredStandard.empty()) { - target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard); + target->SetLanguageStandardProperty(lang, newRequiredStandard, feature); } return true; } @@ -5356,7 +5356,7 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target, target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard, error)) { if (!newRequiredStandard.empty()) { - target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard); + target->SetLanguageStandardProperty(lang, newRequiredStandard, feature); } return true; } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 36e1ad5..d3b37cb 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -185,6 +186,7 @@ public: std::vector InstallGenerators; std::set SystemIncludeDirectories; cmTarget::LinkLibraryVectorType OriginalLinkLibraries; + std::map> LanguageStandardProperties; std::vector IncludeDirectoriesEntries; std::vector IncludeDirectoriesBacktraces; std::vector CompileOptionsEntries; @@ -598,6 +600,35 @@ cmGlobalGenerator* cmTarget::GetGlobalGenerator() const return impl->Makefile->GetGlobalGenerator(); } +BT const* cmTarget::GetLanguageStandardProperty( + const std::string& propertyName) const +{ + auto entry = impl->LanguageStandardProperties.find(propertyName); + if (entry != impl->LanguageStandardProperties.end()) { + return &entry->second; + } + + return nullptr; +} + +void cmTarget::SetLanguageStandardProperty(std::string const& lang, + std::string const& value, + const std::string& feature) +{ + cmListFileBacktrace featureBacktrace; + for (size_t i = 0; i < impl->CompileFeaturesEntries.size(); i++) { + if (impl->CompileFeaturesEntries[i] == feature) { + if (i < impl->CompileFeaturesBacktraces.size()) { + featureBacktrace = impl->CompileFeaturesBacktraces[i]; + } + break; + } + } + + impl->LanguageStandardProperties[cmStrCat(lang, "_STANDARD")] = + BT(value, featureBacktrace); +} + void cmTarget::AddUtility(std::string const& name, bool cross, cmMakefile* mf) { impl->Utilities.insert(BT>( @@ -1127,6 +1158,11 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) return; } #define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP + MAKE_STATIC_PROP(C_STANDARD); + MAKE_STATIC_PROP(CXX_STANDARD); + MAKE_STATIC_PROP(CUDA_STANDARD); + MAKE_STATIC_PROP(OBJC_STANDARD); + MAKE_STATIC_PROP(OBJCXX_STANDARD); MAKE_STATIC_PROP(COMPILE_DEFINITIONS); MAKE_STATIC_PROP(COMPILE_FEATURES); MAKE_STATIC_PROP(COMPILE_OPTIONS); @@ -1310,6 +1346,15 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmProp tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME"); this->SetProperty("COMPILE_PDB_NAME", tmp ? tmp->c_str() : nullptr); this->AddUtility(reusedFrom, false, impl->Makefile); + } else if (prop == propC_STANDARD || prop == propCXX_STANDARD || + prop == propCUDA_STANDARD || prop == propOBJC_STANDARD || + prop == propOBJCXX_STANDARD) { + if (value) { + impl->LanguageStandardProperties[prop] = + BT(value, impl->Makefile->GetBacktrace()); + } else { + impl->LanguageStandardProperties.erase(prop); + } } else { impl->Properties.SetProperty(prop, value); } @@ -1413,6 +1458,11 @@ void cmTarget::AppendProperty(const std::string& prop, } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) { impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, prop + " property may not be APPENDed."); + } else if (prop == "C_STANDARD" || prop == "CXX_STANDARD" || + prop == "CUDA_STANDARD" || prop == "OBJC_STANDARD" || + prop == "OBJCXX_STANDARD") { + impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + prop + " property may not be appended."); } else { impl->Properties.AppendProperty(prop, value, asString); } @@ -1626,6 +1676,11 @@ cmProp cmTarget::GetComputedProperty(const std::string& prop, cmProp cmTarget::GetProperty(const std::string& prop) const { #define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP + MAKE_STATIC_PROP(C_STANDARD); + MAKE_STATIC_PROP(CXX_STANDARD); + MAKE_STATIC_PROP(CUDA_STANDARD); + MAKE_STATIC_PROP(OBJC_STANDARD); + MAKE_STATIC_PROP(OBJCXX_STANDARD); MAKE_STATIC_PROP(LINK_LIBRARIES); MAKE_STATIC_PROP(TYPE); MAKE_STATIC_PROP(INCLUDE_DIRECTORIES); @@ -1646,6 +1701,11 @@ cmProp cmTarget::GetProperty(const std::string& prop) const MAKE_STATIC_PROP(TRUE); #undef MAKE_STATIC_PROP static std::unordered_set const specialProps{ + propC_STANDARD, + propCXX_STANDARD, + propCUDA_STANDARD, + propOBJC_STANDARD, + propOBJCXX_STANDARD, propLINK_LIBRARIES, propTYPE, propINCLUDE_DIRECTORIES, @@ -1664,6 +1724,15 @@ cmProp cmTarget::GetProperty(const std::string& prop) const propSOURCES }; if (specialProps.count(prop)) { + if (prop == propC_STANDARD || prop == propCXX_STANDARD || + prop == propCUDA_STANDARD || prop == propOBJC_STANDARD || + prop == propOBJCXX_STANDARD) { + auto propertyIter = impl->LanguageStandardProperties.find(prop); + if (propertyIter == impl->LanguageStandardProperties.end()) { + return nullptr; + } + return &(propertyIter->second.Value); + } if (prop == propLINK_LIBRARIES) { if (impl->LinkImplementationPropertyEntries.empty()) { return nullptr; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index f0ddb68..175822d 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -233,6 +233,13 @@ public: void AddSystemIncludeDirectories(std::set const& incs); std::set const& GetSystemIncludeDirectories() const; + BT const* GetLanguageStandardProperty( + const std::string& propertyName) const; + + void SetLanguageStandardProperty(std::string const& lang, + std::string const& value, + const std::string& feature); + cmStringRange GetIncludeDirectoriesEntries() const; cmBacktraceRange GetIncludeDirectoriesBacktraces() const; -- cgit v0.12 From 7d6861f367673b57bf45e14863f1104e8e28eafa Mon Sep 17 00:00:00 2001 From: Justin Goshi Date: Thu, 18 Jun 2020 15:43:08 -0700 Subject: fileapi: Extend codemodel targets with language standard --- Help/manual/cmake-file-api.7.rst | 18 ++++ Source/cmFileAPI.cxx | 2 +- Source/cmFileAPICodemodel.cxx | 36 +++++++ .../RunCMake/CommandLine/E_capabilities-stdout.txt | 2 +- Tests/RunCMake/FileAPI/codemodel-v2-check.py | 33 ++++++- .../FileAPI/codemodel-v2-data/directories/cxx.json | 2 + .../FileAPI/codemodel-v2-data/projects/cxx.json | 2 + .../codemodel-v2-data/targets/all_build_cxx.json | 8 ++ .../codemodel-v2-data/targets/all_build_top.json | 8 ++ .../targets/cxx_standard_compile_feature_exe.json | 110 +++++++++++++++++++++ ...ndard_compile_feature_exe_languagestandard.json | 22 +++++ .../targets/cxx_standard_exe.json | 110 +++++++++++++++++++++ Tests/RunCMake/FileAPI/cxx/CMakeLists.txt | 10 ++ 13 files changed, 360 insertions(+), 3 deletions(-) create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe.json create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe_languagestandard.json create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_exe.json diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 91be31d..b54859c 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -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 ``_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 diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx index 594969b..c2ab2f1 100644 --- a/Source/cmFileAPI.cxx +++ b/Source/cmFileAPI.cxx @@ -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 const& versions) diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index fe331ec..21d9abb 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -277,6 +277,7 @@ struct CompileData std::string Language; std::string Sysroot; + JBT LanguageStandard; std::vector> Flags; std::vector> Defines; std::vector> 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 result = result ^ hash()(i.Value) ^ hash()(i.Backtrace.Index); } + if (!in.LanguageStandard.Value.empty()) { + result = result ^ hash()(in.LanguageStandard.Value) ^ + hash()(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 const& header); + Json::Value DumpLanguageStandard(JBT const& standard); Json::Value DumpDefine(JBT 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 const& pch : precompileHeaders) { cd.PrecompileHeaders.emplace_back(this->ToJBT(pch)); } + BT 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 const& header) return precompileHeader; } +Json::Value Target::DumpLanguageStandard(JBT 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 const& def) { Json::Value define = Json::objectValue; diff --git a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt index 03286f1..e24e131 100644 --- a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt +++ b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt @@ -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":{.*}}$ diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index a3dd9ff..b567bf1 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -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: diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json index ebe717a..a51b6eb 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json @@ -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$", diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/cxx.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/cxx.json index 296ae6c..363e853 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/cxx.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/cxx.json @@ -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$", diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_cxx.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_cxx.json index 92a7944..1f443b1 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_cxx.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_cxx.json @@ -80,6 +80,14 @@ "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 }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json index b4def78..59bd750 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json @@ -116,6 +116,14 @@ "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 }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe.json new file mode 100644 index 0000000..d6d573f --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe.json @@ -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 + } + ] +} diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe_languagestandard.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe_languagestandard.json new file mode 100644 index 0000000..57b4161 --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe_languagestandard.json @@ -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" + } +} diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_exe.json new file mode 100644 index 0000000..9cb2832 --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_exe.json @@ -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 + } + ] +} diff --git a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt index fa51195..5758cc4 100644 --- a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt +++ b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt @@ -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() -- cgit v0.12