summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2024-09-26 12:47:39 (GMT)
committerKitware Robot <kwrobot@kitware.com>2024-09-26 12:47:47 (GMT)
commit53f3e5da1e6bc15baedb1053976b677909564c6f (patch)
tree7cfd690d8ca0577ed7b1c30471a1e053cc39f746 /Source
parent8d69aa79b059c9b6145de04458088a6e1e700837 (diff)
parent7abd3137b74543cf698ac6c7290696d82042e7de (diff)
downloadCMake-53f3e5da1e6bc15baedb1053976b677909564c6f.zip
CMake-53f3e5da1e6bc15baedb1053976b677909564c6f.tar.gz
CMake-53f3e5da1e6bc15baedb1053976b677909564c6f.tar.bz2
Merge topic 'link-strategy'
7abd3137b7 Linking: Optionally reorder direct dependencies from LINK_LIBRARIES 9285a9dc9a cmComputeLinkDepends: Add final dependency ordering to debug output f792db4ca2 cmComputeLinkDepends: Add undocumented per-target debug property 80b469a51d cmComputeLinkDepends: Factor out string literals as named constants 3bd73fcc76 cmComputeLinkDepends: Modernize member initialization 8db69c767b cmComputeLinkDepends: Remove redundant member dccdd030cd cmComputeLinkDepends: Replace depender index sentinel value with cm::optional 6c9d8dc243 cmComputeLinkDepends: Replace group index sentinel value with cm::optional ... Acked-by: Kitware Robot <kwrobot@kitware.com> Tested-by: buildbot <buildbot@kitware.com> Merge-request: !9835
Diffstat (limited to 'Source')
-rw-r--r--Source/cmComputeLinkDepends.cxx242
-rw-r--r--Source/cmComputeLinkDepends.h47
-rw-r--r--Source/cmComputeLinkInformation.cxx20
-rw-r--r--Source/cmMakefileTargetGenerator.cxx15
-rw-r--r--Source/cmTarget.cxx1
5 files changed, 190 insertions, 135 deletions
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index f12bcdb..70e992e 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -315,8 +315,10 @@ const LinkLibraryFeatureAttributeSet& GetLinkLibraryFeatureAttributes(
}
// LINK_GROUP helpers
-const auto LG_BEGIN = "<LINK_GROUP:"_s;
-const auto LG_END = "</LINK_GROUP:"_s;
+const cm::string_view LG_BEGIN = "<LINK_GROUP:"_s;
+const cm::string_view LG_END = "</LINK_GROUP:"_s;
+const cm::string_view LG_ITEM_BEGIN = "<LINK_GROUP>"_s;
+const cm::string_view LG_ITEM_END = "</LINK_GROUP>"_s;
inline std::string ExtractGroupFeature(std::string const& item)
{
@@ -431,8 +433,8 @@ public:
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) {
+ for (const auto& g : groups) {
+ for (auto index : g.second) {
this->Emitted.insert(index);
}
}
@@ -477,8 +479,8 @@ public:
// expand groups
if (this->Groups) {
- for (const auto& group : *this->Groups) {
- const LinkEntry& groupEntry = this->Entries[group.first];
+ for (const auto& g : *this->Groups) {
+ const LinkEntry& groupEntry = this->Entries[g.first];
auto it = this->FinalEntries.begin();
while (true) {
it = std::find_if(it, this->FinalEntries.end(),
@@ -488,13 +490,13 @@ public:
if (it == this->FinalEntries.end()) {
break;
}
- it->Item.Value = "</LINK_GROUP>";
- for (auto index = group.second.rbegin();
- index != group.second.rend(); ++index) {
+ it->Item.Value = std::string(LG_ITEM_END);
+ for (auto index = g.second.rbegin(); index != g.second.rend();
+ ++index) {
it = this->FinalEntries.insert(it, this->Entries[*index]);
}
it = this->FinalEntries.insert(it, groupEntry);
- it->Item.Value = "<LINK_GROUP>";
+ it->Item.Value = std::string(LG_ITEM_BEGIN);
}
}
}
@@ -579,16 +581,21 @@ std::string const& cmComputeLinkDepends::LinkEntry::DEFAULT =
cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target,
const std::string& config,
- const std::string& linkLanguage)
-{
- // Store context information.
- this->Target = target;
- this->Makefile = this->Target->Target->GetMakefile();
- this->GlobalGenerator =
- this->Target->GetLocalGenerator()->GetGlobalGenerator();
- this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
- this->LinkLanguage = linkLanguage;
+ const std::string& linkLanguage,
+ LinkLibrariesStrategy strategy)
+ : Target(target)
+ , Makefile(this->Target->Target->GetMakefile())
+ , GlobalGenerator(this->Target->GetLocalGenerator()->GetGlobalGenerator())
+ , CMakeInstance(this->GlobalGenerator->GetCMakeInstance())
+ , Config(config)
+ , DebugMode(this->Makefile->IsOn("CMAKE_LINK_DEPENDS_DEBUG_MODE") ||
+ this->Target->GetProperty("LINK_DEPENDS_DEBUG_MODE").IsOn())
+ , LinkLanguage(linkLanguage)
+ , LinkType(CMP0003_ComputeLinkType(
+ this->Config, this->Makefile->GetCMakeInstance()->GetDebugConfigs()))
+ , Strategy(strategy)
+{
// target oriented feature override property takes precedence over
// global override property
cm::string_view lloPrefix = "LINK_LIBRARY_OVERRIDE_"_s;
@@ -640,22 +647,6 @@ cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target,
});
}
}
-
- // The configuration being linked.
- this->HasConfig = !config.empty();
- this->Config = (this->HasConfig) ? config : std::string();
- std::vector<std::string> debugConfigs =
- this->Makefile->GetCMakeInstance()->GetDebugConfigs();
- this->LinkType = CMP0003_ComputeLinkType(this->Config, debugConfigs);
-
- // Enable debug mode if requested.
- this->DebugMode = this->Makefile->IsOn("CMAKE_LINK_DEPENDS_DEBUG_MODE");
-
- // Assume no compatibility until set.
- this->OldLinkDirMode = false;
-
- // No computation has been done.
- this->CCG = nullptr;
}
cmComputeLinkDepends::~cmComputeLinkDepends() = default;
@@ -706,7 +697,7 @@ cmComputeLinkDepends::Compute()
"---------------------------------------\n");
fprintf(stderr, "Link dependency analysis for target %s, config %s\n",
this->Target->GetName().c_str(),
- this->HasConfig ? this->Config.c_str() : "noconfig");
+ this->Config.empty() ? "noconfig" : this->Config.c_str());
this->DisplayConstraintGraph();
}
@@ -726,6 +717,11 @@ cmComputeLinkDepends::Compute()
// Compute the final ordering.
this->OrderLinkEntries();
+ // Display the final ordering.
+ if (this->DebugMode) {
+ this->DisplayOrderedEntries();
+ }
+
// Compute the final set of link entries.
EntriesProcessing entriesProcessing{ this->Target, this->LinkLanguage,
this->EntryList,
@@ -766,7 +762,7 @@ cmComputeLinkDepends::AllocateLinkEntry(cmLinkItem const& item)
}
std::pair<size_t, bool> cmComputeLinkDepends::AddLinkEntry(
- cmLinkItem const& item, size_t groupIndex)
+ cmLinkItem const& item, cm::optional<size_t> const& groupIndex)
{
// Allocate a spot for the item entry.
auto lei = this->AllocateLinkEntry(item);
@@ -842,10 +838,7 @@ void cmComputeLinkDepends::AddLinkObject(cmLinkItem const& item)
void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe)
{
// Get this entry representation.
- size_t depender_index =
- qe.GroupIndex == cmComputeComponentGraph::INVALID_COMPONENT
- ? qe.Index
- : qe.GroupIndex;
+ size_t depender_index = qe.GroupIndex ? *qe.GroupIndex : qe.Index;
LinkEntry const& entry = this->EntryList[qe.Index];
// Follow the item's dependencies.
@@ -944,8 +937,8 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
}
}
-void cmComputeLinkDepends::AddVarLinkEntries(size_t depender_index,
- const char* value)
+void cmComputeLinkDepends::AddVarLinkEntries(
+ cm::optional<size_t> const& depender_index, const char* value)
{
// This is called to add the dependencies named by
// <item>_LIB_DEPENDS. The variable contains a semicolon-separated
@@ -1006,15 +999,13 @@ void cmComputeLinkDepends::AddDirectLinkEntries()
// Add direct link dependencies in this configuration.
cmLinkImplementation const* impl = this->Target->GetLinkImplementation(
this->Config, cmGeneratorTarget::UseTo::Link);
- this->AddLinkEntries(cmComputeComponentGraph::INVALID_COMPONENT,
- impl->Libraries);
+ this->AddLinkEntries(cm::nullopt, impl->Libraries);
this->AddLinkObjects(impl->Objects);
for (auto const& language : impl->Languages) {
auto runtimeEntries = impl->LanguageRuntimeLibraries.find(language);
if (runtimeEntries != impl->LanguageRuntimeLibraries.end()) {
- this->AddLinkEntries(cmComputeComponentGraph::INVALID_COMPONENT,
- runtimeEntries->second);
+ this->AddLinkEntries(cm::nullopt, runtimeEntries->second);
}
}
for (cmLinkItem const& wi : impl->WrongConfigLibraries) {
@@ -1023,16 +1014,13 @@ void cmComputeLinkDepends::AddDirectLinkEntries()
}
template <typename T>
-void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
- std::vector<T> const& libs)
+void cmComputeLinkDepends::AddLinkEntries(
+ cm::optional<size_t> const& depender_index, std::vector<T> const& libs)
{
// Track inferred dependency sets implied by this list.
std::map<size_t, DependSet> dependSets;
- bool inGroup = false;
- std::pair<size_t, bool> groupIndex{
- cmComputeComponentGraph::INVALID_COMPONENT, false
- };
+ cm::optional<std::pair<size_t, bool>> group;
std::vector<size_t> groupItems;
// Loop over the libraries linked directly by the depender.
@@ -1046,9 +1034,8 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
// emit a warning if an undefined feature is used as part of
// an imported target
- if (item.Feature != LinkEntry::DEFAULT &&
- depender_index != cmComputeComponentGraph::INVALID_COMPONENT) {
- const auto& depender = this->EntryList[depender_index];
+ if (item.Feature != LinkEntry::DEFAULT && depender_index) {
+ const auto& depender = this->EntryList[*depender_index];
if (depender.Target && depender.Target->IsImported() &&
!IsFeatureSupported(this->Makefile, this->LinkLanguage,
item.Feature)) {
@@ -1069,18 +1056,17 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
if (cmHasPrefix(item.AsStr(), LG_BEGIN) &&
cmHasSuffix(item.AsStr(), '>')) {
- groupIndex = this->AddLinkEntry(item);
- if (groupIndex.second) {
- LinkEntry& entry = this->EntryList[groupIndex.first];
+ group = this->AddLinkEntry(item, cm::nullopt);
+ if (group->second) {
+ LinkEntry& entry = this->EntryList[group->first];
entry.Feature = ExtractGroupFeature(item.AsStr());
}
- inGroup = true;
- if (depender_index != cmComputeComponentGraph::INVALID_COMPONENT) {
- this->EntryConstraintGraph[depender_index].emplace_back(
- groupIndex.first, false, false, cmListFileBacktrace());
+ if (depender_index) {
+ this->EntryConstraintGraph[*depender_index].emplace_back(
+ group->first, false, false, cmListFileBacktrace());
} else {
// This is a direct dependency of the target being linked.
- this->OriginalEntries.push_back(groupIndex.first);
+ this->OriginalEntries.push_back(group->first);
}
continue;
}
@@ -1088,20 +1074,19 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
size_t dependee_index;
if (cmHasPrefix(item.AsStr(), LG_END) && cmHasSuffix(item.AsStr(), '>')) {
- dependee_index = groupIndex.first;
- if (groupIndex.second) {
- this->GroupItems.emplace(groupIndex.first, groupItems);
+ assert(group);
+ dependee_index = group->first;
+ if (group->second) {
+ this->GroupItems.emplace(group->first, std::move(groupItems));
}
- inGroup = false;
- groupIndex = std::make_pair(-1, false);
+ group = cm::nullopt;
groupItems.clear();
continue;
}
- if (depender_index != cmComputeComponentGraph::INVALID_COMPONENT &&
- inGroup) {
- const auto& depender = this->EntryList[depender_index];
- const auto& groupFeature = this->EntryList[groupIndex.first].Feature;
+ if (depender_index && group) {
+ const auto& depender = this->EntryList[*depender_index];
+ const auto& groupFeature = this->EntryList[group->first].Feature;
if (depender.Target && depender.Target->IsImported() &&
!IsGroupFeatureSupported(this->Makefile, this->LinkLanguage,
groupFeature)) {
@@ -1121,18 +1106,19 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
}
// Add a link entry for this item.
- auto ale = this->AddLinkEntry(item, groupIndex.first);
+ auto ale = this->AddLinkEntry(
+ item, group ? cm::optional<size_t>(group->first) : cm::nullopt);
dependee_index = ale.first;
LinkEntry& entry = this->EntryList[dependee_index];
bool supportedItem = true;
auto const& itemFeature =
this->GetCurrentFeature(entry.Item.Value, item.Feature);
- if (inGroup && ale.second && entry.Target &&
+ if (group && ale.second && entry.Target &&
(entry.Target->GetType() == cmStateEnums::TargetType::OBJECT_LIBRARY ||
entry.Target->GetType() ==
cmStateEnums::TargetType::INTERFACE_LIBRARY)) {
supportedItem = false;
- const auto& groupFeature = this->EntryList[groupIndex.first].Feature;
+ const auto& groupFeature = this->EntryList[group->first].Feature;
this->CMakeInstance->IssueMessage(
MessageType::AUTHOR_WARNING,
cmStrCat(
@@ -1173,8 +1159,8 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
}
if (supportedItem) {
- if (inGroup) {
- const auto& currentFeature = this->EntryList[groupIndex.first].Feature;
+ if (group) {
+ const auto& currentFeature = this->EntryList[group->first].Feature;
for (const auto& g : this->GroupItems) {
const auto& groupFeature = this->EntryList[g.first].Feature;
if (groupFeature == currentFeature) {
@@ -1245,17 +1231,17 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
}
}
- if (inGroup) {
+ if (group) {
// store item index for dependencies handling
groupItems.push_back(dependee_index);
} else {
std::vector<size_t> indexes;
bool entryHandled = false;
// search any occurrence of the library in already defined groups
- for (const auto& group : this->GroupItems) {
- for (auto index : group.second) {
+ for (const auto& g : this->GroupItems) {
+ for (auto index : g.second) {
if (entry.Item.Value == this->EntryList[index].Item.Value) {
- indexes.push_back(group.first);
+ indexes.push_back(g.first);
entryHandled = true;
break;
}
@@ -1267,8 +1253,8 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
for (auto index : indexes) {
// The dependee must come after the depender.
- if (depender_index != cmComputeComponentGraph::INVALID_COMPONENT) {
- this->EntryConstraintGraph[depender_index].emplace_back(
+ if (depender_index) {
+ this->EntryConstraintGraph[*depender_index].emplace_back(
index, false, false, cmListFileBacktrace());
} else {
// This is a direct dependency of the target being linked.
@@ -1311,14 +1297,14 @@ void cmComputeLinkDepends::AddLinkObjects(std::vector<cmLinkItem> const& objs)
}
}
-cmLinkItem cmComputeLinkDepends::ResolveLinkItem(size_t depender_index,
- const std::string& name)
+cmLinkItem cmComputeLinkDepends::ResolveLinkItem(
+ cm::optional<size_t> const& depender_index, const std::string& name)
{
// Look for a target in the scope of the depender.
cmGeneratorTarget const* from = this->Target;
- if (depender_index != cmComputeComponentGraph::INVALID_COMPONENT) {
+ if (depender_index) {
if (cmGeneratorTarget const* depender =
- this->EntryList[depender_index].Target) {
+ this->EntryList[*depender_index].Target) {
from = depender;
}
}
@@ -1494,9 +1480,8 @@ void cmComputeLinkDepends::OrderLinkEntries()
this->ComponentOrderId = n;
// Run in reverse order so the topological order will preserve the
// original order where there are no constraints.
- for (size_t c = n - 1; c != cmComputeComponentGraph::INVALID_COMPONENT;
- --c) {
- this->VisitComponent(c);
+ for (size_t c = n; c > 0; --c) {
+ this->VisitComponent(c - 1);
}
// Display the component graph.
@@ -1505,8 +1490,22 @@ void cmComputeLinkDepends::OrderLinkEntries()
}
// Start with the original link line.
- for (size_t originalEntry : this->OriginalEntries) {
- this->VisitEntry(originalEntry);
+ switch (this->Strategy) {
+ case LinkLibrariesStrategy::PRESERVE_ORDER: {
+ // Emit the direct dependencies in their original order.
+ // This gives projects control over ordering.
+ for (size_t originalEntry : this->OriginalEntries) {
+ this->VisitEntry(originalEntry);
+ }
+ } break;
+ case LinkLibrariesStrategy::REORDER: {
+ // Schedule the direct dependencies for emission in topo order.
+ // This may produce more efficient link lines.
+ for (size_t originalEntry : this->OriginalEntries) {
+ this->MakePendingComponent(
+ this->CCG->GetComponentMap()[originalEntry]);
+ }
+ } break;
}
// Now explore anything left pending. Since the component graph is
@@ -1671,26 +1670,49 @@ size_t cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
return count;
}
-void cmComputeLinkDepends::DisplayFinalEntries()
+namespace {
+void DisplayLinkEntry(int& count, cmComputeLinkDepends::LinkEntry const& entry)
{
- fprintf(stderr, "target [%s] links to:\n", this->Target->GetName().c_str());
- char space[] = " ";
- int count = 2;
- for (LinkEntry const& lei : this->FinalLinkEntries) {
- if (lei.Kind == LinkEntry::Group) {
- fprintf(stderr, " %s group",
- lei.Item.Value == "<LINK_GROUP>" ? "start" : "end");
- count = lei.Item.Value == "<LINK_GROUP>" ? 4 : 2;
- } else if (lei.Target) {
- fprintf(stderr, "%*starget [%s]", count, space,
- lei.Target->GetName().c_str());
+ if (entry.Kind == cmComputeLinkDepends::LinkEntry::Group) {
+ if (entry.Item.Value == LG_ITEM_BEGIN) {
+ fprintf(stderr, " start group");
+ count = 4;
+ } else if (entry.Item.Value == LG_ITEM_END) {
+ fprintf(stderr, " end group");
+ count = 2;
} else {
- fprintf(stderr, "%*sitem [%s]", count, space, lei.Item.Value.c_str());
- }
- if (lei.Feature != LinkEntry::DEFAULT) {
- fprintf(stderr, ", feature [%s]", lei.Feature.c_str());
+ fprintf(stderr, " group");
}
- fprintf(stderr, "\n");
+ } else if (entry.Target) {
+ fprintf(stderr, "%*starget [%s]", count, "",
+ entry.Target->GetName().c_str());
+ } else {
+ fprintf(stderr, "%*sitem [%s]", count, "", entry.Item.Value.c_str());
+ }
+ if (entry.Feature != cmComputeLinkDepends::LinkEntry::DEFAULT) {
+ fprintf(stderr, ", feature [%s]", entry.Feature.c_str());
+ }
+ fprintf(stderr, "\n");
+}
+}
+
+void cmComputeLinkDepends::DisplayOrderedEntries()
+{
+ fprintf(stderr, "target [%s] link dependency ordering:\n",
+ this->Target->GetName().c_str());
+ int count = 2;
+ for (auto index : this->FinalLinkOrder) {
+ DisplayLinkEntry(count, this->EntryList[index]);
+ }
+ fprintf(stderr, "\n");
+}
+
+void cmComputeLinkDepends::DisplayFinalEntries()
+{
+ fprintf(stderr, "target [%s] link line:\n", this->Target->GetName().c_str());
+ int count = 2;
+ for (LinkEntry const& entry : this->FinalLinkEntries) {
+ DisplayLinkEntry(count, entry);
}
fprintf(stderr, "\n");
}
diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h
index 66daa07..8b8aba4 100644
--- a/Source/cmComputeLinkDepends.h
+++ b/Source/cmComputeLinkDepends.h
@@ -13,18 +13,26 @@
#include <utility>
#include <vector>
-#include "cmComputeComponentGraph.h"
+#include <cm/optional>
+
#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
+{
+ PRESERVE_ORDER,
+ REORDER,
+};
+
/** \class cmComputeLinkDepends
* \brief Compute link dependencies for targets.
*/
@@ -33,7 +41,8 @@ class cmComputeLinkDepends
public:
cmComputeLinkDepends(cmGeneratorTarget const* target,
const std::string& config,
- const std::string& linkLanguage);
+ const std::string& linkLanguage,
+ LinkLibrariesStrategy strategy);
~cmComputeLinkDepends();
cmComputeLinkDepends(const cmComputeLinkDepends&) = delete;
@@ -84,12 +93,16 @@ public:
private:
// Context information.
- cmGeneratorTarget const* Target;
- cmMakefile* Makefile;
- cmGlobalGenerator const* GlobalGenerator;
+ cmGeneratorTarget const* Target = nullptr;
+ cmMakefile* Makefile = nullptr;
+ cmGlobalGenerator const* GlobalGenerator = nullptr;
cmake* CMakeInstance;
- std::string LinkLanguage;
std::string Config;
+ bool DebugMode = false;
+ std::string LinkLanguage;
+ cmTargetLinkLibraryType LinkType;
+ LinkLibrariesStrategy Strategy;
+
EntryVector FinalLinkEntries;
std::map<std::string, std::string> LinkLibraryOverride;
@@ -98,16 +111,18 @@ private:
std::pair<std::map<cmLinkItem, size_t>::iterator, bool> AllocateLinkEntry(
cmLinkItem const& item);
- std::pair<size_t, bool> AddLinkEntry(
- cmLinkItem const& item,
- size_t groupIndex = cmComputeComponentGraph::INVALID_COMPONENT);
+ std::pair<size_t, bool> AddLinkEntry(cmLinkItem const& item,
+ cm::optional<size_t> const& groupIndex);
void AddLinkObject(cmLinkItem const& item);
- void AddVarLinkEntries(size_t depender_index, const char* value);
+ void AddVarLinkEntries(cm::optional<size_t> const& depender_index,
+ const char* value);
void AddDirectLinkEntries();
template <typename T>
- void AddLinkEntries(size_t depender_index, std::vector<T> const& libs);
+ void AddLinkEntries(cm::optional<size_t> const& depender_index,
+ std::vector<T> const& libs);
void AddLinkObjects(std::vector<cmLinkItem> const& objs);
- cmLinkItem ResolveLinkItem(size_t depender_index, const std::string& name);
+ cmLinkItem ResolveLinkItem(cm::optional<size_t> const& depender_index,
+ const std::string& name);
// One entry for each unique item.
std::vector<LinkEntry> EntryList;
@@ -120,7 +135,7 @@ private:
struct BFSEntry
{
size_t Index;
- size_t GroupIndex;
+ cm::optional<size_t> GroupIndex;
const char* LibDepends;
};
std::queue<BFSEntry> BFSQueue;
@@ -192,6 +207,7 @@ private:
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.
@@ -203,8 +219,5 @@ private:
std::vector<size_t> ObjectEntries;
size_t ComponentOrderId;
- cmTargetLinkLibraryType LinkType;
- bool HasConfig;
- bool DebugMode;
- bool OldLinkDirMode;
+ bool OldLinkDirMode = false;
};
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index dd194ed..26ff326 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -9,6 +9,7 @@
#include <cm/memory>
#include <cm/optional>
+#include <cm/string_view>
#include <cmext/algorithm>
#include <cmext/string_view>
@@ -567,8 +568,25 @@ bool cmComputeLinkInformation::Compute()
return false;
}
+ LinkLibrariesStrategy strategy = LinkLibrariesStrategy::PRESERVE_ORDER;
+ if (cmValue s = this->Target->GetProperty("LINK_LIBRARIES_STRATEGY")) {
+ if (*s == "PRESERVE_ORDER"_s) {
+ strategy = LinkLibrariesStrategy::PRESERVE_ORDER;
+ } else if (*s == "REORDER"_s) {
+ strategy = LinkLibrariesStrategy::REORDER;
+ } else {
+ this->CMakeInstance->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("LINK_LIBRARIES_STRATEGY value '", *s,
+ "' is not recognized."),
+ this->Target->GetBacktrace());
+ return false;
+ }
+ }
+
// Compute the ordered link line items.
- cmComputeLinkDepends cld(this->Target, this->Config, this->LinkLanguage);
+ cmComputeLinkDepends cld(this->Target, this->Config, this->LinkLanguage,
+ strategy);
cld.SetOldLinkDirMode(this->OldLinkDirMode);
cmComputeLinkDepends::EntryVector const& linkEntries = cld.Compute();
FeatureDescriptor const* currentFeature = nullptr;
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 9ff0a4a..9d0d466 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -2206,13 +2206,14 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
bool useResponseFile, std::vector<std::string>& makefile_depends,
std::string const& linkLanguage, ResponseFlagFor responseMode)
{
- std::string frameworkPath;
- std::string linkPath;
- cmComputeLinkInformation* pcli =
- this->GeneratorTarget->GetLinkInformation(this->GetConfigName());
- this->LocalGenerator->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
- frameworkPath, linkPath);
- linkLibs = frameworkPath + linkPath + linkLibs;
+ if (cmComputeLinkInformation* pcli =
+ this->GeneratorTarget->GetLinkInformation(this->GetConfigName())) {
+ std::string frameworkPath;
+ std::string linkPath;
+ this->LocalGenerator->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
+ frameworkPath, linkPath);
+ linkLibs = frameworkPath + linkPath + linkLibs;
+ }
if (useResponseFile &&
linkLibs.find_first_not_of(' ') != std::string::npos) {
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index da0091b..f220837 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -466,6 +466,7 @@ TargetProperty const StaticTargetProperties[] = {
{ "LINKER_TYPE"_s, IC::CanCompileSources },
{ "ENABLE_EXPORTS"_s, IC::TargetWithSymbolExports },
{ "LINK_LIBRARIES_ONLY_TARGETS"_s, IC::NormalNonImportedTarget },
+ { "LINK_LIBRARIES_STRATEGY"_s, IC::NormalNonImportedTarget },
{ "LINK_SEARCH_START_STATIC"_s, IC::CanCompileSources },
{ "LINK_SEARCH_END_STATIC"_s, IC::CanCompileSources },
// Initialize per-configuration name postfix property from the variable only