Prechádzať zdrojové kódy

Link Step: Introduce EntriesProcessing class

This refactoring is done in preparation of the possibility to configure
the deduplication of the libraries as well as the order on the link command.
Marc Chevrier 2 rokov pred
rodič
commit
07501c1678
1 zmenil súbory, kde vykonal 136 pridanie a 43 odobranie
  1. 136 43
      Source/cmComputeLinkDepends.cxx

+ 136 - 43
Source/cmComputeLinkDepends.cxx

@@ -232,6 +232,135 @@ bool IsGroupFeatureSupported(cmMakefile* makefile,
     cmStrCat("CMAKE_LINK_GROUP_USING_", feature, "_SUPPORTED");
   return makefile->GetDefinition(featureSupported).IsOn();
 }
+
+class EntriesProcessing
+{
+public:
+  using LinkEntry = cmComputeLinkDepends::LinkEntry;
+  using EntryVector = cmComputeLinkDepends::EntryVector;
+
+  EntriesProcessing(EntryVector& entries, EntryVector& finalEntries)
+    : Entries(entries)
+    , FinalEntries(finalEntries)
+  {
+  }
+
+  void AddGroups(const std::map<size_t, std::vector<size_t>>& groups)
+  {
+    if (!groups.empty()) {
+      this->Groups = &groups;
+      // record all libraries as part of groups to ensure correct
+      // deduplication: libraries as part of groups are always kept.
+      for (const auto& group : groups) {
+        for (auto index : group.second) {
+          this->Emitted.insert(index);
+        }
+      }
+    }
+  }
+
+  void AddLibraries(const std::vector<size_t>& libEntries)
+  {
+    if (this->Order == Reverse) {
+      // Iterate in reverse order so we can keep only the last occurrence
+      // of a library.
+      this->AddLibraries(cmReverseRange(libEntries));
+    } else {
+      this->AddLibraries(cmMakeRange(libEntries));
+    }
+  }
+
+  void AddObjects(const std::vector<size_t>& objectEntries)
+  {
+    // Place explicitly linked object files in the front.  The linker will
+    // always use them anyway, and they may depend on symbols from libraries.
+    if (this->Order == Reverse) {
+      // Append in reverse order at the end since we reverse the final order.
+      for (auto index : cmReverseRange(objectEntries)) {
+        this->FinalEntries.emplace_back(this->Entries[index]);
+      }
+    } else {
+      // Append in reverse order to ensure correct final order
+      for (auto index : cmReverseRange(objectEntries)) {
+        this->FinalEntries.emplace(this->FinalEntries.begin(),
+                                   this->Entries[index]);
+      }
+    }
+  }
+
+  void Finalize()
+  {
+    if (this->Order == Reverse) {
+      // Reverse the resulting order since we iterated in reverse.
+      std::reverse(this->FinalEntries.begin(), this->FinalEntries.end());
+    }
+
+    // expand groups
+    if (this->Groups != nullptr) {
+      for (const auto& group : *this->Groups) {
+        const LinkEntry& groupEntry = this->Entries[group.first];
+        auto it = this->FinalEntries.begin();
+        while (true) {
+          it = std::find_if(it, this->FinalEntries.end(),
+                            [&groupEntry](const LinkEntry& entry) -> bool {
+                              return groupEntry.Item == entry.Item;
+                            });
+          if (it == this->FinalEntries.end()) {
+            break;
+          }
+          it->Item.Value = "</LINK_GROUP>";
+          for (auto index = group.second.rbegin();
+               index != group.second.rend(); ++index) {
+            it = this->FinalEntries.insert(it, this->Entries[*index]);
+          }
+          it = this->FinalEntries.insert(it, groupEntry);
+          it->Item.Value = "<LINK_GROUP>";
+        }
+      }
+    }
+  }
+
+private:
+  enum OrderKind
+  {
+    Forward,
+    Reverse
+  };
+
+  enum UnicityKind
+  {
+    None,
+    Shared,
+    All
+  };
+
+  bool IncludeEntry(LinkEntry const& entry) const
+  {
+    return this->Unicity == None ||
+      (this->Unicity == Shared &&
+       (entry.Target == nullptr ||
+        entry.Target->GetType() != cmStateEnums::SHARED_LIBRARY)) ||
+      (this->Unicity == All && entry.Kind != LinkEntry::Library);
+  }
+
+  template <typename Range>
+  void AddLibraries(const Range& libEntries)
+  {
+    for (auto index : libEntries) {
+      LinkEntry const& entry = this->Entries[index];
+      if (this->IncludeEntry(entry) || this->Emitted.insert(index).second) {
+        this->FinalEntries.emplace_back(entry);
+      }
+    }
+  }
+
+  OrderKind Order = Reverse;
+  UnicityKind Unicity = Shared;
+  EntryVector& Entries;
+  EntryVector& FinalEntries;
+  std::set<size_t> Emitted;
+  const std::map<size_t, std::vector<size_t>>* Groups = nullptr;
+};
 }
 
 const std::string cmComputeLinkDepends::LinkEntry::DEFAULT = "DEFAULT";
