summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorMarc Chevrier <marc.chevrier@gmail.com>2023-11-07 07:38:31 (GMT)
committerMarc Chevrier <marc.chevrier@gmail.com>2023-11-08 16:06:19 (GMT)
commit07501c16784f7e333da2f0d9045c029babfa38ea (patch)
tree68c2c728cb9c9f0aa93fd83ddeed38fa571adff7 /Source
parentd6b796854bcb0460b7d3a8eee3e79a9482b6fc62 (diff)
downloadCMake-07501c16784f7e333da2f0d9045c029babfa38ea.zip
CMake-07501c16784f7e333da2f0d9045c029babfa38ea.tar.gz
CMake-07501c16784f7e333da2f0d9045c029babfa38ea.tar.bz2
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.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmComputeLinkDepends.cxx179
1 files changed, 136 insertions, 43 deletions
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 596572b..0f88577 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/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) {