diff options
author | Brad King <brad.king@kitware.com> | 2021-05-26 14:56:10 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2021-05-29 13:28:36 (GMT) |
commit | 3941555d935afad8343c66f39579bfc611201a6f (patch) | |
tree | 4f5b55b32aa25a56fb6f6f10ba896585878e6331 /Source | |
parent | f530b3a26729d0820c804e312b72e0061d6eeb4b (diff) | |
download | CMake-3941555d935afad8343c66f39579bfc611201a6f.zip CMake-3941555d935afad8343c66f39579bfc611201a6f.tar.gz CMake-3941555d935afad8343c66f39579bfc611201a6f.tar.bz2 |
target_link_libraries: Place $<TARGET_OBJECTS> before libraries
Linkers always use object files explicitly specified on the command line
regardless of where they appear. Move them to the front of the list of
linked libraries in so that symbols required by the object files can be
resolved by any library.
Issue: #22149
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmComputeLinkDepends.cxx | 36 | ||||
-rw-r--r-- | Source/cmComputeLinkDepends.h | 5 | ||||
-rw-r--r-- | Source/cmComputeTargetDepends.cxx | 13 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 38 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 1 | ||||
-rw-r--r-- | Source/cmLinkItem.h | 6 |
6 files changed, 94 insertions, 5 deletions
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 5341e8d..4a6518fd 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -263,6 +263,12 @@ cmComputeLinkDepends::Compute() 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 (int 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()); @@ -328,6 +334,27 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) return index; } +void cmComputeLinkDepends::AddLinkObject(cmLinkItem const& item) +{ + // Check if the item entry has already been added. + auto lei = this->LinkEntryIndex.find(item); + if (lei != this->LinkEntryIndex.end()) { + return; + } + + // Allocate a spot for the item entry. + lei = this->AllocateLinkEntry(item); + + // Initialize the item entry. + int index = lei->second; + LinkEntry& entry = this->EntryList[index]; + entry.Item = BT<std::string>(item.AsStr(), item.Backtrace); + entry.IsObject = true; + + // Record explicitly linked object files separately. + this->ObjectEntries.emplace_back(index); +} + void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe) { // Get this entry representation. @@ -343,6 +370,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe) entry.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY; // This target provides its own link interface information. this->AddLinkEntries(depender_index, iface->Libraries); + this->AddLinkObjects(iface->Objects); if (isIface) { return; @@ -487,6 +515,7 @@ void cmComputeLinkDepends::AddDirectLinkEntries() cmLinkImplementation const* impl = this->Target->GetLinkImplementation(this->Config); this->AddLinkEntries(-1, impl->Libraries); + this->AddLinkObjects(impl->Objects); for (cmLinkItem const& wi : impl->WrongConfigLibraries) { this->CheckWrongConfigItem(wi); } @@ -546,6 +575,13 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, } } +void cmComputeLinkDepends::AddLinkObjects(std::vector<cmLinkItem> const& objs) +{ + for (cmLinkItem const& obj : objs) { + this->AddLinkObject(obj); + } +} + cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index, const std::string& name) { diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 00fbd59..72316f1 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -66,10 +66,12 @@ private: std::map<cmLinkItem, int>::iterator AllocateLinkEntry( cmLinkItem const& item); int AddLinkEntry(cmLinkItem const& item); + void AddLinkObject(cmLinkItem const& item); void AddVarLinkEntries(int depender_index, const char* value); void AddDirectLinkEntries(); template <typename T> void AddLinkEntries(int depender_index, std::vector<T> const& libs); + void AddLinkObjects(std::vector<cmLinkItem> const& objs); cmLinkItem ResolveLinkItem(int depender_index, const std::string& name); // One entry for each unique item. @@ -154,6 +156,9 @@ private: std::set<cmGeneratorTarget const*> OldWrongConfigItems; void CheckWrongConfigItem(cmLinkItem const& item); + // Record of explicitly linked object files. + std::vector<int> ObjectEntries; + int ComponentOrderId; cmTargetLinkLibraryType LinkType; bool HasConfig; diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 0f23417..76712f4 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -20,6 +20,7 @@ #include "cmProperty.h" #include "cmRange.h" #include "cmSourceFile.h" +#include "cmSourceFileLocationKind.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -227,6 +228,12 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) this->AddInterfaceDepends(depender_index, lib, it, emitted); } } + for (cmLinkItem const& obj : impl->Objects) { + if (cmSourceFile const* o = depender->Makefile->GetSource( + obj.AsStr(), cmSourceFileLocationKind::Known)) { + this->AddObjectDepends(depender_index, o, emitted); + } + } } // Add dependencies on object libraries not otherwise handled above. @@ -274,6 +281,12 @@ void cmComputeTargetDepends::AddInterfaceDepends( this->AddInterfaceDepends(depender_index, libBT, config, emitted); } } + for (cmLinkItem const& obj : iface->Objects) { + if (cmSourceFile const* o = depender->Makefile->GetSource( + obj.AsStr(), cmSourceFileLocationKind::Known)) { + this->AddObjectDepends(depender_index, o, emitted); + } + } } } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 51742cf..5deb2df 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6275,8 +6275,8 @@ cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem( void cmGeneratorTarget::ExpandLinkItems( std::string const& prop, std::string const& value, std::string const& config, cmGeneratorTarget const* headTarget, bool usage_requirements_only, - std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition, - bool& hadContextSensitiveCondition, + std::vector<cmLinkItem>& items, std::vector<cmLinkItem>& objects, + bool& hadHeadSensitiveCondition, bool& hadContextSensitiveCondition, bool& hadLinkLanguageSensitiveCondition) const { // Keep this logic in sync with ComputeLinkImplementationLibraries. @@ -6294,9 +6294,22 @@ void cmGeneratorTarget::ExpandLinkItems( cmExpandList(cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker, this, headTarget->LinkerLanguage), libs); + cmMakefile const* mf = this->LocalGenerator->GetMakefile(); for (std::string const& lib : libs) { if (cm::optional<cmLinkItem> maybeItem = this->LookupLinkItem(lib, cge->GetBacktrace())) { + if (!maybeItem->Target) { + // Report explicitly linked object files separately. + std::string const& maybeObj = maybeItem->AsStr(); + if (cmSystemTools::FileIsFullPath(maybeObj)) { + cmSourceFile const* sf = + mf->GetSource(maybeObj, cmSourceFileLocationKind::Known); + if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { + objects.emplace_back(std::move(*maybeItem)); + continue; + } + } + } items.emplace_back(std::move(*maybeItem)); } } @@ -6804,7 +6817,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // The interface libraries have been explicitly set. this->ExpandLinkItems(linkIfaceProp, *explicitLibraries, config, headTarget, usage_requirements_only, iface.Libraries, - iface.HadHeadSensitiveCondition, + iface.Objects, iface.HadHeadSensitiveCondition, iface.HadContextSensitiveCondition, iface.HadLinkLanguageSensitiveCondition); return; @@ -6828,6 +6841,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // Compare the link implementation fallback link interface to the // preferred new link interface property and warn if different. std::vector<cmLinkItem> ifaceLibs; + std::vector<cmLinkItem> ifaceObjects; static const std::string newProp = "INTERFACE_LINK_LIBRARIES"; if (cmProp newExplicitLibraries = this->GetProperty(newProp)) { bool hadHeadSensitiveConditionDummy = false; @@ -6835,7 +6849,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( bool hadLinkLanguageSensitiveConditionDummy = false; this->ExpandLinkItems(newProp, *newExplicitLibraries, config, headTarget, usage_requirements_only, ifaceLibs, - hadHeadSensitiveConditionDummy, + ifaceObjects, hadHeadSensitiveConditionDummy, hadContextSensitiveConditionDummy, hadLinkLanguageSensitiveConditionDummy); } @@ -6903,7 +6917,7 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( cmExpandList(info->Languages, iface.Languages); this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config, headTarget, usage_requirements_only, iface.Libraries, - iface.HadHeadSensitiveCondition, + iface.Objects, iface.HadHeadSensitiveCondition, iface.HadContextSensitiveCondition, iface.HadLinkLanguageSensitiveCondition); std::vector<std::string> deps = cmExpandedList(info->SharedDeps); @@ -7425,6 +7439,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( cmGeneratorTarget const* head) const { cmLocalGenerator const* lg = this->LocalGenerator; + cmMakefile const* mf = lg->GetMakefile(); cmStringRange entryRange = this->Target->GetLinkImplementationEntries(); cmBacktraceRange btRange = this->Target->GetLinkImplementationBacktraces(); cmBacktraceRange::const_iterator btIt = btRange.begin(); @@ -7500,6 +7515,19 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( // The entry is meant for this configuration. cmLinkItem item = this->ResolveLinkItem(name, *btIt, lg); + if (!item.Target) { + // Report explicitly linked object files separately. + std::string const& maybeObj = item.AsStr(); + if (cmSystemTools::FileIsFullPath(maybeObj)) { + cmSourceFile const* sf = + mf->GetSource(maybeObj, cmSourceFileLocationKind::Known); + if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { + impl.Objects.emplace_back(std::move(item)); + continue; + } + } + } + impl.Libraries.emplace_back(std::move(item), evaluated != *le); } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index dbc47b8..be36f3f 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1036,6 +1036,7 @@ private: const cmGeneratorTarget* headTarget, bool usage_requirements_only, std::vector<cmLinkItem>& items, + std::vector<cmLinkItem>& objects, bool& hadHeadSensitiveCondition, bool& hadContextSensitiveCondition, bool& hadLinkLanguageSensitiveCondition) const; diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index 5a90e7e..db44938 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -50,6 +50,9 @@ struct cmLinkImplementationLibraries // Libraries linked directly in this configuration. std::vector<cmLinkImplItem> Libraries; + // Object files linked directly in this configuration. + std::vector<cmLinkItem> Objects; + // Libraries linked directly in other configurations. // Needed only for OLD behavior of CMP0003. std::vector<cmLinkItem> WrongConfigLibraries; @@ -63,6 +66,9 @@ struct cmLinkInterfaceLibraries // Libraries listed in the interface. std::vector<cmLinkItem> Libraries; + // Object files listed in the interface. + std::vector<cmLinkItem> Objects; + // Whether the list depends on a genex referencing the head target. bool HadHeadSensitiveCondition = false; |