diff options
author | Brad King <brad.king@kitware.com> | 2024-09-26 12:47:39 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2024-09-26 12:47:47 (GMT) |
commit | 53f3e5da1e6bc15baedb1053976b677909564c6f (patch) | |
tree | 7cfd690d8ca0577ed7b1c30471a1e053cc39f746 /Source | |
parent | 8d69aa79b059c9b6145de04458088a6e1e700837 (diff) | |
parent | 7abd3137b74543cf698ac6c7290696d82042e7de (diff) | |
download | CMake-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.cxx | 242 | ||||
-rw-r--r-- | Source/cmComputeLinkDepends.h | 47 | ||||
-rw-r--r-- | Source/cmComputeLinkInformation.cxx | 20 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 15 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 1 |
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 |