Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmComputeLinkDepends.h
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
#pragma once
4
5
#include "cmConfigure.h" // IWYU pragma: keep
6
7
#include <cstddef>
8
#include <map>
9
#include <memory>
10
#include <queue>
11
#include <set>
12
#include <string>
13
#include <utility>
14
#include <vector>
15
16
#include <cm/optional>
17
18
#include "cmGraphAdjacencyList.h"
19
#include "cmLinkItem.h"
20
#include "cmListFileCache.h"
21
#include "cmTargetLinkLibraryType.h"
22
23
class cmComputeComponentGraph;
24
class cmGeneratorTarget;
25
class cmGlobalGenerator;
26
class cmMakefile;
27
class cmSourceFile;
28
class cmake;
29
30
enum class LinkLibrariesStrategy
31
{
32
  REORDER_MINIMALLY,
33
  REORDER_FREELY,
34
};
35
36
/** \class cmComputeLinkDepends
37
 * \brief Compute link dependencies for targets.
38
 */
39
class cmComputeLinkDepends
40
{
41
public:
42
  cmComputeLinkDepends(cmGeneratorTarget const* target, std::string config,
43
                       std::string linkLanguage,
44
                       LinkLibrariesStrategy strategy);
45
  ~cmComputeLinkDepends();
46
47
  cmComputeLinkDepends(cmComputeLinkDepends const&) = delete;
48
  cmComputeLinkDepends& operator=(cmComputeLinkDepends const&) = delete;
49
50
  // Basic information about each link item.
51
  struct LinkEntry
52
  {
53
0
    LinkEntry() = default;
54
    LinkEntry(BT<std::string> item, cmGeneratorTarget const* target = nullptr)
55
0
      : Item(std::move(item))
56
0
      , Target(target)
57
0
    {
58
0
    }
59
60
    static std::string const& DEFAULT;
61
62
    enum EntryKind
63
    {
64
      Library,
65
      Object,
66
      SharedDep,
67
      Flag,
68
      // The following member is for the management of items specified
69
      // through genex $<LINK_GROUP:...>
70
      Group
71
    };
72
73
    BT<std::string> Item;
74
    cmGeneratorTarget const* Target = nullptr;
75
    // The source file representing the external object (used when linking
76
    // `$<TARGET_OBJECTS>`)
77
    cmSourceFile const* ObjectSource = nullptr;
78
    EntryKind Kind = Library;
79
    // The following member is for the management of items specified
80
    // through genex $<LINK_LIBRARY:...>
81
    std::string Feature = std::string(DEFAULT);
82
  };
83
84
  using EntryVector = std::vector<LinkEntry>;
85
  EntryVector const& Compute();
86
87
private:
88
  // Context information.
89
  cmGeneratorTarget const* Target = nullptr;
90
  cmMakefile* Makefile = nullptr;
91
  cmGlobalGenerator const* GlobalGenerator = nullptr;
92
  cmake* CMakeInstance;
93
  std::string Config;
94
  bool DebugMode = false;
95
  std::string LinkLanguage;
96
  cmTargetLinkLibraryType LinkType;
97
  LinkLibrariesStrategy Strategy;
98
99
  EntryVector FinalLinkEntries;
100
  std::map<std::string, std::string> LinkLibraryOverride;
101
102
  std::string const& GetCurrentFeature(
103
    std::string const& item, std::string const& defaultFeature) const;
104
105
  std::pair<std::map<cmLinkItem, size_t>::iterator, bool> AllocateLinkEntry(
106
    cmLinkItem const& item);
107
  std::pair<size_t, bool> AddLinkEntry(cmLinkItem const& item,
108
                                       cm::optional<size_t> groupIndex);
109
  void AddLinkObject(cmLinkItem const& item);
110
  void AddVarLinkEntries(cm::optional<size_t> depender_index,
111
                         char const* value);
112
  void AddDirectLinkEntries();
113
  template <typename T>
114
  void AddLinkEntries(cm::optional<size_t> depender_index,
115
                      std::vector<T> const& libs);
116
  void AddLinkObjects(std::vector<cmLinkItem> const& objs);
117
  cmLinkItem ResolveLinkItem(cm::optional<size_t> depender_index,
118
                             std::string const& name);
119
120
  // One entry for each unique item.
121
  std::vector<LinkEntry> EntryList;
122
  std::map<cmLinkItem, size_t> LinkEntryIndex;
123
124
  // map storing, for each group, the list of items
125
  std::map<size_t, std::vector<size_t>> GroupItems;
126
127
  // BFS of initial dependencies.
128
  struct BFSEntry
129
  {
130
    size_t Index;
131
    cm::optional<size_t> GroupIndex;
132
    char const* LibDepends;
133
  };
134
  std::queue<BFSEntry> BFSQueue;
135
  void FollowLinkEntry(BFSEntry qe);
136
137
  // Shared libraries that are included only because they are
138
  // dependencies of other shared libraries, not because they are part
139
  // of the interface.
140
  struct SharedDepEntry
141
  {
142
    cmLinkItem Item;
143
    size_t DependerIndex;
144
  };
145
  std::queue<SharedDepEntry> SharedDepQueue;
146
  std::set<size_t> SharedDepFollowed;
147
  void FollowSharedDeps(size_t depender_index, cmLinkInterface const* iface,
148
                        bool follow_interface = false);
149
  void QueueSharedDependencies(size_t depender_index,
150
                               std::vector<cmLinkItem> const& deps);
151
  void HandleSharedDependency(SharedDepEntry const& dep);
152
153
  // Dependency inferral for each link item.
154
  struct DependSet : public std::set<size_t>
155
  {
156
  };
157
  struct DependSetList : public std::vector<DependSet>
158
  {
159
    bool Initialized = false;
160
  };
161
  std::vector<DependSetList> InferredDependSets;
162
  void InferDependencies();
163
164
  // To finalize dependencies over groups in place of raw items
165
  void UpdateGroupDependencies();
166
167
  // Ordering constraint graph adjacency list.
168
  using NodeList = cmGraphNodeList;
169
  using EdgeList = cmGraphEdgeList;
170
  using Graph = cmGraphAdjacencyList;
171
  Graph EntryConstraintGraph;
172
  void CleanConstraintGraph();
173
  bool CheckCircularDependencies() const;
174
  void DisplayConstraintGraph();
175
176
  // Ordering algorithm.
177
  void OrderLinkEntries();
178
  std::vector<char> ComponentVisited;
179
  std::vector<size_t> ComponentOrder;
180
181
  struct PendingComponent
182
  {
183
    // The real component id.  Needed because the map is indexed by
184
    // component topological index.
185
    size_t Id;
186
187
    // The number of times the component needs to be seen.  This is
188
    // always 1 for trivial components and is initially 2 for
189
    // non-trivial components.
190
    size_t Count;
191
192
    // The entries yet to be seen to complete the component.
193
    std::set<size_t> Entries;
194
  };
195
  std::map<size_t, PendingComponent> PendingComponents;
196
  std::unique_ptr<cmComputeComponentGraph> CCG;
197
  std::vector<size_t> FinalLinkOrder;
198
  void DisplayComponents();
199
  void VisitComponent(size_t c);
200
  void VisitEntry(size_t index);
201
  PendingComponent& MakePendingComponent(size_t component);
202
  size_t ComputeComponentCount(NodeList const& nl);
203
  void DisplayOrderedEntries();
204
  void DisplayFinalEntries();
205
206
  // Record of the original link line.
207
  std::vector<size_t> OriginalEntries;
208
209
  // Record of explicitly linked object files.
210
  std::vector<size_t> ObjectEntries;
211
212
  size_t ComponentOrderId;
213
};