From fc7e4d1ed85370d03acbd62bc753cced3550752b Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 6 Sep 2018 13:10:55 -0400 Subject: cmLinkItem: Convert to a "sum type" over a string and target pointer Avoid exposing the item name implicitly as std::string. When the item is a target, avoid storing a second copy of its name. Most link item construction is paired with calls to `FindTargetToLink` to get the possible target pointer. Rename these methods to `ResolveLinkItem` and refactor them to construct the entire item. --- Source/CMakeLists.txt | 1 + Source/cmComputeLinkDepends.cxx | 30 ++++++++-------- Source/cmComputeLinkDepends.h | 3 +- Source/cmComputeTargetDepends.cxx | 8 ++--- Source/cmExportFileGenerator.cxx | 12 ++++++- Source/cmGeneratorTarget.cxx | 44 +++++++++++++----------- Source/cmGeneratorTarget.h | 2 +- Source/cmLinkItem.cxx | 72 +++++++++++++++++++++++++++++++++++++++ Source/cmLinkItem.h | 38 +++++++-------------- bootstrap | 1 + 10 files changed, 145 insertions(+), 66 deletions(-) create mode 100644 Source/cmLinkItem.cxx diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 0457984..628cc6f 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -265,6 +265,7 @@ set(SRCS cmInstallDirectoryGenerator.h cmInstallDirectoryGenerator.cxx cmLinkedTree.h + cmLinkItem.cxx cmLinkItem.h cmLinkLineComputer.cxx cmLinkLineComputer.h diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index b1f3860..3659a1e 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -295,22 +295,24 @@ std::map::iterator cmComputeLinkDepends::AllocateLinkEntry( int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) { // Check if the item entry has already been added. - std::map::iterator lei = this->LinkEntryIndex.find(item); + std::map::iterator lei = + this->LinkEntryIndex.find(item.AsStr()); if (lei != this->LinkEntryIndex.end()) { // Yes. We do not need to follow the item's dependencies again. return lei->second; } // Allocate a spot for the item entry. - lei = this->AllocateLinkEntry(item); + lei = this->AllocateLinkEntry(item.AsStr()); // Initialize the item entry. int index = lei->second; LinkEntry& entry = this->EntryList[index]; - entry.Item = item; + entry.Item = item.AsStr(); entry.Target = item.Target; - entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' && - item.substr(0, 10) != "-framework"); + entry.IsFlag = + (!entry.Target && entry.Item[0] == '-' && entry.Item[1] != 'l' && + entry.Item.substr(0, 10) != "-framework"); // If the item has dependencies queue it to follow them. if (entry.Target) { @@ -396,14 +398,14 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) { // Check if the target already has an entry. std::map::iterator lei = - this->LinkEntryIndex.find(dep.Item); + this->LinkEntryIndex.find(dep.Item.AsStr()); if (lei == this->LinkEntryIndex.end()) { // Allocate a spot for the item entry. - lei = this->AllocateLinkEntry(dep.Item); + lei = this->AllocateLinkEntry(dep.Item.AsStr()); // Initialize the item entry. LinkEntry& entry = this->EntryList[lei->second]; - entry.Item = dep.Item; + entry.Item = dep.Item.AsStr(); entry.Target = dep.Item.Target; // This item was added specifically because it is a dependent @@ -473,9 +475,9 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, // If the library is meant for this link type then use it. if (llt == GENERAL_LibraryType || llt == this->LinkType) { - actual_libs.emplace_back(d, this->FindTargetToLink(depender_index, d)); + actual_libs.emplace_back(this->ResolveLinkItem(depender_index, d)); } else if (this->OldLinkDirMode) { - cmLinkItem item(d, this->FindTargetToLink(depender_index, d)); + cmLinkItem item = this->ResolveLinkItem(depender_index, d); this->CheckWrongConfigItem(item); } @@ -512,7 +514,7 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, // Skip entries that will resolve to the target getting linked or // are empty. cmLinkItem const& item = l; - if (item == this->Target->GetName() || item.empty()) { + if (item.AsStr() == this->Target->GetName() || item.AsStr().empty()) { continue; } @@ -553,8 +555,8 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, } } -cmGeneratorTarget const* cmComputeLinkDepends::FindTargetToLink( - int depender_index, const std::string& name) +cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index, + const std::string& name) { // Look for a target in the scope of the depender. cmGeneratorTarget const* from = this->Target; @@ -564,7 +566,7 @@ cmGeneratorTarget const* cmComputeLinkDepends::FindTargetToLink( from = depender; } } - return from->FindTargetToLink(name); + return from->ResolveLinkItem(name); } void cmComputeLinkDepends::InferDependencies() diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index dd0e029..fb3a02f 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -79,8 +79,7 @@ private: void AddDirectLinkEntries(); template void AddLinkEntries(int depender_index, std::vector const& libs); - cmGeneratorTarget const* FindTargetToLink(int depender_index, - const std::string& name); + cmLinkItem ResolveLinkItem(int depender_index, const std::string& name); // One entry for each unique item. std::vector EntryList; diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index efdd3a5..edda2bd 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -229,7 +229,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) emitted.insert(depender->GetName()); for (cmLinkImplItem const& lib : impl->Libraries) { // Don't emit the same library twice for this target. - if (emitted.insert(lib).second) { + if (emitted.insert(lib.AsStr()).second) { this->AddTargetDepend(depender_index, lib, true); this->AddInterfaceDepends(depender_index, lib, it, emitted); } @@ -245,7 +245,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) emitted.insert(depender->GetName()); for (cmLinkItem const& litem : tutils) { // Don't emit the same utility twice for this target. - if (emitted.insert(litem).second) { + if (emitted.insert(litem.AsStr()).second) { this->AddTargetDepend(depender_index, litem, false); } } @@ -261,7 +261,7 @@ void cmComputeTargetDepends::AddInterfaceDepends( dependee->GetLinkInterface(config, depender)) { for (cmLinkItem const& lib : iface->Libraries) { // Don't emit the same library twice for this target. - if (emitted.insert(lib).second) { + if (emitted.insert(lib.AsStr()).second) { this->AddTargetDepend(depender_index, lib, true); this->AddInterfaceDepends(depender_index, lib, config, emitted); } @@ -324,7 +324,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, << depender->GetName() << "\" does not exist."; cmListFileBacktrace const* backtrace = - depender->GetUtilityBacktrace(dependee_name); + depender->GetUtilityBacktrace(dependee_name.AsStr()); if (backtrace) { cm->IssueMessage(messageType, e.str(), *backtrace); } else { diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 75d3374..1c5040a 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -831,6 +831,16 @@ void cmExportFileGenerator::SetImportDetailProperties( } } +static std::string const& asString(std::string const& l) +{ + return l; +} + +static std::string const& asString(cmLinkItem const& l) +{ + return l.AsStr(); +} + template void cmExportFileGenerator::SetImportLinkProperty( std::string const& suffix, cmGeneratorTarget* target, @@ -850,7 +860,7 @@ void cmExportFileGenerator::SetImportLinkProperty( link_entries += sep; sep = ";"; - std::string temp = l; + std::string temp = asString(l); this->AddTargetNamespace(temp, target, missingTargets); link_entries += temp; } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 80a99d5..377c008 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -671,9 +671,12 @@ std::set const& cmGeneratorTarget::GetUtilityItems() const this->UtilityItemsDone = true; std::set const& utilities = this->GetUtilities(); for (std::string const& i : utilities) { - cmGeneratorTarget* gt = - this->LocalGenerator->FindGeneratorTargetToUse(i); - this->UtilityItems.insert(cmLinkItem(i, gt)); + if (cmGeneratorTarget* gt = + this->LocalGenerator->FindGeneratorTargetToUse(i)) { + this->UtilityItems.insert(cmLinkItem(gt)); + } else { + this->UtilityItems.insert(cmLinkItem(i)); + } } } return this->UtilityItems; @@ -816,7 +819,8 @@ static void AddInterfaceEntries( thisTarget->GetLinkImplementationLibraries(config)) { for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target) { - std::string genex = "$"; + std::string genex = + "$"; cmGeneratorExpression ge(lib.Backtrace); std::unique_ptr cge = ge.Parse(genex); cge->SetEvaluateForBuildsystem(true); @@ -836,7 +840,7 @@ static void AddObjectEntries( for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target && lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { - std::string genex = "$"; + std::string genex = "$"; cmGeneratorExpression ge(lib.Backtrace); std::unique_ptr cge = ge.Parse(genex); cge->SetEvaluateForBuildsystem(true); @@ -860,7 +864,7 @@ static bool processSources( for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { cmLinkImplItem const& item = entry->LinkImplItem; - std::string const& targetName = item; + std::string const& targetName = item.AsStr(); std::vector entrySources; cmSystemTools::ExpandListArgument( entry->ge->Evaluate(tgt->GetLocalGenerator(), config, false, tgt, tgt, @@ -1756,7 +1760,7 @@ public: void Visit(cmLinkItem const& item) { if (!item.Target) { - if (item.find("::") != std::string::npos) { + if (item.AsStr().find("::") != std::string::npos) { bool noMessage = false; cmake::MessageType messageType = cmake::FATAL_ERROR; std::ostringstream e; @@ -1777,7 +1781,7 @@ public: if (!noMessage) { e << "Target \"" << this->Target->GetName() - << "\" links to target \"" << item + << "\" links to target \"" << item.AsStr() << "\" but the target was not found. Perhaps a find_package() " "call is missing for an IMPORTED target, or an ALIAS target is " "missing?"; @@ -2477,7 +2481,7 @@ static void processIncludeDirectories( { for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { cmLinkImplItem const& item = entry->LinkImplItem; - std::string const& targetName = item; + std::string const& targetName = item.AsStr(); bool const fromImported = item.Target && item.Target->IsImported(); bool const checkCMP0027 = item.FromGenex; std::vector entryIncludes; @@ -2615,7 +2619,7 @@ std::vector cmGeneratorTarget::GetIncludeDirectories( cmLinkImplementationLibraries const* impl = this->GetLinkImplementationLibraries(config); for (cmLinkImplItem const& lib : impl->Libraries) { - std::string libDir = cmSystemTools::CollapseFullPath(lib); + std::string libDir = cmSystemTools::CollapseFullPath(lib.AsStr()); static cmsys::RegularExpression frameworkCheck( "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); @@ -4495,7 +4499,7 @@ void cmGeneratorTarget::LookupLinkItems(std::vector const& names, if (name == this->GetName() || name.empty()) { continue; } - items.emplace_back(name, this->FindTargetToLink(name)); + items.push_back(this->ResolveLinkItem(name)); } } @@ -4573,12 +4577,12 @@ void cmGeneratorTarget::ComputeLinkInterface( // on other shared libraries that are not in the interface. std::unordered_set emitted; for (cmLinkItem const& lib : iface.Libraries) { - emitted.insert(lib); + emitted.insert(lib.AsStr()); } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { cmLinkImplementation const* impl = this->GetLinkImplementation(config); for (cmLinkImplItem const& lib : impl->Libraries) { - if (emitted.insert(lib).second) { + if (emitted.insert(lib.AsStr()).second) { if (lib.Target) { // This is a runtime dependency on another shared library. if (lib.Target->GetType() == cmStateEnums::SHARED_LIBRARY) { @@ -5603,7 +5607,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // The entry is meant for this configuration. - impl.Libraries.emplace_back(name, this->FindTargetToLink(name), *btIt, + impl.Libraries.emplace_back(this->ResolveLinkItem(name), *btIt, evaluated != *le); } @@ -5631,14 +5635,12 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( continue; } // Support OLD behavior for CMP0003. - impl.WrongConfigLibraries.emplace_back(name, - this->FindTargetToLink(name)); + impl.WrongConfigLibraries.push_back(this->ResolveLinkItem(name)); } } } -cmGeneratorTarget* cmGeneratorTarget::FindTargetToLink( - std::string const& name) const +cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name) const { cmGeneratorTarget* tgt = this->LocalGenerator->FindGeneratorTargetToUse(name); @@ -5651,7 +5653,11 @@ cmGeneratorTarget* cmGeneratorTarget::FindTargetToLink( tgt = nullptr; } - return tgt; + if (tgt) { + return cmLinkItem(tgt); + } + + return cmLinkItem(name); } std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 1030d91..a847e21 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -357,7 +357,7 @@ public: cmOptionalLinkImplementation& impl, const cmGeneratorTarget* head) const; - cmGeneratorTarget* FindTargetToLink(std::string const& name) const; + cmLinkItem ResolveLinkItem(std::string const& name) const; // Compute the set of languages compiled by the target. This is // computed every time it is called because the languages can change diff --git a/Source/cmLinkItem.cxx b/Source/cmLinkItem.cxx new file mode 100644 index 0000000..69b6821 --- /dev/null +++ b/Source/cmLinkItem.cxx @@ -0,0 +1,72 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmLinkItem.h" + +#include "cmGeneratorTarget.h" + +#include // IWYU pragma: keep + +cmLinkItem::cmLinkItem() + : String() + , Target(nullptr) +{ +} + +cmLinkItem::cmLinkItem(std::string const& n) + : String(n) + , Target(nullptr) +{ +} + +cmLinkItem::cmLinkItem(cmGeneratorTarget const* t) + : String() + , Target(t) +{ +} + +std::string const& cmLinkItem::AsStr() const +{ + return this->Target ? this->Target->GetName() : this->String; +} + +bool operator<(cmLinkItem const& l, cmLinkItem const& r) +{ + // Order among targets. + if (l.Target && r.Target) { + return l.Target < r.Target; + } + // Order targets before strings. + if (l.Target) { + return true; + } + if (r.Target) { + return false; + } + // Order among strings. + return l.String < r.String; +} + +bool operator==(cmLinkItem const& l, cmLinkItem const& r) +{ + return l.Target == r.Target && l.String == r.String; +} + +std::ostream& operator<<(std::ostream& os, cmLinkItem const& item) +{ + return os << item.AsStr(); +} + +cmLinkImplItem::cmLinkImplItem() + : cmLinkItem() + , Backtrace() + , FromGenex(false) +{ +} + +cmLinkImplItem::cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt, + bool fromGenex) + : cmLinkItem(std::move(item)) + , Backtrace(bt) + , FromGenex(fromGenex) +{ +} diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index e8c9487..74fd298 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -17,40 +18,27 @@ class cmGeneratorTarget; // Basic information about each link item. -class cmLinkItem : public std::string +class cmLinkItem { - typedef std::string std_string; + std::string String; public: - cmLinkItem() - : std_string() - , Target(nullptr) - { - } - cmLinkItem(const std_string& n, cmGeneratorTarget const* t) - : std_string(n) - , Target(t) - { - } + cmLinkItem(); + explicit cmLinkItem(std::string const& s); + explicit cmLinkItem(cmGeneratorTarget const* t); + std::string const& AsStr() const; cmGeneratorTarget const* Target; + friend bool operator<(cmLinkItem const& l, cmLinkItem const& r); + friend bool operator==(cmLinkItem const& l, cmLinkItem const& r); + friend std::ostream& operator<<(std::ostream& os, cmLinkItem const& item); }; class cmLinkImplItem : public cmLinkItem { public: - cmLinkImplItem() - : cmLinkItem() - , Backtrace() - , FromGenex(false) - { - } - cmLinkImplItem(std::string const& n, cmGeneratorTarget const* t, - cmListFileBacktrace const& bt, bool fromGenex) - : cmLinkItem(n, t) - , Backtrace(bt) - , FromGenex(fromGenex) - { - } + cmLinkImplItem(); + cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt, + bool fromGenex); cmListFileBacktrace Backtrace; bool FromGenex; }; diff --git a/bootstrap b/bootstrap index 0b49b74..188193d 100755 --- a/bootstrap +++ b/bootstrap @@ -352,6 +352,7 @@ CMAKE_CXX_SOURCES="\ cmInstallTargetsCommand \ cmInstalledFile \ cmLinkDirectoriesCommand \ + cmLinkItem \ cmLinkLineComputer \ cmListCommand \ cmListFileCache \ -- cgit v0.12 From bea390e9bd68e1aa7d86b6aef7384f502c39068c Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 6 Sep 2018 14:21:06 -0400 Subject: Fix dependency propagation through same-name imported targets If two imported targets in different directories have the same name we should still be able to propagate transitive link dependencies from both. Fix the target and link dependency analyzers to de-duplicate targets using target pointers rather than target names since the pointers will not be duplicated even if the names are. Issue: #18345 --- Source/cmComputeLinkDepends.cxx | 19 ++++++------- Source/cmComputeLinkDepends.h | 6 ++-- Source/cmComputeTargetDepends.cxx | 50 ++++++++++++++++++--------------- Source/cmComputeTargetDepends.h | 4 +-- Source/cmGeneratorTarget.cxx | 6 ++-- Tests/CMakeLists.txt | 1 + Tests/ImportedSameName/A/CMakeLists.txt | 7 +++++ Tests/ImportedSameName/A/a.c | 3 ++ Tests/ImportedSameName/B/CMakeLists.txt | 7 +++++ Tests/ImportedSameName/B/b.c | 3 ++ Tests/ImportedSameName/CMakeLists.txt | 8 ++++++ Tests/ImportedSameName/main.c | 9 ++++++ 12 files changed, 82 insertions(+), 41 deletions(-) create mode 100644 Tests/ImportedSameName/A/CMakeLists.txt create mode 100644 Tests/ImportedSameName/A/a.c create mode 100644 Tests/ImportedSameName/B/CMakeLists.txt create mode 100644 Tests/ImportedSameName/B/b.c create mode 100644 Tests/ImportedSameName/CMakeLists.txt create mode 100644 Tests/ImportedSameName/main.c diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 3659a1e..aa17de6 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -279,12 +279,12 @@ cmComputeLinkDepends::Compute() return this->FinalLinkEntries; } -std::map::iterator cmComputeLinkDepends::AllocateLinkEntry( - std::string const& item) +std::map::iterator cmComputeLinkDepends::AllocateLinkEntry( + cmLinkItem const& item) { - std::map::value_type index_entry( + std::map::value_type index_entry( item, static_cast(this->EntryList.size())); - std::map::iterator lei = + std::map::iterator lei = this->LinkEntryIndex.insert(index_entry).first; this->EntryList.emplace_back(); this->InferredDependSets.push_back(nullptr); @@ -295,15 +295,14 @@ std::map::iterator cmComputeLinkDepends::AllocateLinkEntry( int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) { // Check if the item entry has already been added. - std::map::iterator lei = - this->LinkEntryIndex.find(item.AsStr()); + std::map::iterator lei = this->LinkEntryIndex.find(item); if (lei != this->LinkEntryIndex.end()) { // Yes. We do not need to follow the item's dependencies again. return lei->second; } // Allocate a spot for the item entry. - lei = this->AllocateLinkEntry(item.AsStr()); + lei = this->AllocateLinkEntry(item); // Initialize the item entry. int index = lei->second; @@ -397,11 +396,11 @@ void cmComputeLinkDepends::QueueSharedDependencies( void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) { // Check if the target already has an entry. - std::map::iterator lei = - this->LinkEntryIndex.find(dep.Item.AsStr()); + std::map::iterator lei = + this->LinkEntryIndex.find(dep.Item); if (lei == this->LinkEntryIndex.end()) { // Allocate a spot for the item entry. - lei = this->AllocateLinkEntry(dep.Item.AsStr()); + lei = this->AllocateLinkEntry(dep.Item); // Initialize the item entry. LinkEntry& entry = this->EntryList[lei->second]; diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index fb3a02f..66fb1e6 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -72,8 +72,8 @@ private: std::string Config; EntryVector FinalLinkEntries; - std::map::iterator AllocateLinkEntry( - std::string const& item); + std::map::iterator AllocateLinkEntry( + cmLinkItem const& item); int AddLinkEntry(cmLinkItem const& item); void AddVarLinkEntries(int depender_index, const char* value); void AddDirectLinkEntries(); @@ -83,7 +83,7 @@ private: // One entry for each unique item. std::vector EntryList; - std::map LinkEntryIndex; + std::map LinkEntryIndex; // BFS of initial dependencies. struct BFSEntry diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index edda2bd..268e749 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -195,7 +195,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // dependencies in all targets, because the generated build-systems can't // deal with config-specific dependencies. { - std::set emitted; + std::set emitted; std::vector configs; depender->Makefile->GetConfigurations(configs); @@ -206,30 +206,34 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) std::vector objectFiles; depender->GetExternalObjects(objectFiles, it); for (cmSourceFile const* o : objectFiles) { - std::string objLib = o->GetObjectLibrary(); - if (!objLib.empty() && emitted.insert(objLib).second) { - if (depender->GetType() != cmStateEnums::EXECUTABLE && - depender->GetType() != cmStateEnums::STATIC_LIBRARY && - depender->GetType() != cmStateEnums::SHARED_LIBRARY && - depender->GetType() != cmStateEnums::MODULE_LIBRARY && - depender->GetType() != cmStateEnums::OBJECT_LIBRARY) { - this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, - "Only executables and libraries may reference target objects.", - depender->GetBacktrace()); - return; + std::string const& objLib = o->GetObjectLibrary(); + if (!objLib.empty()) { + cmLinkItem const& objItem = depender->ResolveLinkItem(objLib); + if (emitted.insert(objItem).second) { + if (depender->GetType() != cmStateEnums::EXECUTABLE && + depender->GetType() != cmStateEnums::STATIC_LIBRARY && + depender->GetType() != cmStateEnums::SHARED_LIBRARY && + depender->GetType() != cmStateEnums::MODULE_LIBRARY && + depender->GetType() != cmStateEnums::OBJECT_LIBRARY) { + this->GlobalGenerator->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, + "Only executables and libraries may reference target objects.", + depender->GetBacktrace()); + return; + } + const_cast(depender)->Target->AddUtility( + objLib); } - const_cast(depender)->Target->AddUtility(objLib); } } cmLinkImplementation const* impl = depender->GetLinkImplementation(it); // A target should not depend on itself. - emitted.insert(depender->GetName()); + emitted.insert(cmLinkItem(depender)); for (cmLinkImplItem const& lib : impl->Libraries) { // Don't emit the same library twice for this target. - if (emitted.insert(lib.AsStr()).second) { + if (emitted.insert(lib).second) { this->AddTargetDepend(depender_index, lib, true); this->AddInterfaceDepends(depender_index, lib, it, emitted); } @@ -240,12 +244,12 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // Loop over all utility dependencies. { std::set const& tutils = depender->GetUtilityItems(); - std::set emitted; + std::set emitted; // A target should not depend on itself. - emitted.insert(depender->GetName()); + emitted.insert(cmLinkItem(depender)); for (cmLinkItem const& litem : tutils) { // Don't emit the same utility twice for this target. - if (emitted.insert(litem.AsStr()).second) { + if (emitted.insert(litem).second) { this->AddTargetDepend(depender_index, litem, false); } } @@ -254,14 +258,14 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) void cmComputeTargetDepends::AddInterfaceDepends( int depender_index, const cmGeneratorTarget* dependee, - const std::string& config, std::set& emitted) + const std::string& config, std::set& emitted) { cmGeneratorTarget const* depender = this->Targets[depender_index]; if (cmLinkInterface const* iface = dependee->GetLinkInterface(config, depender)) { for (cmLinkItem const& lib : iface->Libraries) { // Don't emit the same library twice for this target. - if (emitted.insert(lib.AsStr()).second) { + if (emitted.insert(lib).second) { this->AddTargetDepend(depender_index, lib, true); this->AddInterfaceDepends(depender_index, lib, config, emitted); } @@ -271,7 +275,7 @@ void cmComputeTargetDepends::AddInterfaceDepends( void cmComputeTargetDepends::AddInterfaceDepends( int depender_index, cmLinkItem const& dependee_name, - const std::string& config, std::set& emitted) + const std::string& config, std::set& emitted) { cmGeneratorTarget const* depender = this->Targets[depender_index]; cmGeneratorTarget const* dependee = dependee_name.Target; @@ -285,7 +289,7 @@ void cmComputeTargetDepends::AddInterfaceDepends( if (dependee) { // A target should not depend on itself. - emitted.insert(depender->GetName()); + emitted.insert(cmLinkItem(depender)); this->AddInterfaceDepends(depender_index, dependee, config, emitted); } } diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index e93e376..3046e8a 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -51,11 +51,11 @@ private: bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name, const std::string& config, - std::set& emitted); + std::set& emitted); void AddInterfaceDepends(int depender_index, cmGeneratorTarget const* dependee, const std::string& config, - std::set& emitted); + std::set& emitted); cmGlobalGenerator* GlobalGenerator; bool DebugMode; bool NoCycles; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 377c008..080ff1c 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -4575,14 +4575,14 @@ void cmGeneratorTarget::ComputeLinkInterface( this->GetType() == cmStateEnums::INTERFACE_LIBRARY) { // Shared libraries may have runtime implementation dependencies // on other shared libraries that are not in the interface. - std::unordered_set emitted; + std::set emitted; for (cmLinkItem const& lib : iface.Libraries) { - emitted.insert(lib.AsStr()); + emitted.insert(lib); } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { cmLinkImplementation const* impl = this->GetLinkImplementation(config); for (cmLinkImplItem const& lib : impl->Libraries) { - if (emitted.insert(lib.AsStr()).second) { + if (emitted.insert(lib).second) { if (lib.Target) { // This is a runtime dependency on another shared library. if (lib.Target->GetType() == cmStateEnums::SHARED_LIBRARY) { diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 971d7ff..a22521b 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -396,6 +396,7 @@ if(BUILD_TESTING) ADD_TEST_MACRO(CompatibleInterface CompatibleInterface) ADD_TEST_MACRO(AliasTarget AliasTarget) ADD_TEST_MACRO(StagingPrefix StagingPrefix) + ADD_TEST_MACRO(ImportedSameName ImportedSameName) ADD_TEST_MACRO(InterfaceLibrary InterfaceLibrary) if (CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]") set(ConfigSources_BUILD_OPTIONS -DCMAKE_BUILD_TYPE=Debug) diff --git a/Tests/ImportedSameName/A/CMakeLists.txt b/Tests/ImportedSameName/A/CMakeLists.txt new file mode 100644 index 0000000..9417a2c --- /dev/null +++ b/Tests/ImportedSameName/A/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(a STATIC a.c) + +add_library(sameName INTERFACE IMPORTED) +target_link_libraries(sameName INTERFACE a) + +add_library(ifaceA INTERFACE) +target_link_libraries(ifaceA INTERFACE sameName) diff --git a/Tests/ImportedSameName/A/a.c b/Tests/ImportedSameName/A/a.c new file mode 100644 index 0000000..4ef3698 --- /dev/null +++ b/Tests/ImportedSameName/A/a.c @@ -0,0 +1,3 @@ +void a(void) +{ +} diff --git a/Tests/ImportedSameName/B/CMakeLists.txt b/Tests/ImportedSameName/B/CMakeLists.txt new file mode 100644 index 0000000..6947fa9 --- /dev/null +++ b/Tests/ImportedSameName/B/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(b STATIC b.c) + +add_library(sameName INTERFACE IMPORTED) +target_link_libraries(sameName INTERFACE b) + +add_library(ifaceB INTERFACE) +target_link_libraries(ifaceB INTERFACE sameName) diff --git a/Tests/ImportedSameName/B/b.c b/Tests/ImportedSameName/B/b.c new file mode 100644 index 0000000..c7c7df4 --- /dev/null +++ b/Tests/ImportedSameName/B/b.c @@ -0,0 +1,3 @@ +void b(void) +{ +} diff --git a/Tests/ImportedSameName/CMakeLists.txt b/Tests/ImportedSameName/CMakeLists.txt new file mode 100644 index 0000000..4292c12 --- /dev/null +++ b/Tests/ImportedSameName/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.12) +project(ImportedSameName C) + +add_subdirectory(A) +add_subdirectory(B) + +add_executable(ImportedSameName main.c) +target_link_libraries(ImportedSameName PRIVATE ifaceA ifaceB) diff --git a/Tests/ImportedSameName/main.c b/Tests/ImportedSameName/main.c new file mode 100644 index 0000000..33196b7 --- /dev/null +++ b/Tests/ImportedSameName/main.c @@ -0,0 +1,9 @@ +extern void a(void); +extern void b(void); + +int main(void) +{ + a(); + b(); + return 0; +} -- cgit v0.12 From 1b57f49586afc9e8663d5e146732b1cd0597e7ef Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 6 Sep 2018 16:49:34 -0400 Subject: genex: Simplify cmGeneratorExpressionInterpreter All callers were constructing with a non-empty target name using the target whose pointer was passed anyway. Drop this argument. Simplify logic accordingly. Re-order constructor arguments to match the cmCompiledGeneratorExpression::Evaluate arguments. Also remove unnecessary getters. --- Source/cmExtraSublimeTextGenerator.cxx | 12 +++---- Source/cmGeneratorExpression.cxx | 15 ++++---- Source/cmGeneratorExpression.h | 55 +++--------------------------- Source/cmGlobalXCodeGenerator.cxx | 12 +++---- Source/cmLocalVisualStudio7Generator.cxx | 3 +- Source/cmMakefileTargetGenerator.cxx | 3 +- Source/cmNinjaTargetGenerator.cxx | 11 +++--- Source/cmServerProtocol.cxx | 9 +++-- Source/cmVisualStudio10TargetGenerator.cxx | 3 +- 9 files changed, 36 insertions(+), 87 deletions(-) diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 14e7927..c4cca07 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -354,8 +354,8 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject( lg->GetTargetCompileFlags(gtgt, config, language, flags); // Add source file specific flags. - cmGeneratorExpressionInterpreter genexInterpreter(lg, gtgt, config, - gtgt->GetName(), language); + cmGeneratorExpressionInterpreter genexInterpreter(lg, config, gtgt, + language); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) { @@ -381,8 +381,8 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines( cmMakefile* makefile = lg->GetMakefile(); const std::string& language = source->GetLanguage(); const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - cmGeneratorExpressionInterpreter genexInterpreter( - lg, target, config, target->GetName(), language); + cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target, + language); // Add the export symbol definition for shared library objects. if (const char* exportMacro = target->GetExportMacro()) { @@ -419,8 +419,8 @@ std::string cmExtraSublimeTextGenerator::ComputeIncludes( cmMakefile* makefile = lg->GetMakefile(); const std::string& language = source->GetLanguage(); const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - cmGeneratorExpressionInterpreter genexInterpreter( - lg, target, config, target->GetName(), language); + cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target, + language); // Add include directories for this source file const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 6823cd5..6d83a3f 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -13,6 +13,7 @@ #include "cmGeneratorExpressionEvaluator.h" #include "cmGeneratorExpressionLexer.h" #include "cmGeneratorExpressionParser.h" +#include "cmGeneratorTarget.h" #include "cmSystemTools.h" cmGeneratorExpression::cmGeneratorExpression( @@ -389,14 +390,16 @@ void cmCompiledGeneratorExpression::GetMaxLanguageStandard( const std::string& cmGeneratorExpressionInterpreter::Evaluate( const char* expression, const std::string& property) { - if (this->Target.empty()) { - return this->EvaluateExpression(expression); - } + this->CompiledGeneratorExpression = + this->GeneratorExpression.Parse(expression); // Specify COMPILE_OPTIONS to DAGchecker, same semantic as COMPILE_FLAGS cmGeneratorExpressionDAGChecker dagChecker( - this->Target, property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property, - nullptr, nullptr); + this->HeadTarget->GetName(), + property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property, nullptr, + nullptr); - return this->EvaluateExpression(expression, &dagChecker); + return this->CompiledGeneratorExpression->Evaluate( + this->LocalGenerator, this->Config, false, this->HeadTarget, &dagChecker, + this->Language); } diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 2b7df91..8176d5c 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -160,24 +160,15 @@ class cmGeneratorExpressionInterpreter public: cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator, - cmGeneratorTarget* generatorTarget, - const std::string& config, - const std::string& target, - const std::string& lang) + std::string const& config, + cmGeneratorTarget const* headTarget, + std::string const& lang = std::string()) : LocalGenerator(localGenerator) - , GeneratorTarget(generatorTarget) , Config(config) - , Target(target) + , HeadTarget(headTarget) , Language(lang) { } - cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator, - cmGeneratorTarget* generatorTarget, - const std::string& config) - : cmGeneratorExpressionInterpreter(localGenerator, generatorTarget, config, - std::string(), std::string()) - { - } const std::string& Evaluate(const char* expression, const std::string& property); @@ -188,47 +179,11 @@ public: } protected: - cmGeneratorExpression& GetGeneratorExpression() - { - return this->GeneratorExpression; - } - - cmCompiledGeneratorExpression& GetCompiledGeneratorExpression() - { - return *(this->CompiledGeneratorExpression); - } - - cmLocalGenerator* GetLocalGenerator() { return this->LocalGenerator; } - - cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; } - - const std::string& GetTargetName() const { return this->Target; } - const std::string& GetLanguage() const { return this->Language; } - - const std::string& EvaluateExpression( - const char* expression, - cmGeneratorExpressionDAGChecker* dagChecker = nullptr) - { - this->CompiledGeneratorExpression = - this->GeneratorExpression.Parse(expression); - - if (dagChecker == nullptr) { - return this->CompiledGeneratorExpression->Evaluate( - this->LocalGenerator, this->Config, false, this->GeneratorTarget); - } - - return this->CompiledGeneratorExpression->Evaluate( - this->LocalGenerator, this->Config, false, this->GeneratorTarget, - dagChecker, this->Language); - } - -private: cmGeneratorExpression GeneratorExpression; std::unique_ptr CompiledGeneratorExpression; cmLocalGenerator* LocalGenerator = nullptr; - cmGeneratorTarget* GeneratorTarget = nullptr; std::string Config; - std::string Target; + cmGeneratorTarget const* HeadTarget = nullptr; std::string Language; }; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 7456d3c..e353a37 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -751,11 +751,10 @@ class XCodeGeneratorExpressionInterpreter public: XCodeGeneratorExpressionInterpreter(cmSourceFile* sourceFile, cmLocalGenerator* localGenerator, - cmGeneratorTarget* generatorTarget, + cmGeneratorTarget* headTarget, const std::string& lang) - : cmGeneratorExpressionInterpreter(localGenerator, generatorTarget, - "NO-PER-CONFIG-SUPPORT-IN-XCODE", - generatorTarget->GetName(), lang) + : cmGeneratorExpressionInterpreter( + localGenerator, "NO-PER-CONFIG-SUPPORT-IN-XCODE", headTarget, lang) , SourceFile(sourceFile) { } @@ -767,8 +766,7 @@ public: { const std::string& processed = this->cmGeneratorExpressionInterpreter::Evaluate(expression, property); - if (this->GetCompiledGeneratorExpression() - .GetHadContextSensitiveCondition()) { + if (this->CompiledGeneratorExpression->GetHadContextSensitiveCondition()) { std::ostringstream e; /* clang-format off */ e << @@ -777,7 +775,7 @@ public: "specified for source:\n" " " << this->SourceFile->GetFullPath() << "\n"; /* clang-format on */ - this->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); } return processed; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 13bd214..c05b085 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1497,8 +1497,7 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( lang = sourceLang; } - cmGeneratorExpressionInterpreter genexInterpreter(lg, gt, *i, - gt->GetName(), lang); + cmGeneratorExpressionInterpreter genexInterpreter(lg, *i, gt, lang); bool needfc = false; if (!objectName.empty()) { diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index e8cf255..c8dc392 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -434,8 +434,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( std::string config = this->LocalGenerator->GetConfigName(); std::string configUpper = cmSystemTools::UpperCase(config); cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, this->GeneratorTarget, config, - this->GeneratorTarget->GetName(), lang); + this->LocalGenerator, config, this->GeneratorTarget, lang); // Add Fortran format flags. if (lang == "Fortran") { diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 1cfaac5..ebcc501 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -136,9 +136,8 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( // Add source file specific flags. cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, this->GeneratorTarget, - this->LocalGenerator->GetConfigName(), this->GeneratorTarget->GetName(), - language); + this->LocalGenerator, this->LocalGenerator->GetConfigName(), + this->GeneratorTarget, language); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) { @@ -188,8 +187,7 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, std::set defines; const std::string config = this->LocalGenerator->GetConfigName(); cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, this->GeneratorTarget, config, - this->GeneratorTarget->GetName(), language); + this->LocalGenerator, config, this->GeneratorTarget, language); const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) { @@ -217,8 +215,7 @@ std::string cmNinjaTargetGenerator::ComputeIncludes( std::vector includes; const std::string config = this->LocalGenerator->GetConfigName(); cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, this->GeneratorTarget, config, - this->GeneratorTarget->GetName(), language); + this->LocalGenerator, config, this->GeneratorTarget, language); const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); if (const char* cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) { diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index af4b466..231cacb 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -722,8 +722,8 @@ static void PopulateFileGroupData( ? languageDataMap.at(kInterfaceSourcesLanguageDataKey) : languageDataMap.at(fileData.Language); cmLocalGenerator* lg = target->GetLocalGenerator(); - cmGeneratorExpressionInterpreter genexInterpreter( - lg, target, config, target->GetName(), fileData.Language); + cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target, + fileData.Language); std::string compileFlags = ld.Flags; const std::string COMPILE_FLAGS("COMPILE_FLAGS"); @@ -817,7 +817,7 @@ static Json::Value DumpSourceFilesList( auto targetProp = target->Target->GetProperty("INTERFACE_SOURCES"); if (targetProp != nullptr) { cmGeneratorExpressionInterpreter genexInterpreter( - target->GetLocalGenerator(), target, config, target->GetName(), ""); + target->GetLocalGenerator(), config, target); auto evaluatedSources = cmsys::SystemTools::SplitString( genexInterpreter.Evaluate(targetProp, "INTERFACE_SOURCES"), ';'); @@ -977,8 +977,7 @@ static void CreateInterfaceSourcesEntry( LanguageData& ld = languageDataMap[kInterfaceSourcesLanguageDataKey]; ld.Language = ""; - cmGeneratorExpressionInterpreter genexInterpreter(lg, target, config, - target->GetName(), ""); + cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target); std::vector propertyValue; GetTargetProperty(genexInterpreter, target, "INTERFACE_INCLUDE_DIRECTORIES", propertyValue); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 9e74335..53a2a59 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2117,8 +2117,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( flagtable = gg->GetCSharpFlagTable(); } cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, this->GeneratorTarget, config, - this->GeneratorTarget->GetName(), lang); + this->LocalGenerator, config, this->GeneratorTarget, lang); cmVS10GeneratorOptions clOptions( this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler, flagtable, this); -- cgit v0.12 From f35be599612b788125d08a7c3e61d0fad3805bdd Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 6 Sep 2018 18:22:31 -0400 Subject: Fix transitive usage requirements through same-name imported targets If two imported targets in different directories have the same name we should still be able to propagate transitive usage requirements from both. Fix the DAG checker to work with target pointers instead of target names since the pointers will not be duplicated even if the names are. Fixes: #18345 --- Source/cmExportBuildAndroidMKGenerator.cxx | 2 +- Source/cmExportTryCompileFileGenerator.cxx | 3 +- Source/cmGeneratorExpression.cxx | 3 +- Source/cmGeneratorExpressionDAGChecker.cxx | 13 +++++---- Source/cmGeneratorExpressionDAGChecker.h | 13 +++++---- Source/cmGeneratorExpressionNode.cxx | 13 ++++----- Source/cmGeneratorTarget.cxx | 45 +++++++++++++++--------------- Tests/ImportedSameName/A/CMakeLists.txt | 1 + Tests/ImportedSameName/B/CMakeLists.txt | 1 + Tests/ImportedSameName/main.c | 7 +++++ 10 files changed, 54 insertions(+), 47 deletions(-) diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index bb370c4..3d32b84 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -108,7 +108,7 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( // build type of the makefile cmGeneratorExpression ge; cmGeneratorExpressionDAGChecker dagChecker( - target->GetName(), "INTERFACE_LINK_LIBRARIES", nullptr, nullptr); + target, "INTERFACE_LINK_LIBRARIES", nullptr, nullptr); std::unique_ptr cge = ge.Parse(property.second); std::string evaluated = cge->Evaluate( diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index 87648cb..c169032 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -65,8 +65,7 @@ std::string cmExportTryCompileFileGenerator::FindTargets( cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker(tgt->GetName(), propName, nullptr, - nullptr); + cmGeneratorExpressionDAGChecker dagChecker(tgt, propName, nullptr, nullptr); std::unique_ptr cge = ge.Parse(prop); diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 6d83a3f..658e9a7 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -13,7 +13,6 @@ #include "cmGeneratorExpressionEvaluator.h" #include "cmGeneratorExpressionLexer.h" #include "cmGeneratorExpressionParser.h" -#include "cmGeneratorTarget.h" #include "cmSystemTools.h" cmGeneratorExpression::cmGeneratorExpression( @@ -395,7 +394,7 @@ const std::string& cmGeneratorExpressionInterpreter::Evaluate( // Specify COMPILE_OPTIONS to DAGchecker, same semantic as COMPILE_FLAGS cmGeneratorExpressionDAGChecker dagChecker( - this->HeadTarget->GetName(), + this->HeadTarget, property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property, nullptr, nullptr); diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index face282..8d57441 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -14,7 +14,7 @@ #include cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( - const cmListFileBacktrace& backtrace, const std::string& target, + const cmListFileBacktrace& backtrace, cmGeneratorTarget const* target, const std::string& property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent) : Parent(parent) @@ -28,7 +28,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( } cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( - const std::string& target, const std::string& property, + cmGeneratorTarget const* target, const std::string& property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent) : Parent(parent) @@ -58,8 +58,8 @@ void cmGeneratorExpressionDAGChecker::Initialize() TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(clang-tidy) #undef TEST_TRANSITIVE_PROPERTY_METHOD { - std::map>::const_iterator it = - top->Seen.find(this->Target); + std::map>::const_iterator + it = top->Seen.find(this->Target); if (it != top->Seen.end()) { const std::set& propSet = it->second; if (propSet.find(this->Property) != propSet.end()) { @@ -166,7 +166,8 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression() return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL"; } -bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt) +bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries( + cmGeneratorTarget const* tgt) { const cmGeneratorExpressionDAGChecker* top = this; const cmGeneratorExpressionDAGChecker* parent = this->Parent; @@ -189,7 +190,7 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt) strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0; } -std::string cmGeneratorExpressionDAGChecker::TopTarget() const +cmGeneratorTarget const* cmGeneratorExpressionDAGChecker::TopTarget() const { const cmGeneratorExpressionDAGChecker* top = this; const cmGeneratorExpressionDAGChecker* parent = this->Parent; diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index cd23904..8b1697b 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -13,6 +13,7 @@ struct GeneratorExpressionContent; struct cmGeneratorExpressionContext; +class cmGeneratorTarget; #define CM_SELECT_BOTH(F, A1, A2) F(A1, A2) #define CM_SELECT_FIRST(F, A1, A2) F(A1) @@ -41,11 +42,11 @@ struct cmGeneratorExpressionContext; struct cmGeneratorExpressionDAGChecker { cmGeneratorExpressionDAGChecker(const cmListFileBacktrace& backtrace, - const std::string& target, + cmGeneratorTarget const* target, const std::string& property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent); - cmGeneratorExpressionDAGChecker(const std::string& target, + cmGeneratorExpressionDAGChecker(cmGeneratorTarget const* target, const std::string& property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent); @@ -64,7 +65,7 @@ struct cmGeneratorExpressionDAGChecker const std::string& expr); bool EvaluatingGenexExpression(); - bool EvaluatingLinkLibraries(const char* tgt = nullptr); + bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr); #define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const; @@ -75,7 +76,7 @@ struct cmGeneratorExpressionDAGChecker bool GetTransitivePropertiesOnly(); void SetTransitivePropertiesOnly() { this->TransitivePropertiesOnly = true; } - std::string TopTarget() const; + cmGeneratorTarget const* TopTarget() const; private: Result CheckGraph() const; @@ -83,9 +84,9 @@ private: private: const cmGeneratorExpressionDAGChecker* const Parent; - const std::string Target; + cmGeneratorTarget const* Target; const std::string Property; - std::map> Seen; + std::map> Seen; const GeneratorExpressionContent* const Content; const cmListFileBacktrace Backtrace; Result CheckResult; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 9aa5212..1e51f09 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -378,8 +378,8 @@ protected: { if (context->HeadTarget) { cmGeneratorExpressionDAGChecker dagChecker( - context->Backtrace, context->HeadTarget->GetName(), genexOperator, - content, dagCheckerParent); + context->Backtrace, context->HeadTarget, genexOperator, content, + dagCheckerParent); switch (dagChecker.Check()) { case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: { @@ -1196,9 +1196,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode return target->GetLinkerLanguage(context->Config); } - cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, - target->GetName(), propertyName, - content, dagCheckerParent); + cmGeneratorExpressionDAGChecker dagChecker( + context->Backtrace, target, propertyName, content, dagCheckerParent); switch (dagChecker.Check()) { case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: @@ -1911,9 +1910,9 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode return std::string(); } if (dagChecker && - (dagChecker->EvaluatingLinkLibraries(name.c_str()) || + (dagChecker->EvaluatingLinkLibraries(target) || (dagChecker->EvaluatingSources() && - name == dagChecker->TopTarget()))) { + target == dagChecker->TopTarget()))) { ::reportError(context, content->GetOriginalExpression(), "Expressions which require the linker language may not " "be used while evaluating link libraries"); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 080ff1c..e8e7b90 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -773,7 +773,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory( if (iter == this->SystemIncludesCache.end()) { cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr); + this, "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr); bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED"); @@ -964,8 +964,8 @@ void cmGeneratorTarget::GetSourceFiles(std::vector& files, this->DebugSourcesDone = true; } - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "SOURCES", - nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr, + nullptr); std::unordered_set uniqueSrcs; bool contextDependentDirectSources = @@ -2078,8 +2078,8 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector& result, } cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "AUTOUIC_OPTIONS", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr, + nullptr); cmSystemTools::ExpandListArgument( ge.Parse(prop)->Evaluate(this->LocalGenerator, config, false, this, &dagChecker), @@ -2588,8 +2588,8 @@ std::vector cmGeneratorTarget::GetIncludeDirectories( std::vector includes; std::unordered_set uniqueIncludes; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "INCLUDE_DIRECTORIES", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES", + nullptr, nullptr); std::vector debugProperties; const char* debugProp = @@ -2710,8 +2710,8 @@ void cmGeneratorTarget::GetCompileOptions(std::vector& result, { std::unordered_set uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "COMPILE_OPTIONS", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr, + nullptr); std::vector debugProperties; const char* debugProp = @@ -2763,8 +2763,8 @@ void cmGeneratorTarget::GetCompileFeatures(std::vector& result, { std::unordered_set uniqueFeatures; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "COMPILE_FEATURES", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr, + nullptr); std::vector debugProperties; const char* debugProp = @@ -2814,8 +2814,8 @@ void cmGeneratorTarget::GetCompileDefinitions( { std::unordered_set uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "COMPILE_DEFINITIONS", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS", + nullptr, nullptr); std::vector debugProperties; const char* debugProp = @@ -2895,8 +2895,8 @@ void cmGeneratorTarget::GetLinkOptions(std::vector& result, { std::unordered_set uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "LINK_OPTIONS", - nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr, + nullptr); std::vector debugProperties; const char* debugProp = @@ -3043,8 +3043,8 @@ void cmGeneratorTarget::GetStaticLibraryLinkOptions( std::vector entries; std::unordered_set uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "STATIC_LIBRARY_OPTIONS", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS", + nullptr, nullptr); if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) { std::vector options; @@ -3083,8 +3083,8 @@ void cmGeneratorTarget::GetLinkDepends(std::vector& result, { std::vector linkDependsEntries; std::unordered_set uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "LINK_DEPENDS", - nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr, + nullptr); if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) { std::vector depends; @@ -4509,8 +4509,7 @@ void cmGeneratorTarget::ExpandLinkItems( std::vector& items, bool& hadHeadSensitiveCondition) const { cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, nullptr, - nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr); // The $ expression may be in a link interface to specify private // link dependencies that are otherwise excluded from usage requirements. if (usage_requirements_only) { @@ -5561,8 +5560,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( end = entryRange.end(); le != end; ++le, ++btIt) { std::vector llibs; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "LINK_LIBRARIES", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr, + nullptr); cmGeneratorExpression ge(*btIt); std::unique_ptr const cge = ge.Parse(*le); std::string const& evaluated = diff --git a/Tests/ImportedSameName/A/CMakeLists.txt b/Tests/ImportedSameName/A/CMakeLists.txt index 9417a2c..0a31b40 100644 --- a/Tests/ImportedSameName/A/CMakeLists.txt +++ b/Tests/ImportedSameName/A/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(a STATIC a.c) +target_compile_definitions(a INTERFACE DEF_A) add_library(sameName INTERFACE IMPORTED) target_link_libraries(sameName INTERFACE a) diff --git a/Tests/ImportedSameName/B/CMakeLists.txt b/Tests/ImportedSameName/B/CMakeLists.txt index 6947fa9..d930326 100644 --- a/Tests/ImportedSameName/B/CMakeLists.txt +++ b/Tests/ImportedSameName/B/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(b STATIC b.c) +target_compile_definitions(b INTERFACE DEF_B) add_library(sameName INTERFACE IMPORTED) target_link_libraries(sameName INTERFACE b) diff --git a/Tests/ImportedSameName/main.c b/Tests/ImportedSameName/main.c index 33196b7..a0cb27f 100644 --- a/Tests/ImportedSameName/main.c +++ b/Tests/ImportedSameName/main.c @@ -1,3 +1,10 @@ +#ifndef DEF_A +# error "DEF_A not defined" +#endif +#ifndef DEF_B +# error "DEF_B not defined" +#endif + extern void a(void); extern void b(void); -- cgit v0.12