blob: 0ad846b7ea8bff29fcef93e3c880bbcfc3192c47 [file] [log] [blame]
Corentin Plouet55365832019-10-08 13:45:30 +11001/* 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
13void 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
24void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item,
25 cmLinkItem const& rootItem)
26{
Corentin Plouet55365832019-10-08 13:45:30 +110027 if (item.Target == nullptr) {
28 return;
29 }
30
Robert Maynard7a969fe2020-06-30 13:44:37 -040031 for (auto const& config : item.Target->Makefile->GetGeneratorConfigs(
32 cmMakefile::IncludeEmptyConfig)) {
Corentin Plouet55365832019-10-08 13:45:30 +110033 this->VisitLinks(item, rootItem, config);
34 }
35}
36
37void 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
69bool 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
82bool 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
97void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target,
98 std::string const& config,
99 DependencyMap& dependencies)
100{
Brad King73337cb2022-03-22 09:31:36 -0400101 const auto* implementationLibraries = target.GetLinkImplementationLibraries(
102 config, cmGeneratorTarget::LinkInterfaceFor::Link);
Corentin Plouet55365832019-10-08 13:45:30 +1100103 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 King1e498802021-12-08 16:39:31 -0500110 const auto* interfaceLibraries = target.GetLinkInterfaceLibraries(
111 config, &target, cmGeneratorTarget::LinkInterfaceFor::Usage);
Corentin Plouet55365832019-10-08 13:45:30 +1100112 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 Edwards7abc3d62020-02-13 11:12:34 -0500128 auto objectItem = cmLinkItem(lib, false, lib->GetBacktrace());
Corentin Plouet55365832019-10-08 13:45:30 +1100129 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}