resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmLinkItemGraphVisitor.cxx
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 {
27   if (item.Target == nullptr) {
28     return;
29   }
30
31   for (auto const& config : item.Target->Makefile->GetGeneratorConfigs(
32          cmMakefile::IncludeEmptyConfig)) {
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 {
101   const auto* implementationLibraries = target.GetLinkImplementationLibraries(
102     config, cmGeneratorTarget::LinkInterfaceFor::Link);
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
110   const auto* interfaceLibraries = target.GetLinkInterfaceLibraries(
111     config, &target, cmGeneratorTarget::LinkInterfaceFor::Usage);
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()) {
128       auto objectItem = cmLinkItem(lib, false, lib->GetBacktrace());
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 }