/* 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 <map> #include <memory> #include <queue> #include <set> #include <string> #include <vector> #include "cmGraphAdjacencyList.h" #include "cmLinkItem.h" #include "cmListFileCache.h" #include "cmTargetLinkLibraryType.h" class cmComputeComponentGraph; class cmGeneratorTarget; class cmGlobalGenerator; class cmMakefile; class cmake; /** \class cmComputeLinkDepends * \brief Compute link dependencies for targets. */ class cmComputeLinkDepends { public: cmComputeLinkDepends(cmGeneratorTarget const* target, const std::string& config); ~cmComputeLinkDepends(); cmComputeLinkDepends(const cmComputeLinkDepends&) = delete; cmComputeLinkDepends& operator=(const cmComputeLinkDepends&) = delete; // Basic information about each link item. struct LinkEntry { BT<std::string> Item; cmGeneratorTarget const* Target = nullptr; bool IsSharedDep = false; bool IsFlag = false; bool IsObject = false; }; 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; cmMakefile* Makefile; cmGlobalGenerator const* GlobalGenerator; cmake* CMakeInstance; std::string Config; EntryVector FinalLinkEntries; std::map<cmLinkItem, int>::iterator AllocateLinkEntry( cmLinkItem const& item); int AddLinkEntry(cmLinkItem const& item); void AddLinkObject(cmLinkItem const& item); void AddVarLinkEntries(int depender_index, const char* value); void AddDirectLinkEntries(); template <typename T> void AddLinkEntries(int depender_index, std::vector<T> const& libs); void AddLinkObjects(std::vector<cmLinkItem> const& objs); cmLinkItem ResolveLinkItem(int depender_index, const std::string& name); // One entry for each unique item. std::vector<LinkEntry> EntryList; std::map<cmLinkItem, int> LinkEntryIndex; // BFS of initial dependencies. struct BFSEntry { int Index; 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; int DependerIndex; }; std::queue<SharedDepEntry> SharedDepQueue; std::set<int> SharedDepFollowed; void FollowSharedDeps(int depender_index, cmLinkInterface const* iface, bool follow_interface = false); void QueueSharedDependencies(int depender_index, std::vector<cmLinkItem> const& deps); void HandleSharedDependency(SharedDepEntry const& dep); // Dependency inferral for each link item. struct DependSet : public std::set<int> { }; struct DependSetList : public std::vector<DependSet> { bool Initialized = false; }; std::vector<DependSetList> InferredDependSets; void InferDependencies(); // Ordering constraint graph adjacency list. using NodeList = cmGraphNodeList; using EdgeList = cmGraphEdgeList; using Graph = cmGraphAdjacencyList; Graph EntryConstraintGraph; void CleanConstraintGraph(); void DisplayConstraintGraph(); // Ordering algorithm. void OrderLinkEntires(); std::vector<char> ComponentVisited; std::vector<int> ComponentOrder; struct PendingComponent { // The real component id. Needed because the map is indexed by // component topological index. int 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. int Count; // The entries yet to be seen to complete the component. std::set<int> Entries; }; std::map<int, PendingComponent> PendingComponents; std::unique_ptr<cmComputeComponentGraph> CCG; std::vector<int> FinalLinkOrder; void DisplayComponents(); void VisitComponent(unsigned int c); void VisitEntry(int index); PendingComponent& MakePendingComponent(unsigned int component); int ComputeComponentCount(NodeList const& nl); void DisplayFinalEntries(); // Record of the original link line. std::vector<int> OriginalEntries; std::set<cmGeneratorTarget const*> OldWrongConfigItems; void CheckWrongConfigItem(cmLinkItem const& item); // Record of explicitly linked object files. std::vector<int> ObjectEntries; int ComponentOrderId; cmTargetLinkLibraryType LinkType; bool HasConfig; bool DebugMode; bool OldLinkDirMode; };