@@ -380,49 +509,13 @@ cmComputeLinkDepends::Compute()
   this->OrderLinkEntries();
 
   // Compute the final set of link entries.
-  // Iterate in reverse order so we can keep only the last occurrence
-  // of a shared library.
-  std::set<size_t> emitted;
-  for (size_t i : cmReverseRange(this->FinalLinkOrder)) {
-    LinkEntry const& e = this->EntryList[i];
-    cmGeneratorTarget const* t = e.Target;
-    // Entries that we know the linker will re-use do not need to be repeated.
-    bool uniquify = t && t->GetType() == cmStateEnums::SHARED_LIBRARY;
-    if (!uniquify || emitted.insert(i).second) {
-      this->FinalLinkEntries.push_back(e);
-    }
-  }
-  // Place explicitly linked object files in the front.  The linker will
-  // always use them anyway, and they may depend on symbols from libraries.
-  // Append in reverse order since we reverse the final order below.
-  for (size_t i : cmReverseRange(this->ObjectEntries)) {
-    this->FinalLinkEntries.emplace_back(this->EntryList[i]);
-  }
-  // Reverse the resulting order since we iterated in reverse.
-  std::reverse(this->FinalLinkEntries.begin(), this->FinalLinkEntries.end());
-
-  // Expand group items
-  if (!this->GroupItems.empty()) {
-    for (const auto& group : this->GroupItems) {
-      const LinkEntry& groupEntry = this->EntryList[group.first];
-      auto it = this->FinalLinkEntries.begin();
-      while (true) {
-        it = std::find_if(it, this->FinalLinkEntries.end(),
-                          [&groupEntry](const LinkEntry& entry) -> bool {
-                            return groupEntry.Item == entry.Item;
-                          });
-        if (it == this->FinalLinkEntries.end()) {
-          break;
-        }
-        it->Item.Value = "</LINK_GROUP>";
-        for (auto i = group.second.rbegin(); i != group.second.rend(); ++i) {
-          it = this->FinalLinkEntries.insert(it, this->EntryList[*i]);
-        }
-        it = this->FinalLinkEntries.insert(it, groupEntry);
-        it->Item.Value = "<LINK_GROUP>";
-      }
-    }
-  }
+  EntriesProcessing entriesProcessing{ this->EntryList,
+                                       this->FinalLinkEntries };
+  // Add groups first, to ensure that libraries of the groups are always kept.
+  entriesProcessing.AddGroups(this->GroupItems);
+  entriesProcessing.AddLibraries(this->FinalLinkOrder);
+  entriesProcessing.AddObjects(this->ObjectEntries);
+  entriesProcessing.Finalize();
 
   // Display the final set.
   if (this->DebugMode) {