Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmLinkItemGraphVisitor.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst 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 "cmListFileCache.h"
12
#include "cmMakefile.h"
13
14
void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item)
15
0
{
16
0
  if (this->ItemVisited(item)) {
17
0
    return;
18
0
  }
19
20
0
  this->OnItem(item);
21
22
0
  this->VisitLinks(item, item);
23
0
}
24
25
void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item,
26
                                        cmLinkItem const& rootItem)
27
0
{
28
0
  if (!item.Target) {
29
0
    return;
30
0
  }
31
32
0
  for (auto const& config : item.Target->Makefile->GetGeneratorConfigs(
33
0
         cmMakefile::IncludeEmptyConfig)) {
34
0
    this->VisitLinks(item, rootItem, config);
35
0
  }
36
0
}
37
38
void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item,
39
                                        cmLinkItem const& rootItem,
40
                                        std::string const& config)
41
0
{
42
0
  auto const& target = *item.Target;
43
44
0
  DependencyMap dependencies;
45
0
  cmLinkItemGraphVisitor::GetDependencies(target, config, dependencies);
46
47
0
  for (auto const& d : dependencies) {
48
0
    auto const& dependency = d.second;
49
0
    auto const& dependencyType = dependency.first;
50
0
    auto const& dependee = dependency.second;
51
0
    this->VisitItem(dependee);
52
53
0
    if (this->LinkVisited(item, dependee)) {
54
0
      continue;
55
0
    }
56
57
0
    this->OnDirectLink(item, dependee, dependencyType);
58
59
0
    if (rootItem.AsStr() != item.AsStr()) {
60
0
      this->OnIndirectLink(rootItem, dependee);
61
0
    }
62
63
    // Visit all the direct and indirect links.
64
0
    this->VisitLinks(dependee, dependee);
65
0
    this->VisitLinks(dependee, item);
66
0
    this->VisitLinks(dependee, rootItem);
67
0
  }
68
0
}
69
70
bool cmLinkItemGraphVisitor::ItemVisited(cmLinkItem const& item)
71
0
{
72
0
  auto& collection = this->VisitedItems;
73
74
0
  bool const visited = collection.find(item.AsStr()) != collection.cend();
75
76
0
  if (!visited) {
77
0
    collection.insert(item.AsStr());
78
0
  }
79
80
0
  return visited;
81
0
}
82
83
bool cmLinkItemGraphVisitor::LinkVisited(cmLinkItem const& depender,
84
                                         cmLinkItem const& dependee)
85
0
{
86
0
  auto const link = std::make_pair(depender.AsStr(), dependee.AsStr());
87
88
0
  bool const linkVisited =
89
0
    this->VisitedLinks.find(link) != this->VisitedLinks.cend();
90
91
0
  if (!linkVisited) {
92
0
    this->VisitedLinks.insert(link);
93
0
  }
94
95
0
  return linkVisited;
96
0
}
97
98
void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target,
99
                                             std::string const& config,
100
                                             DependencyMap& dependencies)
101
0
{
102
0
  auto const* implementationLibraries = target.GetLinkImplementationLibraries(
103
0
    config, cmGeneratorTarget::UseTo::Link);
104
0
  if (implementationLibraries) {
105
0
    for (auto const& lib : implementationLibraries->Libraries) {
106
0
      auto const& name = lib.AsStr();
107
0
      dependencies[name] = Dependency(DependencyType::LinkPrivate, lib);
108
0
    }
109
0
  }
110
111
0
  auto const* interfaceLibraries = target.GetLinkInterfaceLibraries(
112
0
    config, &target, cmGeneratorTarget::UseTo::Compile);
113
0
  if (interfaceLibraries) {
114
0
    for (auto const& lib : interfaceLibraries->Libraries) {
115
0
      auto const& name = lib.AsStr();
116
0
      if (dependencies.find(name) != dependencies.cend()) {
117
0
        dependencies[name] = Dependency(DependencyType::LinkPublic, lib);
118
0
      } else {
119
0
        dependencies[name] = Dependency(DependencyType::LinkInterface, lib);
120
0
      }
121
0
    }
122
0
  }
123
124
0
  std::vector<BT<cmGeneratorTarget*>> objectLibraries;
125
0
  target.GetObjectLibrariesInSources(objectLibraries);
126
0
  for (auto const& lib : objectLibraries) {
127
0
    auto const& name = lib.Value->GetName();
128
0
    if (dependencies.find(name) == dependencies.cend()) {
129
0
      auto objectItem = cmLinkItem(lib.Value, false, lib.Backtrace);
130
0
      dependencies[name] = Dependency(DependencyType::Object, objectItem);
131
0
    }
132
0
  }
133
134
0
  auto const& utilityItems = target.GetUtilityItems();
135
0
  for (auto const& item : utilityItems) {
136
0
    auto const& name = item.AsStr();
137
0
    if (dependencies.find(name) == dependencies.cend()) {
138
0
      dependencies[name] = Dependency(DependencyType::Utility, item);
139
0
    }
140
0
  }
141
0
}