cmComputeLinkDepends.h 6.2 KB

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