/* 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 #include #include #include #include #include #include #include #include #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 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 $ Group }; BT Item; cmGeneratorTarget const* Target = nullptr; // The source file representing the external object (used when linking // `$`) cmSourceFile const* ObjectSource = nullptr; EntryKind Kind = Library; // The following member is for the management of items specified // through genex $ std::string Feature = std::string(DEFAULT); }; using EntryVector = std::vector; EntryVector const& Compute(); void SetOldLinkDirMode(bool b); std::set 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 LinkLibraryOverride; std::string const& GetCurrentFeature( std::string const& item, std::string const& defaultFeature) const; std::pair::iterator, bool> AllocateLinkEntry( cmLinkItem const& item); std::pair AddLinkEntry(cmLinkItem const& item, cm::optional const& groupIndex); void AddLinkObject(cmLinkItem const& item); void AddVarLinkEntries(cm::optional const& depender_index, const char* value); void AddDirectLinkEntries(); template void AddLinkEntries(cm::optional const& depender_index, std::vector const& libs); void AddLinkObjects(std::vector const& objs); cmLinkItem ResolveLinkItem(cm::optional const& depender_index, const std::string& name); // One entry for each unique item. std::vector EntryList; std::map LinkEntryIndex; // map storing, for each group, the list of items std::map> GroupItems; // BFS of initial dependencies. struct BFSEntry { size_t Index; cm::optional GroupIndex; const char* LibDepends; }; std::queue 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 SharedDepQueue; std::set SharedDepFollowed; void FollowSharedDeps(size_t depender_index, cmLinkInterface const* iface, bool follow_interface = false); void QueueSharedDependencies(size_t depender_index, std::vector const& deps); void HandleSharedDependency(SharedDepEntry const& dep); // Dependency inferral for each link item. struct DependSet : public std::set { }; struct DependSetList : public std::vector { bool Initialized = false; }; std::vector 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 ComponentVisited; std::vector 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 Entries; }; std::map PendingComponents; std::unique_ptr CCG; std::vector 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 OriginalEntries; std::set OldWrongConfigItems; void CheckWrongConfigItem(cmLinkItem const& item); // Record of explicitly linked object files. std::vector ObjectEntries; size_t ComponentOrderId; bool OldLinkDirMode = false; };