| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| #include "cmLinkItemGraphVisitor.h" |
| |
| #include <map> |
| #include <utility> |
| #include <vector> |
| |
| #include "cmGeneratorTarget.h" |
| #include "cmLinkItem.h" |
| #include "cmMakefile.h" |
| |
| void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item) |
| { |
| if (this->ItemVisited(item)) { |
| return; |
| } |
| |
| this->OnItem(item); |
| |
| this->VisitLinks(item, item); |
| } |
| |
| void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item, |
| cmLinkItem const& rootItem) |
| { |
| if (!item.Target) { |
| return; |
| } |
| |
| for (auto const& config : item.Target->Makefile->GetGeneratorConfigs( |
| cmMakefile::IncludeEmptyConfig)) { |
| this->VisitLinks(item, rootItem, config); |
| } |
| } |
| |
| void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item, |
| cmLinkItem const& rootItem, |
| std::string const& config) |
| { |
| auto const& target = *item.Target; |
| |
| DependencyMap dependencies; |
| cmLinkItemGraphVisitor::GetDependencies(target, config, dependencies); |
| |
| for (auto const& d : dependencies) { |
| auto const& dependency = d.second; |
| auto const& dependencyType = dependency.first; |
| auto const& dependee = dependency.second; |
| this->VisitItem(dependee); |
| |
| if (this->LinkVisited(item, dependee)) { |
| continue; |
| } |
| |
| this->OnDirectLink(item, dependee, dependencyType); |
| |
| if (rootItem.AsStr() != item.AsStr()) { |
| this->OnIndirectLink(rootItem, dependee); |
| } |
| |
| // Visit all the direct and indirect links. |
| this->VisitLinks(dependee, dependee); |
| this->VisitLinks(dependee, item); |
| this->VisitLinks(dependee, rootItem); |
| } |
| } |
| |
| bool cmLinkItemGraphVisitor::ItemVisited(cmLinkItem const& item) |
| { |
| auto& collection = this->VisitedItems; |
| |
| bool const visited = collection.find(item.AsStr()) != collection.cend(); |
| |
| if (!visited) { |
| collection.insert(item.AsStr()); |
| } |
| |
| return visited; |
| } |
| |
| bool cmLinkItemGraphVisitor::LinkVisited(cmLinkItem const& depender, |
| cmLinkItem const& dependee) |
| { |
| auto const link = std::make_pair(depender.AsStr(), dependee.AsStr()); |
| |
| bool const linkVisited = |
| this->VisitedLinks.find(link) != this->VisitedLinks.cend(); |
| |
| if (!linkVisited) { |
| this->VisitedLinks.insert(link); |
| } |
| |
| return linkVisited; |
| } |
| |
| void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target, |
| std::string const& config, |
| DependencyMap& dependencies) |
| { |
| const auto* implementationLibraries = target.GetLinkImplementationLibraries( |
| config, cmGeneratorTarget::UseTo::Link); |
| if (implementationLibraries) { |
| for (auto const& lib : implementationLibraries->Libraries) { |
| auto const& name = lib.AsStr(); |
| dependencies[name] = Dependency(DependencyType::LinkPrivate, lib); |
| } |
| } |
| |
| const auto* interfaceLibraries = target.GetLinkInterfaceLibraries( |
| config, &target, cmGeneratorTarget::UseTo::Compile); |
| if (interfaceLibraries) { |
| for (auto const& lib : interfaceLibraries->Libraries) { |
| auto const& name = lib.AsStr(); |
| if (dependencies.find(name) != dependencies.cend()) { |
| dependencies[name] = Dependency(DependencyType::LinkPublic, lib); |
| } else { |
| dependencies[name] = Dependency(DependencyType::LinkInterface, lib); |
| } |
| } |
| } |
| |
| std::vector<cmGeneratorTarget*> objectLibraries; |
| target.GetObjectLibrariesCMP0026(objectLibraries); |
| for (auto const& lib : objectLibraries) { |
| auto const& name = lib->GetName(); |
| if (dependencies.find(name) == dependencies.cend()) { |
| auto objectItem = cmLinkItem(lib, false, lib->GetBacktrace()); |
| dependencies[name] = Dependency(DependencyType::Object, objectItem); |
| } |
| } |
| |
| auto const& utilityItems = target.GetUtilityItems(); |
| for (auto const& item : utilityItems) { |
| auto const& name = item.AsStr(); |
| if (dependencies.find(name) == dependencies.cend()) { |
| dependencies[name] = Dependency(DependencyType::Utility, item); |
| } |
| } |
| } |