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