From 18e42d3e63f7807495be8fc4c2159629a30c1144 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 26 May 2021 10:36:07 -0400 Subject: cmGeneratorExpressionNode: Constify local variable --- Source/cmGeneratorExpressionNode.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 7125170..8030b64 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1681,7 +1681,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode // Create the cmSourceFile instances in the referencing directory. cmMakefile* mf = context->LG->GetMakefile(); - for (std::string& o : objects) { + for (std::string const& o : objects) { mf->AddTargetObject(tgtName, o); } -- cgit v0.12 From ddffbb8adbfb12ecc2ab920434006a40bfeae326 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 26 May 2021 10:37:03 -0400 Subject: cmMakefile: Register explicit object sources more efficiently `AddTargetObject` knows the location of object files. --- Source/cmMakefile.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index ffe94ba..908b3f0 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3454,7 +3454,8 @@ void cmMakefile::CreateGeneratedOutputs( void cmMakefile::AddTargetObject(std::string const& tgtName, std::string const& objFile) { - cmSourceFile* sf = this->GetOrCreateSource(objFile, true); + cmSourceFile* sf = + this->GetOrCreateSource(objFile, true, cmSourceFileLocationKind::Known); sf->SetObjectLibrary(tgtName); sf->SetProperty("EXTERNAL_OBJECT", "1"); #if !defined(CMAKE_BOOTSTRAP) -- cgit v0.12 From 96809a8541513c7adb52a65766154d417281227e Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 26 May 2021 10:43:47 -0400 Subject: cmGeneratorTarget: Give temporary link impl item an explicit name --- Source/cmGeneratorTarget.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index a7d825d..ca18f53 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -7490,8 +7490,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // The entry is meant for this configuration. - impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt, lg), - evaluated != *le); + cmLinkItem item = this->ResolveLinkItem(name, *btIt, lg); + impl.Libraries.emplace_back(std::move(item), evaluated != *le); } std::set const& seenProps = cge->GetSeenTargetProperties(); -- cgit v0.12 From 7f506b95a78a3238d3481539810441ca955a0901 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 26 May 2021 10:44:41 -0400 Subject: cmGeneratorTarget: Refactor link item lookup Look up items individually so the call sites can do something with the result besides appending to a vector. --- Source/cmGeneratorTarget.cxx | 37 ++++++++++++++++++++------------- Source/cmGeneratorTarget.h | 5 ++--- Source/cmTargetLinkLibrariesCommand.cxx | 2 +- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index ca18f53..51742cf 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6255,22 +6255,21 @@ bool cmGeneratorTarget::IsLinkLookupScope(std::string const& n, return false; } -void cmGeneratorTarget::LookupLinkItems(std::vector const& names, - cmListFileBacktrace const& bt, - std::vector& items) const +cm::optional cmGeneratorTarget::LookupLinkItem( + std::string const& n, cmListFileBacktrace const& bt) const { + cm::optional maybeItem; cmLocalGenerator const* lg = this->LocalGenerator; - for (std::string const& n : names) { - if (this->IsLinkLookupScope(n, lg)) { - continue; - } + if (this->IsLinkLookupScope(n, lg)) { + return maybeItem; + } - std::string name = this->CheckCMP0004(n); - if (name == this->GetName() || name.empty()) { - continue; - } - items.push_back(this->ResolveLinkItem(name, bt, lg)); + std::string name = this->CheckCMP0004(n); + if (name == this->GetName() || name.empty()) { + return maybeItem; } + maybeItem = this->ResolveLinkItem(name, bt, lg); + return maybeItem; } void cmGeneratorTarget::ExpandLinkItems( @@ -6295,7 +6294,12 @@ void cmGeneratorTarget::ExpandLinkItems( cmExpandList(cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker, this, headTarget->LinkerLanguage), libs); - this->LookupLinkItems(libs, cge->GetBacktrace(), items); + for (std::string const& lib : libs) { + if (cm::optional maybeItem = + this->LookupLinkItem(lib, cge->GetBacktrace())) { + items.emplace_back(std::move(*maybeItem)); + } + } hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); hadContextSensitiveCondition = cge->GetHadContextSensitiveCondition(); hadLinkLanguageSensitiveCondition = @@ -6903,7 +6907,12 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( iface.HadContextSensitiveCondition, iface.HadLinkLanguageSensitiveCondition); std::vector deps = cmExpandedList(info->SharedDeps); - this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps); + for (std::string const& dep : deps) { + if (cm::optional maybeItem = + this->LookupLinkItem(dep, cmListFileBacktrace())) { + iface.SharedDeps.emplace_back(std::move(*maybeItem)); + } + } } return &iface; diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 2935e0b..dbc47b8 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1039,9 +1039,8 @@ private: bool& hadHeadSensitiveCondition, bool& hadContextSensitiveCondition, bool& hadLinkLanguageSensitiveCondition) const; - void LookupLinkItems(std::vector const& names, - cmListFileBacktrace const& bt, - std::vector& items) const; + cm::optional LookupLinkItem(std::string const& n, + cmListFileBacktrace const& bt) const; std::vector> GetSourceFilePaths( std::string const& config) const; diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index aecc18e..3423b30 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -565,7 +565,7 @@ void TLL::AffectsProperty(std::string const& prop) if (!this->EncodeRemoteReference) { return; } - // Add a wrapper to the expression to tell LookupLinkItems to look up + // Add a wrapper to the expression to tell LookupLinkItem to look up // names in the caller's directory. if (this->Props.insert(prop).second) { this->Target->AppendProperty(prop, this->DirectoryId); -- cgit v0.12 From 83ad066ed10ccabc4331c4b620ad6a4fa0cd36ba Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 28 May 2021 14:58:11 -0400 Subject: cmComputeTargetDepends: Factor out helper to add object library dependency --- Source/cmComputeTargetDepends.cxx | 49 +++++++++++++++++++++++---------------- Source/cmComputeTargetDepends.h | 3 +++ 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 85a9d9c..0f23417 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -233,26 +233,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) std::vector objectFiles; depender->GetExternalObjects(objectFiles, it); for (cmSourceFile const* o : objectFiles) { - std::string const& objLib = o->GetObjectLibrary(); - if (!objLib.empty()) { - cmLinkItem const& objItem = - depender->ResolveLinkItem(objLib, cmListFileBacktrace()); - if (emitted.insert(objItem).second) { - if (depender->GetType() != cmStateEnums::EXECUTABLE && - depender->GetType() != cmStateEnums::STATIC_LIBRARY && - depender->GetType() != cmStateEnums::SHARED_LIBRARY && - depender->GetType() != cmStateEnums::MODULE_LIBRARY && - depender->GetType() != cmStateEnums::OBJECT_LIBRARY) { - this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - MessageType::FATAL_ERROR, - "Only executables and libraries may reference target objects.", - depender->GetBacktrace()); - return; - } - const_cast(depender)->Target->AddUtility( - objLib, false); - } - } + this->AddObjectDepends(depender_index, o, emitted); } } } @@ -319,6 +300,34 @@ void cmComputeTargetDepends::AddInterfaceDepends( } } +void cmComputeTargetDepends::AddObjectDepends(int depender_index, + cmSourceFile const* o, + std::set& emitted) +{ + std::string const& objLib = o->GetObjectLibrary(); + if (objLib.empty()) { + return; + } + cmGeneratorTarget const* depender = this->Targets[depender_index]; + cmLinkItem const& objItem = + depender->ResolveLinkItem(objLib, cmListFileBacktrace()); + if (emitted.insert(objItem).second) { + if (depender->GetType() != cmStateEnums::EXECUTABLE && + depender->GetType() != cmStateEnums::STATIC_LIBRARY && + depender->GetType() != cmStateEnums::SHARED_LIBRARY && + depender->GetType() != cmStateEnums::MODULE_LIBRARY && + depender->GetType() != cmStateEnums::OBJECT_LIBRARY) { + this->GlobalGenerator->GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + "Only executables and libraries may reference target objects.", + depender->GetBacktrace()); + return; + } + const_cast(depender)->Target->AddUtility(objLib, + false); + } +} + void cmComputeTargetDepends::AddTargetDepend(int depender_index, cmLinkItem const& dependee_name, bool linking, bool cross) diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index 3517844..0eab368 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -16,6 +16,7 @@ class cmComputeComponentGraph; class cmGeneratorTarget; class cmGlobalGenerator; class cmLinkItem; +class cmSourceFile; class cmTargetDependSet; /** \class cmComputeTargetDepends @@ -71,6 +72,8 @@ private: cmListFileBacktrace const& dependee_backtrace, const std::string& config, std::set& emitted); + void AddObjectDepends(int depender_index, cmSourceFile const* o, + std::set& emitted); cmGlobalGenerator* GlobalGenerator; bool DebugMode; bool NoCycles; -- cgit v0.12 From 8a4ca110e49c64c4892a37ffe08a91a5a5219acf Mon Sep 17 00:00:00 2001 From: Brad King Date: Sat, 29 May 2021 09:21:20 -0400 Subject: cmComputeLinkInformation: Improve type safety of item IsPath member Use an enum to avoid implicit conversions to bool. --- Source/cmComputeLinkInformation.cxx | 25 +++++++++++++------------ Source/cmComputeLinkInformation.h | 13 ++++++++++--- Source/cmGlobalXCodeGenerator.cxx | 8 +++++--- Source/cmLinkLineComputer.cxx | 2 +- Source/cmLinkLineDeviceComputer.cxx | 2 +- Source/cmLocalVisualStudio7Generator.cxx | 2 +- Source/cmVisualStudio10TargetGenerator.cxx | 7 ++++--- 7 files changed, 35 insertions(+), 24 deletions(-) diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 5473316..6371286 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -659,14 +659,14 @@ void cmComputeLinkInformation::AddItem(BT const& item, std::string exe = tgt->GetFullPath(config, artifact, true); linkItem += exe; - this->Items.emplace_back(BT(linkItem, item.Backtrace), true, - tgt); + this->Items.emplace_back(BT(linkItem, item.Backtrace), + ItemIsPath::Yes, tgt); this->Depends.push_back(std::move(exe)); } else if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { // Add the interface library as an item so it can be considered as part // of COMPATIBLE_INTERFACE_ enforcement. The generators will ignore // this for the actual link line. - this->Items.emplace_back(std::string(), false, tgt); + this->Items.emplace_back(std::string(), ItemIsPath::No, tgt); // Also add the item the interface specifies to be used in its place. std::string const& libName = tgt->GetImportedLibName(config); @@ -1038,10 +1038,10 @@ void cmComputeLinkInformation::SetCurrentLinkType(LinkType lt) if (this->LinkTypeEnabled) { switch (this->CurrentLinkType) { case LinkStatic: - this->Items.emplace_back(this->StaticLinkTypeFlag, false); + this->Items.emplace_back(this->StaticLinkTypeFlag, ItemIsPath::No); break; case LinkShared: - this->Items.emplace_back(this->SharedLinkTypeFlag, false); + this->Items.emplace_back(this->SharedLinkTypeFlag, ItemIsPath::No); break; default: break; @@ -1084,7 +1084,7 @@ void cmComputeLinkInformation::AddTargetItem(BT const& item, } // Now add the full path to the library. - this->Items.emplace_back(item, true, target); + this->Items.emplace_back(item, ItemIsPath::Yes, target); } void cmComputeLinkInformation::AddFullItem(BT const& item) @@ -1138,7 +1138,7 @@ void cmComputeLinkInformation::AddFullItem(BT const& item) } // Now add the full path to the library. - this->Items.emplace_back(item, true); + this->Items.emplace_back(item, ItemIsPath::Yes); } bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) @@ -1226,7 +1226,7 @@ void cmComputeLinkInformation::AddUserItem(BT const& item, this->SetCurrentLinkType(this->StartLinkType); // Use the item verbatim. - this->Items.emplace_back(item, false); + this->Items.emplace_back(item, ItemIsPath::No); return; } @@ -1296,7 +1296,8 @@ void cmComputeLinkInformation::AddUserItem(BT const& item, // Create an option to ask the linker to search for the library. std::string out = cmStrCat(this->LibLinkFlag, lib, this->LibLinkSuffix); - this->Items.emplace_back(BT(out, item.Backtrace), false); + this->Items.emplace_back(BT(out, item.Backtrace), + ItemIsPath::No); // Here we could try to find the library the linker will find and // add a runtime information entry for it. It would probably not be @@ -1328,13 +1329,13 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item) if (this->GlobalGenerator->IsXcode()) { // Add framework path - it will be handled by Xcode after it's added to // "Link Binary With Libraries" build phase - this->Items.emplace_back(item, true); + this->Items.emplace_back(item, ItemIsPath::Yes); } else { // Add the item using the -framework option. - this->Items.emplace_back(std::string("-framework"), false); + this->Items.emplace_back(std::string("-framework"), ItemIsPath::No); cmOutputConverter converter(this->Makefile->GetStateSnapshot()); fw = converter.EscapeForShell(fw); - this->Items.emplace_back(fw, false); + this->Items.emplace_back(fw, ItemIsPath::No); } } diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 4acb99f..9afa0eb 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -35,17 +35,24 @@ public: ~cmComputeLinkInformation(); bool Compute(); + enum class ItemIsPath + { + No, + Yes, + }; + struct Item { Item() = default; - Item(BT v, bool p, cmGeneratorTarget const* target = nullptr) + Item(BT v, ItemIsPath isPath, + cmGeneratorTarget const* target = nullptr) : Value(std::move(v)) - , IsPath(p) + , IsPath(isPath) , Target(target) { } BT Value; - bool IsPath = true; + ItemIsPath IsPath = ItemIsPath::Yes; cmGeneratorTarget const* Target = nullptr; }; using ItemVector = std::vector; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 009d133..693a11c 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3454,7 +3454,9 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) libItem.Target->GetType() == cmStateEnums::SHARED_LIBRARY || libItem.Target->GetType() == cmStateEnums::MODULE_LIBRARY || libItem.Target->GetType() == cmStateEnums::UNKNOWN_LIBRARY)) || - (!libItem.Target && libItem.IsPath && forceLinkPhase))) { + (!libItem.Target && + libItem.IsPath == cmComputeLinkInformation::ItemIsPath::Yes && + forceLinkPhase))) { std::string libName; bool canUseLinkPhase = true; if (libItem.Target) { @@ -3565,7 +3567,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) auto* libTarget = FindXCodeTarget(libItem->Target); cmXCodeObject* buildFile; if (!libTarget) { - if (libItem->IsPath) { + if (libItem->IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { // Get or create a direct file ref in the root project auto cleanPath = libItem->Value.Value; if (cmSystemTools::FileIsFullPath(cleanPath)) { @@ -3724,7 +3726,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) BuildObjectListOrString libPaths(this, true); for (auto const& libItem : configItemMap[configName]) { auto const& libName = *libItem; - if (libName.IsPath) { + if (libName.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { auto cleanPath = libName.Value.Value; if (cmSystemTools::FileIsFullPath(cleanPath)) { cleanPath = cmSystemTools::CollapseFullPath(cleanPath); diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index a3f2968..6eb8d75 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -74,7 +74,7 @@ void cmLinkLineComputer::ComputeLinkLibs( } BT linkLib; - if (item.IsPath) { + if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { linkLib.Value += cli.GetLibLinkFileFlag(); linkLib.Value += this->ConvertToOutputFormat( this->ConvertToLinkReference(item.Value.Value)); diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 9cae926..2ffff96 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -111,7 +111,7 @@ void cmLinkLineDeviceComputer::ComputeLinkLibraries( } BT linkLib; - if (item.IsPath) { + if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { // nvcc understands absolute paths to libraries ending in '.a' or '.lib'. // These should be passed to nvlink. Other extensions need to be left // out because nvlink may not understand or need them. Even though it diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index c50cc5d..151470b 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1254,7 +1254,7 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries( { cmLocalVisualStudio7Generator* lg = this->LocalGenerator; for (auto const& lib : libs) { - if (lib.IsPath) { + if (lib.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { std::string rel = lg->MaybeRelativeToCurBinDir(lib.Value.Value); fout << lg->ConvertToXMLOutputPath(rel) << " "; } else if (!lib.Target || diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 1c8b672..98d56df 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -3391,7 +3391,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( } } - if (l.IsPath) { + if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { std::string path = this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value); ConvertToWindowsSlash(path); @@ -3945,7 +3945,8 @@ bool cmVisualStudio10TargetGenerator::ComputeLibOptions( using ItemVector = cmComputeLinkInformation::ItemVector; const ItemVector& libs = cli.GetItems(); for (cmComputeLinkInformation::Item const& l : libs) { - if (l.IsPath && cmVS10IsTargetsFile(l.Value.Value)) { + if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes && + cmVS10IsTargetsFile(l.Value.Value)) { std::string path = this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value); ConvertToWindowsSlash(path); @@ -4028,7 +4029,7 @@ void cmVisualStudio10TargetGenerator::AddLibraries( } } - if (l.IsPath) { + if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { std::string path = this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value); ConvertToWindowsSlash(path); -- cgit v0.12 From f530b3a26729d0820c804e312b72e0061d6eeb4b Mon Sep 17 00:00:00 2001 From: Brad King Date: Sat, 29 May 2021 08:26:45 -0400 Subject: OpenWatcom: Add infrastructure to link to object files --- Modules/Compiler/OpenWatcom.cmake | 1 + Source/cmComputeLinkDepends.h | 1 + Source/cmComputeLinkInformation.cxx | 27 +++++++++++++++++++-------- Source/cmComputeLinkInformation.h | 20 ++++++++++++++++++-- Source/cmLinkLineComputer.cxx | 6 +++++- 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/Modules/Compiler/OpenWatcom.cmake b/Modules/Compiler/OpenWatcom.cmake index ec36908..8cfe683 100644 --- a/Modules/Compiler/OpenWatcom.cmake +++ b/Modules/Compiler/OpenWatcom.cmake @@ -7,6 +7,7 @@ include_guard() set(CMAKE_LIBRARY_PATH_FLAG "libpath ") set(CMAKE_LINK_LIBRARY_FLAG "library ") set(CMAKE_LINK_LIBRARY_FILE_FLAG "library ") +set(CMAKE_LINK_OBJECT_FILE_FLAG "file ") if(CMAKE_VERBOSE_MAKEFILE) set(CMAKE_WCL_QUIET) diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 902500a..00fbd59 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -42,6 +42,7 @@ public: cmGeneratorTarget const* Target = nullptr; bool IsSharedDep = false; bool IsFlag = false; + bool IsObject = false; }; using EntryVector = std::vector; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 6371286..2647998 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -309,6 +309,13 @@ cmComputeLinkInformation::cmComputeLinkInformation( this->LibLinkSuffix = this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX"); } + if (cmProp flag = this->Makefile->GetDefinition( + "CMAKE_" + this->LinkLanguage + "_LINK_OBJECT_FILE_FLAG")) { + this->ObjLinkFileFlag = *flag; + } else { + this->ObjLinkFileFlag = + this->Makefile->GetSafeDefinition("CMAKE_LINK_OBJECT_FILE_FLAG"); + } // Get options needed to specify RPATHs. this->RuntimeUseChrpath = false; @@ -514,7 +521,8 @@ bool cmComputeLinkInformation::Compute() if (linkEntry.IsSharedDep) { this->AddSharedDepItem(linkEntry.Item, linkEntry.Target); } else { - this->AddItem(linkEntry.Item, linkEntry.Target); + this->AddItem(linkEntry.Item, linkEntry.Target, + linkEntry.IsObject ? ItemIsObject::Yes : ItemIsObject::No); } } @@ -634,7 +642,8 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) } void cmComputeLinkInformation::AddItem(BT const& item, - cmGeneratorTarget const* tgt) + cmGeneratorTarget const* tgt, + ItemIsObject isObject) { // Compute the proper name to use to link this library. const std::string& config = this->Config; @@ -660,13 +669,14 @@ void cmComputeLinkInformation::AddItem(BT const& item, std::string exe = tgt->GetFullPath(config, artifact, true); linkItem += exe; this->Items.emplace_back(BT(linkItem, item.Backtrace), - ItemIsPath::Yes, tgt); + ItemIsPath::Yes, ItemIsObject::No, tgt); this->Depends.push_back(std::move(exe)); } else if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { // Add the interface library as an item so it can be considered as part // of COMPATIBLE_INTERFACE_ enforcement. The generators will ignore // this for the actual link line. - this->Items.emplace_back(std::string(), ItemIsPath::No, tgt); + this->Items.emplace_back(std::string(), ItemIsPath::No, ItemIsObject::No, + tgt); // Also add the item the interface specifies to be used in its place. std::string const& libName = tgt->GetImportedLibName(config); @@ -719,7 +729,7 @@ void cmComputeLinkInformation::AddItem(BT const& item, } else { // Use the full path given to the library file. this->Depends.push_back(item.Value); - this->AddFullItem(item); + this->AddFullItem(item, isObject); this->AddLibraryRuntimeInfo(item.Value); } } else { @@ -1084,10 +1094,11 @@ void cmComputeLinkInformation::AddTargetItem(BT const& item, } // Now add the full path to the library. - this->Items.emplace_back(item, ItemIsPath::Yes, target); + this->Items.emplace_back(item, ItemIsPath::Yes, ItemIsObject::No, target); } -void cmComputeLinkInformation::AddFullItem(BT const& item) +void cmComputeLinkInformation::AddFullItem(BT const& item, + ItemIsObject isObject) { // Check for the implicit link directory special case. if (this->CheckImplicitDirItem(item.Value)) { @@ -1138,7 +1149,7 @@ void cmComputeLinkInformation::AddFullItem(BT const& item) } // Now add the full path to the library. - this->Items.emplace_back(item, ItemIsPath::Yes); + this->Items.emplace_back(item, ItemIsPath::Yes, isObject); } bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 9afa0eb..7fe30b3 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -41,18 +41,27 @@ public: Yes, }; + enum class ItemIsObject + { + No, + Yes, + }; + struct Item { Item() = default; Item(BT v, ItemIsPath isPath, + ItemIsObject isObject = ItemIsObject::No, cmGeneratorTarget const* target = nullptr) : Value(std::move(v)) , IsPath(isPath) + , IsObject(isObject) , Target(target) { } BT Value; ItemIsPath IsPath = ItemIsPath::Yes; + ItemIsObject IsObject = ItemIsObject::No; cmGeneratorTarget const* Target = nullptr; }; using ItemVector = std::vector; @@ -81,6 +90,11 @@ public: return this->LibLinkFileFlag; } + std::string const& GetObjLinkFileFlag() const + { + return this->ObjLinkFileFlag; + } + std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; } std::string GetRPathLinkString() const; @@ -89,7 +103,8 @@ public: const cmGeneratorTarget* GetTarget() { return this->Target; } private: - void AddItem(BT const& item, const cmGeneratorTarget* tgt); + void AddItem(BT const& item, const cmGeneratorTarget* tgt, + ItemIsObject isObject = ItemIsObject::No); void AddSharedDepItem(BT const& item, cmGeneratorTarget const* tgt); void AddRuntimeDLL(cmGeneratorTarget const* tgt); @@ -125,6 +140,7 @@ private: const char* LoaderFlag; std::string LibLinkFlag; std::string LibLinkFileFlag; + std::string ObjLinkFileFlag; std::string LibLinkSuffix; std::string RuntimeFlag; std::string RuntimeSep; @@ -166,7 +182,7 @@ private: // Handling of link items. void AddTargetItem(BT const& item, const cmGeneratorTarget* target); - void AddFullItem(BT const& item); + void AddFullItem(BT const& item, ItemIsObject isObject); bool CheckImplicitDirItem(std::string const& item); void AddUserItem(BT const& item, bool pathNotKnown); void AddFrameworkItem(std::string const& item); diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 6eb8d75..5646368 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -75,7 +75,11 @@ void cmLinkLineComputer::ComputeLinkLibs( BT linkLib; if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { - linkLib.Value += cli.GetLibLinkFileFlag(); + if (item.IsObject == cmComputeLinkInformation::ItemIsObject::Yes) { + linkLib.Value += cli.GetObjLinkFileFlag(); + } else { + linkLib.Value += cli.GetLibLinkFileFlag(); + } linkLib.Value += this->ConvertToOutputFormat( this->ConvertToLinkReference(item.Value.Value)); linkLib.Backtrace = item.Value.Backtrace; -- cgit v0.12 From 3941555d935afad8343c66f39579bfc611201a6f Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 26 May 2021 10:56:10 -0400 Subject: target_link_libraries: Place $ 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 --- Help/command/target_link_libraries.rst | 85 ++++++++++++++++++++++++++ Help/release/dev/link-objects-first.rst | 8 +++ Source/cmComputeLinkDepends.cxx | 36 +++++++++++ Source/cmComputeLinkDepends.h | 5 ++ Source/cmComputeTargetDepends.cxx | 13 ++++ Source/cmGeneratorTarget.cxx | 38 ++++++++++-- Source/cmGeneratorTarget.h | 1 + Source/cmLinkItem.h | 6 ++ Tests/ObjectLibrary/CMakeLists.txt | 2 + Tests/ObjectLibrary/LinkObjects/CMakeLists.txt | 45 ++++++++++++++ Tests/ObjectLibrary/LinkObjects/a_dep.c | 7 +++ Tests/ObjectLibrary/LinkObjects/a_obj.c | 8 +++ Tests/ObjectLibrary/LinkObjects/b_dep.c | 7 +++ Tests/ObjectLibrary/LinkObjects/b_obj.c | 8 +++ Tests/ObjectLibrary/LinkObjects/c_dep.c | 7 +++ Tests/ObjectLibrary/LinkObjects/c_obj.c | 8 +++ Tests/ObjectLibrary/LinkObjects/d_dep.c | 7 +++ Tests/ObjectLibrary/LinkObjects/d_obj.c | 8 +++ Tests/ObjectLibrary/LinkObjects/e_dep.c | 7 +++ Tests/ObjectLibrary/LinkObjects/e_lib.c | 5 ++ Tests/ObjectLibrary/LinkObjects/e_obj.c | 8 +++ Tests/ObjectLibrary/LinkObjects/main.c | 24 ++++++++ 22 files changed, 338 insertions(+), 5 deletions(-) create mode 100644 Help/release/dev/link-objects-first.rst create mode 100644 Tests/ObjectLibrary/LinkObjects/CMakeLists.txt create mode 100644 Tests/ObjectLibrary/LinkObjects/a_dep.c create mode 100644 Tests/ObjectLibrary/LinkObjects/a_obj.c create mode 100644 Tests/ObjectLibrary/LinkObjects/b_dep.c create mode 100644 Tests/ObjectLibrary/LinkObjects/b_obj.c create mode 100644 Tests/ObjectLibrary/LinkObjects/c_dep.c create mode 100644 Tests/ObjectLibrary/LinkObjects/c_obj.c create mode 100644 Tests/ObjectLibrary/LinkObjects/d_dep.c create mode 100644 Tests/ObjectLibrary/LinkObjects/d_obj.c create mode 100644 Tests/ObjectLibrary/LinkObjects/e_dep.c create mode 100644 Tests/ObjectLibrary/LinkObjects/e_lib.c create mode 100644 Tests/ObjectLibrary/LinkObjects/e_obj.c create mode 100644 Tests/ObjectLibrary/LinkObjects/main.c diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst index 872e264..ac231bc 100644 --- a/Help/command/target_link_libraries.rst +++ b/Help/command/target_link_libraries.rst @@ -289,6 +289,91 @@ treated as :ref:`Interface Libraries`, but when they appear in a target's :prop_tgt:`LINK_LIBRARIES` property their object files will be included in the link too. +.. _`Linking Object Libraries via $`: + +Linking Object Libraries via $ +"""""""""""""""""""""""""""""""""""""""""""""" + +.. versionadded:: 3.21 + +The object files associated with an object library may be referenced +by the :genex:`$` generator expression. Such object +files are placed on the link line *before* all libraries, regardless +of their relative order. Additionally, an ordering dependency will be +added to the build sysstem to make sure the object library is up-to-date +before the dependent target links. For example, the code + +.. code-block:: cmake + + add_library(obj3 OBJECT obj3.c) + target_compile_definitions(obj3 PUBLIC OBJ3) + + add_executable(main3 main3.c) + target_link_libraries(main3 PRIVATE a3 $ b3) + +links executable ``main3`` with object files from ``main3.c`` +and ``obj3.c`` followed by the ``a3`` and ``b3`` libraries. +``main3.c`` is *not* compiled with usage requirements from ``obj3``, +such as ``-DOBJ3``. + +This approach can be used to achieve transitive inclusion of object +files in link lines as usage requirements. Continuing the above +example, the code + +.. code-block:: cmake + + add_library(iface_obj3 INTERFACE) + target_link_libraries(iface_obj3 INTERFACE obj3 $) + +creates an interface library ``iface_obj3`` that forwards the ``obj3`` +usage requirements and adds the ``obj3`` object files to dependents' +link lines. The code + +.. code-block:: cmake + + add_executable(use_obj3 use_obj3.c) + target_link_libraries(use_obj3 PRIVATE iface_obj3) + +compiles ``use_obj3.c`` with ``-DOBJ3`` and links executable ``use_obj3`` +with object files from ``use_obj3.c`` and ``obj3.c``. + +This also works transitively through a static library. Since a static +library does not link, it does not consume the object files from +object libraries referenced this way. Instead, the object files +become transitive link dependencies of the static library. +Continuing the above example, the code + +.. code-block:: cmake + + add_library(static3 STATIC static3.c) + target_link_libraries(static3 PRIVATE iface_obj3) + + add_executable(use_static3 use_static3.c) + target_link_libraries(use_static3 PRIVATE static3) + +compiles ``static3.c`` with ``-DOBJ3`` and creates ``libstatic3.a`` +using only its own object file. ``use_static3.c`` is compiled *without* +``-DOBJ3`` because the usage requirement is not transitive through +the private dependency of ``static3``. However, the link dependencies +of ``static3`` are propagated, including the ``iface_obj3`` reference +to ``$``. The ``use_static3`` executable is +created with object files from ``use_static3.c`` and ``obj3.c``, and +linked to library ``libstatic3.a``. + +When using this approach, it is the project's responsibility to avoid +linking multiple dependent binaries to ``iface_obj3``, because they will +all get the ``obj3`` object files on their link lines. + +.. note:: + + Referencing :genex:`$` in ``target_link_libraries`` + calls worked in versions of CMake prior to 3.21 for some cases, + but was not fully supported: + + * It did not place the object files before libraries on link lines. + * It did not add an ordering dependency on the object library. + * It did not work in Xcode with multiple architectures. + Cyclic Dependencies of Static Libraries ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/release/dev/link-objects-first.rst b/Help/release/dev/link-objects-first.rst new file mode 100644 index 0000000..0c622e7 --- /dev/null +++ b/Help/release/dev/link-objects-first.rst @@ -0,0 +1,8 @@ +link-objects-first +------------------ + +* :command:`target_link_libraries` calls referencing object libraries + via the :genex:`TARGET_OBJECTS` generator expression now place the + object files before all libraries on the link line, regardless of + their specified order. See documentation on + :ref:`Linking Object Libraries via \$\` for details. 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(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 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::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 void AddLinkEntries(int depender_index, std::vector const& libs); + void AddLinkObjects(std::vector const& objs); cmLinkItem ResolveLinkItem(int depender_index, const std::string& name); // One entry for each unique item. @@ -154,6 +156,9 @@ private: std::set OldWrongConfigItems; void CheckWrongConfigItem(cmLinkItem const& item); + // Record of explicitly linked object files. + std::vector 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 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& items, bool& hadHeadSensitiveCondition, - bool& hadContextSensitiveCondition, + std::vector& items, std::vector& 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 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 ifaceLibs; + std::vector 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 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& items, + std::vector& 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 Libraries; + // Object files linked directly in this configuration. + std::vector Objects; + // Libraries linked directly in other configurations. // Needed only for OLD behavior of CMP0003. std::vector WrongConfigLibraries; @@ -63,6 +66,9 @@ struct cmLinkInterfaceLibraries // Libraries listed in the interface. std::vector Libraries; + // Object files listed in the interface. + std::vector Objects; + // Whether the list depends on a genex referencing the head target. bool HadHeadSensitiveCondition = false; diff --git a/Tests/ObjectLibrary/CMakeLists.txt b/Tests/ObjectLibrary/CMakeLists.txt index 74f34e4..06167a8 100644 --- a/Tests/ObjectLibrary/CMakeLists.txt +++ b/Tests/ObjectLibrary/CMakeLists.txt @@ -74,4 +74,6 @@ target_link_libraries(UseABstaticObjs ABstatic) add_subdirectory(ExportLanguages) +add_subdirectory(LinkObjects) + add_subdirectory(Transitive) diff --git a/Tests/ObjectLibrary/LinkObjects/CMakeLists.txt b/Tests/ObjectLibrary/LinkObjects/CMakeLists.txt new file mode 100644 index 0000000..899be45 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/CMakeLists.txt @@ -0,0 +1,45 @@ +add_executable(LinkObjects main.c) + +# Link TARGET_OBJECTS through LINK_LIBRARIES. +add_library(LinkObjectsAObj OBJECT a_obj.c) +add_library(LinkObjectsADep STATIC a_dep.c) +target_compile_definitions(LinkObjectsAObj PUBLIC OBJA) +target_link_libraries(LinkObjects PRIVATE LinkObjectsADep $) + +# Link TARGET_OBJECTS through INTERFACE_LINK_LIBRARIES with usage requirements. +add_library(LinkObjectsB INTERFACE) +add_library(LinkObjectsBObj OBJECT b_obj.c) +add_library(LinkObjectsBDep STATIC b_dep.c) +target_compile_definitions(LinkObjectsBObj PUBLIC OBJB) +target_link_libraries(LinkObjectsB INTERFACE LinkObjectsBObj $) +target_link_libraries(LinkObjectsBObj PRIVATE LinkObjectsBDep) +target_link_libraries(LinkObjects PRIVATE LinkObjectsB) + +# Link TARGET_OBJECTS through INTERFACE_LINK_LIBRARIES without usage requirements. +add_library(LinkObjectsC INTERFACE) +add_library(LinkObjectsCObj OBJECT c_obj.c) +add_library(LinkObjectsCDep STATIC c_dep.c) +target_compile_definitions(LinkObjectsCObj PUBLIC OBJC) +target_link_libraries(LinkObjectsC INTERFACE LinkObjectsCDep $) +target_link_libraries(LinkObjectsCObj PRIVATE LinkObjectsCDep) +target_link_libraries(LinkObjects PRIVATE LinkObjectsC) + +# Link TARGET_OBJECTS through both LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES, deduplicated. +add_library(LinkObjectsD INTERFACE) +add_library(LinkObjectsDObj OBJECT d_obj.c) +add_library(LinkObjectsDDep STATIC d_dep.c) +target_compile_definitions(LinkObjectsDObj PUBLIC OBJD) +target_link_libraries(LinkObjectsD INTERFACE LinkObjectsDObj $) +target_link_libraries(LinkObjectsDObj PRIVATE LinkObjectsDDep) +target_link_libraries(LinkObjects PRIVATE $ LinkObjectsD) + +# Link TARGET_OBJECTS through STATIC library private dependency. +add_library(LinkObjectsE INTERFACE) +add_library(LinkObjectsEObj OBJECT e_obj.c) +add_library(LinkObjectsEDep STATIC e_dep.c) +add_library(LinkObjectsEStatic STATIC e_lib.c) +target_compile_definitions(LinkObjectsEObj PUBLIC OBJE) +target_link_libraries(LinkObjectsE INTERFACE LinkObjectsEObj $) +target_link_libraries(LinkObjectsEObj PRIVATE LinkObjectsEDep) +target_link_libraries(LinkObjectsEStatic PRIVATE LinkObjectsE) +target_link_libraries(LinkObjects PRIVATE LinkObjectsEStatic) diff --git a/Tests/ObjectLibrary/LinkObjects/a_dep.c b/Tests/ObjectLibrary/LinkObjects/a_dep.c new file mode 100644 index 0000000..0128740 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/a_dep.c @@ -0,0 +1,7 @@ +#ifdef OBJA +# error "OBJA is defined, but should not be" +#endif +int a_dep(void) +{ + return 0; +} diff --git a/Tests/ObjectLibrary/LinkObjects/a_obj.c b/Tests/ObjectLibrary/LinkObjects/a_obj.c new file mode 100644 index 0000000..5e79c60 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/a_obj.c @@ -0,0 +1,8 @@ +#ifndef OBJA +# error "OBJA is not defined, but should be" +#endif +extern int a_dep(void); +int a_obj(void) +{ + return a_dep(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/b_dep.c b/Tests/ObjectLibrary/LinkObjects/b_dep.c new file mode 100644 index 0000000..ad5d367 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/b_dep.c @@ -0,0 +1,7 @@ +#ifdef OBJB +# error "OBJB is defined, but should not be" +#endif +int b_dep(void) +{ + return 0; +} diff --git a/Tests/ObjectLibrary/LinkObjects/b_obj.c b/Tests/ObjectLibrary/LinkObjects/b_obj.c new file mode 100644 index 0000000..d0f426a --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/b_obj.c @@ -0,0 +1,8 @@ +#ifndef OBJB +# error "OBJB is not defined, but should be" +#endif +extern int b_dep(void); +int b_obj(void) +{ + return b_dep(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/c_dep.c b/Tests/ObjectLibrary/LinkObjects/c_dep.c new file mode 100644 index 0000000..1d99ab8 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/c_dep.c @@ -0,0 +1,7 @@ +#ifdef OBJC +# error "OBJC is defined, but should not be" +#endif +int c_dep(void) +{ + return 0; +} diff --git a/Tests/ObjectLibrary/LinkObjects/c_obj.c b/Tests/ObjectLibrary/LinkObjects/c_obj.c new file mode 100644 index 0000000..08fa5f5 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/c_obj.c @@ -0,0 +1,8 @@ +#ifndef OBJC +# error "OBJC is not defined, but should be" +#endif +extern int c_dep(void); +int c_obj(void) +{ + return c_dep(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/d_dep.c b/Tests/ObjectLibrary/LinkObjects/d_dep.c new file mode 100644 index 0000000..cf09314 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/d_dep.c @@ -0,0 +1,7 @@ +#ifdef OBJD +# error "OBJD is defined, but should not be" +#endif +int d_dep(void) +{ + return 0; +} diff --git a/Tests/ObjectLibrary/LinkObjects/d_obj.c b/Tests/ObjectLibrary/LinkObjects/d_obj.c new file mode 100644 index 0000000..d14ce66 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/d_obj.c @@ -0,0 +1,8 @@ +#ifndef OBJD +# error "OBJD is not defined, but should be" +#endif +extern int d_dep(void); +int d_obj(void) +{ + return d_dep(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/e_dep.c b/Tests/ObjectLibrary/LinkObjects/e_dep.c new file mode 100644 index 0000000..7fb70c1 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/e_dep.c @@ -0,0 +1,7 @@ +#ifdef OBJE +# error "OBJE is defined, but should not be" +#endif +int e_dep(void) +{ + return 0; +} diff --git a/Tests/ObjectLibrary/LinkObjects/e_lib.c b/Tests/ObjectLibrary/LinkObjects/e_lib.c new file mode 100644 index 0000000..9bb3a44 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/e_lib.c @@ -0,0 +1,5 @@ +extern int e_obj(void); +int e_lib(void) +{ + return e_obj(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/e_obj.c b/Tests/ObjectLibrary/LinkObjects/e_obj.c new file mode 100644 index 0000000..02624eb --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/e_obj.c @@ -0,0 +1,8 @@ +#ifndef OBJE +# error "OBJE is not defined, but should be" +#endif +extern int e_dep(void); +int e_obj(void) +{ + return e_dep(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/main.c b/Tests/ObjectLibrary/LinkObjects/main.c new file mode 100644 index 0000000..c09c4f1 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/main.c @@ -0,0 +1,24 @@ +#ifdef OBJA +# error "OBJA is defined, but should not be" +#endif +#ifndef OBJB +# error "OBJB is not defined, but should be" +#endif +#ifdef OBJC +# error "OBJC is defined, but should not be" +#endif +#ifndef OBJD +# error "OBJD is not defined, but should be" +#endif +#ifdef OBJE +# error "OBJE is defined, but should not be" +#endif +extern int a_obj(void); +extern int b_obj(void); +extern int c_obj(void); +extern int d_obj(void); +extern int e_lib(void); +int main(void) +{ + return a_obj() + b_obj() + c_obj() + d_obj() + e_lib(); +} -- cgit v0.12