Corentin Plouet | 5536583 | 2019-10-08 13:45:30 +1100 | [diff] [blame] | 1 | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| 2 | file Copyright.txt or https://cmake.org/licensing for details. */ |
| 3 | #include "cmLinkItemGraphVisitor.h" |
| 4 | |
| 5 | #include <map> |
| 6 | #include <utility> |
| 7 | #include <vector> |
| 8 | |
| 9 | #include "cmGeneratorTarget.h" |
| 10 | #include "cmLinkItem.h" |
| 11 | #include "cmMakefile.h" |
| 12 | |
| 13 | void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item) |
| 14 | { |
| 15 | if (this->ItemVisited(item)) { |
| 16 | return; |
| 17 | } |
| 18 | |
| 19 | this->OnItem(item); |
| 20 | |
| 21 | this->VisitLinks(item, item); |
| 22 | } |
| 23 | |
| 24 | void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item, |
| 25 | cmLinkItem const& rootItem) |
| 26 | { |
Corentin Plouet | 5536583 | 2019-10-08 13:45:30 +1100 | [diff] [blame] | 27 | if (item.Target == nullptr) { |
| 28 | return; |
| 29 | } |
| 30 | |
Robert Maynard | 7a969fe | 2020-06-30 13:44:37 -0400 | [diff] [blame] | 31 | for (auto const& config : item.Target->Makefile->GetGeneratorConfigs( |
| 32 | cmMakefile::IncludeEmptyConfig)) { |
Corentin Plouet | 5536583 | 2019-10-08 13:45:30 +1100 | [diff] [blame] | 33 | this->VisitLinks(item, rootItem, config); |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item, |
| 38 | cmLinkItem const& rootItem, |
| 39 | std::string const& config) |
| 40 | { |
| 41 | auto const& target = *item.Target; |
| 42 | |
| 43 | DependencyMap dependencies; |
| 44 | cmLinkItemGraphVisitor::GetDependencies(target, config, dependencies); |
| 45 | |
| 46 | for (auto const& d : dependencies) { |
| 47 | auto const& dependency = d.second; |
| 48 | auto const& dependencyType = dependency.first; |
| 49 | auto const& dependee = dependency.second; |
| 50 | this->VisitItem(dependee); |
| 51 | |
| 52 | if (this->LinkVisited(item, dependee)) { |
| 53 | continue; |
| 54 | } |
| 55 | |
| 56 | this->OnDirectLink(item, dependee, dependencyType); |
| 57 | |
| 58 | if (rootItem.AsStr() != item.AsStr()) { |
| 59 | this->OnIndirectLink(rootItem, dependee); |
| 60 | } |
| 61 | |
| 62 | // Visit all the direct and indirect links. |
| 63 | this->VisitLinks(dependee, dependee); |
| 64 | this->VisitLinks(dependee, item); |
| 65 | this->VisitLinks(dependee, rootItem); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | bool cmLinkItemGraphVisitor::ItemVisited(cmLinkItem const& item) |
| 70 | { |
| 71 | auto& collection = this->VisitedItems; |
| 72 | |
| 73 | bool const visited = collection.find(item.AsStr()) != collection.cend(); |
| 74 | |
| 75 | if (!visited) { |
| 76 | collection.insert(item.AsStr()); |
| 77 | } |
| 78 | |
| 79 | return visited; |
| 80 | } |
| 81 | |
| 82 | bool cmLinkItemGraphVisitor::LinkVisited(cmLinkItem const& depender, |
| 83 | cmLinkItem const& dependee) |
| 84 | { |
| 85 | auto const link = std::make_pair<>(depender.AsStr(), dependee.AsStr()); |
| 86 | |
| 87 | bool const linkVisited = |
| 88 | this->VisitedLinks.find(link) != this->VisitedLinks.cend(); |
| 89 | |
| 90 | if (!linkVisited) { |
| 91 | this->VisitedLinks.insert(link); |
| 92 | } |
| 93 | |
| 94 | return linkVisited; |
| 95 | } |
| 96 | |
| 97 | void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target, |
| 98 | std::string const& config, |
| 99 | DependencyMap& dependencies) |
| 100 | { |
Brad King | 73337cb | 2022-03-22 09:31:36 -0400 | [diff] [blame] | 101 | const auto* implementationLibraries = target.GetLinkImplementationLibraries( |
| 102 | config, cmGeneratorTarget::LinkInterfaceFor::Link); |
Corentin Plouet | 5536583 | 2019-10-08 13:45:30 +1100 | [diff] [blame] | 103 | if (implementationLibraries != nullptr) { |
| 104 | for (auto const& lib : implementationLibraries->Libraries) { |
| 105 | auto const& name = lib.AsStr(); |
| 106 | dependencies[name] = Dependency(DependencyType::LinkPrivate, lib); |
| 107 | } |
| 108 | } |
| 109 | |
Brad King | 1e49880 | 2021-12-08 16:39:31 -0500 | [diff] [blame] | 110 | const auto* interfaceLibraries = target.GetLinkInterfaceLibraries( |
| 111 | config, &target, cmGeneratorTarget::LinkInterfaceFor::Usage); |
Corentin Plouet | 5536583 | 2019-10-08 13:45:30 +1100 | [diff] [blame] | 112 | if (interfaceLibraries != nullptr) { |
| 113 | for (auto const& lib : interfaceLibraries->Libraries) { |
| 114 | auto const& name = lib.AsStr(); |
| 115 | if (dependencies.find(name) != dependencies.cend()) { |
| 116 | dependencies[name] = Dependency(DependencyType::LinkPublic, lib); |
| 117 | } else { |
| 118 | dependencies[name] = Dependency(DependencyType::LinkInterface, lib); |
| 119 | } |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | std::vector<cmGeneratorTarget*> objectLibraries; |
| 124 | target.GetObjectLibrariesCMP0026(objectLibraries); |
| 125 | for (auto const& lib : objectLibraries) { |
| 126 | auto const& name = lib->GetName(); |
| 127 | if (dependencies.find(name) == dependencies.cend()) { |
Kyle Edwards | 7abc3d6 | 2020-02-13 11:12:34 -0500 | [diff] [blame] | 128 | auto objectItem = cmLinkItem(lib, false, lib->GetBacktrace()); |
Corentin Plouet | 5536583 | 2019-10-08 13:45:30 +1100 | [diff] [blame] | 129 | dependencies[name] = Dependency(DependencyType::Object, objectItem); |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | auto const& utilityItems = target.GetUtilityItems(); |
| 134 | for (auto const& item : utilityItems) { |
| 135 | auto const& name = item.AsStr(); |
| 136 | if (dependencies.find(name) == dependencies.cend()) { |
| 137 | dependencies[name] = Dependency(DependencyType::Utility, item); |
| 138 | } |
| 139 | } |
| 140 | } |