| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst or https://cmake.org/licensing for details. */ | |
| #include "cmLinkItemGraphVisitor.h" | |
| #include <map> | |
| #include <utility> | |
| #include <vector> | |
| #include "cmGeneratorTarget.h" | |
| #include "cmLinkItem.h" | |
| #include "cmListFileCache.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) | |
| { | |
| auto const* 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); | |
| } | |
| } | |
| auto const* 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<BT<cmGeneratorTarget*>> objectLibraries; | |
| target.GetObjectLibrariesInSources(objectLibraries); | |
| for (auto const& lib : objectLibraries) { | |
| auto const& name = lib.Value->GetName(); | |
| if (dependencies.find(name) == dependencies.cend()) { | |
| auto objectItem = cmLinkItem(lib.Value, false, lib.Backtrace); | |
| dependencies[name] = Dependency(DependencyType::Object, objectItem); | |
| } | |
| } | |
| auto const& utilityItems = target.GetUtilityItems(); | |
| for (auto const& item : utilityItems) { | |
| auto const& name = item.AsStr(); | |
| dependencies.emplace(name, Dependency(DependencyType::Utility, item)); | |
| } | |
| } |