From e109307c43c610e18e6ece6c67aea55dd47a8ac4 Mon Sep 17 00:00:00 2001 From: Vito Gamberini Date: Tue, 14 Jan 2025 11:23:34 -0500 Subject: [PATCH] Add support for foreign targets --- Source/cmAddExecutableCommand.cxx | 3 +- Source/cmAddLibraryCommand.cxx | 3 +- Source/cmGeneratorTarget.cxx | 8 ++++- Source/cmGeneratorTarget.h | 1 + Source/cmGeneratorTarget_Link.cxx | 3 +- Source/cmGlobalGenerator.cxx | 24 ++++++++++----- Source/cmGlobalGenerator.h | 8 +++-- Source/cmInstallCommand.cxx | 6 ++-- Source/cmMakefile.cxx | 39 ++++++++++++++++++++----- Source/cmMakefile.h | 7 ++++- Source/cmStateTypes.h | 18 ++++++++++++ Source/cmTarget.cxx | 19 ++++++++++++ Source/cmTarget.h | 2 ++ Source/cmTargetLinkLibrariesCommand.cxx | 3 +- 14 files changed, 119 insertions(+), 25 deletions(-) diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx index 16a89651f2..545fda0f3e 100644 --- a/Source/cmAddExecutableCommand.cxx +++ b/Source/cmAddExecutableCommand.cxx @@ -107,7 +107,8 @@ bool cmAddExecutableCommand(std::vector const& args, "\" is itself an ALIAS.")); return false; } - cmTarget* aliasedTarget = mf.FindTargetToUse(aliasedName, true); + cmTarget* aliasedTarget = + mf.FindTargetToUse(aliasedName, { cmStateEnums::TargetDomain::NATIVE }); if (!aliasedTarget) { status.SetError(cmStrCat("cannot create ALIAS target \"", exename, "\" because target \"", aliasedName, diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index e2a52d13ea..84362d66e4 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -189,7 +189,8 @@ bool cmAddLibraryCommand(std::vector const& args, "\" is itself an ALIAS.")); return false; } - cmTarget* aliasedTarget = mf.FindTargetToUse(aliasedName, true); + cmTarget* aliasedTarget = + mf.FindTargetToUse(aliasedName, { cmStateEnums::TargetDomain::NATIVE }); if (!aliasedTarget) { status.SetError(cmStrCat("cannot create ALIAS target \"", libName, "\" because target \"", aliasedName, diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 20d32eb74f..961c642295 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1149,6 +1149,11 @@ bool cmGeneratorTarget::IsImportedGloballyVisible() const return this->Target->IsImportedGloballyVisible(); } +bool cmGeneratorTarget::IsForeign() const +{ + return this->Target->IsForeign(); +} + bool cmGeneratorTarget::CanCompileSources() const { return this->Target->CanCompileSources(); @@ -5396,7 +5401,8 @@ bool cmGeneratorTarget::AddHeaderSetVerification() cmTarget* verifyTarget = nullptr; cmTarget* allVerifyTarget = this->GlobalGenerator->GetMakefiles().front()->FindTargetToUse( - "all_verify_interface_header_sets", true); + "all_verify_interface_header_sets", + { cmStateEnums::TargetDomain::NATIVE }); auto interfaceFileSetEntries = this->Target->GetInterfaceHeaderSetsEntries(); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index f2ff038ffc..43ff76cc6f 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -60,6 +60,7 @@ public: bool IsSynthetic() const; bool IsImported() const; bool IsImportedGloballyVisible() const; + bool IsForeign() const; bool CanCompileSources() const; bool HasKnownRuntimeArtifactLocation(std::string const& config) const; const std::string& GetLocation(const std::string& config) const; diff --git a/Source/cmGeneratorTarget_Link.cxx b/Source/cmGeneratorTarget_Link.cxx index 92e5ddf4fe..8bb5848aa5 100644 --- a/Source/cmGeneratorTarget_Link.cxx +++ b/Source/cmGeneratorTarget_Link.cxx @@ -1362,7 +1362,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( std::string name = this->CheckCMP0004(lib); if (this->GetPolicyStatusCMP0108() == cmPolicies::NEW) { // resolve alias name - auto* target = this->Makefile->FindTargetToUse(name); + auto* target = this->Makefile->FindTargetToUse( + name, cmStateEnums::AllTargetDomains); if (target) { name = target->GetName(); } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 2f963c5c8d..e22f9819ca 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1929,7 +1929,8 @@ bool cmGlobalGenerator::AddHeaderSetVerification() } cmTarget* allVerifyTarget = this->Makefiles.front()->FindTargetToUse( - "all_verify_interface_header_sets", true); + "all_verify_interface_header_sets", + { cmStateEnums::TargetDomain::NATIVE }); if (allVerifyTarget) { this->LocalGenerators.front()->AddGeneratorTarget( cm::make_unique(allVerifyTarget, @@ -2671,11 +2672,18 @@ void cmGlobalGenerator::IndexLocalGenerator(cmLocalGenerator* lg) this->LocalGeneratorSearchIndex[id.String] = lg; } -cmTarget* cmGlobalGenerator::FindTargetImpl(std::string const& name) const +cmTarget* cmGlobalGenerator::FindTargetImpl( + std::string const& name, cmStateEnums::TargetDomainSet domains) const { + bool const useForeign = + domains.contains(cmStateEnums::TargetDomain::FOREIGN); + bool const useNative = domains.contains(cmStateEnums::TargetDomain::NATIVE); + auto const it = this->TargetSearchIndex.find(name); if (it != this->TargetSearchIndex.end()) { - return it->second; + if (it->second->IsForeign() ? useForeign : useNative) { + return it->second; + } } return nullptr; } @@ -2690,16 +2698,16 @@ cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTargetImpl( return nullptr; } -cmTarget* cmGlobalGenerator::FindTarget(const std::string& name, - bool excludeAliases) const +cmTarget* cmGlobalGenerator::FindTarget( + const std::string& name, cmStateEnums::TargetDomainSet domains) const { - if (!excludeAliases) { + if (domains.contains(cmStateEnums::TargetDomain::ALIAS)) { auto const ai = this->AliasTargets.find(name); if (ai != this->AliasTargets.end()) { - return this->FindTargetImpl(ai->second); + return this->FindTargetImpl(ai->second, domains); } } - return this->FindTargetImpl(name); + return this->FindTargetImpl(name, domains); } cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTarget( diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 7f07c1cfd2..23d32587fd 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -25,6 +25,7 @@ #include "cmExportSet.h" #include "cmLocalGenerator.h" #include "cmStateSnapshot.h" +#include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -380,7 +381,9 @@ public: //! Find a target by name by searching the local generators. cmTarget* FindTarget(const std::string& name, - bool excludeAliases = false) const; + cmStateEnums::TargetDomainSet domains = { + cmStateEnums::TargetDomain::NATIVE, + cmStateEnums::TargetDomain::ALIAS }) const; cmGeneratorTarget* FindGeneratorTarget(const std::string& name) const; @@ -783,7 +786,8 @@ protected: std::map AliasTargets; - cmTarget* FindTargetImpl(std::string const& name) const; + cmTarget* FindTargetImpl(std::string const& name, + cmStateEnums::TargetDomainSet domains) const; cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const; diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 7f5a22b867..39c289d194 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -711,7 +711,8 @@ bool HandleTargetsMode(std::vector const& args, if (!target) { // If no local target has been found, find it in the global scope. cmTarget* const global_target = - helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true); + helper.Makefile->GetGlobalGenerator()->FindTarget( + tgt, { cmStateEnums::TargetDomain::NATIVE }); if (global_target && !global_target->IsImported()) { target = global_target; } @@ -1402,7 +1403,8 @@ bool HandleImportedRuntimeArtifactsMode(std::vector const& args, if (!target || !target->IsImported()) { // If no local target has been found, find it in the global scope. cmTarget* const global_target = - helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true); + helper.Makefile->GetGlobalGenerator()->FindTarget( + tgt, { cmStateEnums::TargetDomain::NATIVE }); if (global_target && global_target->IsImported()) { target = global_target; } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 8450f75487..e176a05a20 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -4357,31 +4357,56 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name, return this->ImportedTargetsOwned.back().get(); } -cmTarget* cmMakefile::FindTargetToUse(const std::string& name, - bool excludeAliases) const +cmTarget* cmMakefile::AddForeignTarget(const std::string& origin, + const std::string& name) +{ + std::unique_ptr target(new cmTarget( + cmStrCat("@foreign_", origin, "::", name), + cmStateEnums::TargetType::INTERFACE_LIBRARY, cmTarget::Visibility::Foreign, + this, cmTarget::PerConfig::Yes)); + + this->ImportedTargets[name] = target.get(); + this->GetGlobalGenerator()->IndexTarget(target.get()); + this->GetStateSnapshot().GetDirectory().AddImportedTargetName(name); + + this->ImportedTargetsOwned.push_back(std::move(target)); + return this->ImportedTargetsOwned.back().get(); +} + +cmTarget* cmMakefile::FindTargetToUse( + const std::string& name, cmStateEnums::TargetDomainSet domains) const { // Look for an imported target. These take priority because they // are more local in scope and do not have to be globally unique. auto targetName = name; - if (!excludeAliases) { + if (domains.contains(cmStateEnums::TargetDomain::ALIAS)) { // Look for local alias targets. auto alias = this->AliasTargets.find(name); if (alias != this->AliasTargets.end()) { targetName = alias->second; } } - auto imported = this->ImportedTargets.find(targetName); + auto const imported = this->ImportedTargets.find(targetName); + + bool const useForeign = + domains.contains(cmStateEnums::TargetDomain::FOREIGN); + bool const useNative = domains.contains(cmStateEnums::TargetDomain::NATIVE); + if (imported != this->ImportedTargets.end()) { - return imported->second; + if (imported->second->IsForeign() ? useForeign : useNative) { + return imported->second; + } } // Look for a target built in this directory. if (cmTarget* t = this->FindLocalNonAliasTarget(name)) { - return t; + if (t->IsForeign() ? useForeign : useNative) { + return t; + } } // Look for a target built in this project. - return this->GetGlobalGenerator()->FindTarget(name, excludeAliases); + return this->GetGlobalGenerator()->FindTarget(name, domains); } bool cmMakefile::IsAlias(const std::string& name) const diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 620917f2c4..117970e341 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -260,6 +260,9 @@ public: cmTarget* AddImportedTarget(const std::string& name, cmStateEnums::TargetType type, bool global); + cmTarget* AddForeignTarget(const std::string& origin, + const std::string& name); + std::pair CreateNewTarget( const std::string& name, cmStateEnums::TargetType type, cmTarget::PerConfig perConfig = cmTarget::PerConfig::Yes, @@ -493,7 +496,9 @@ public: /** Find a target to use in place of the given name. The target returned may be imported or built within the project. */ cmTarget* FindTargetToUse(const std::string& name, - bool excludeAliases = false) const; + cmStateEnums::TargetDomainSet domains = { + cmStateEnums::TargetDomain::NATIVE, + cmStateEnums::TargetDomain::ALIAS }) const; bool IsAlias(const std::string& name) const; std::map GetAliasTargets() const diff --git a/Source/cmStateTypes.h b/Source/cmStateTypes.h index 24b809b571..73d797e03b 100644 --- a/Source/cmStateTypes.h +++ b/Source/cmStateTypes.h @@ -5,6 +5,8 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include + #include "cmLinkedTree.h" namespace cmStateDetail { @@ -43,6 +45,22 @@ enum TargetType UNKNOWN_LIBRARY }; +// Target search domains for FindTarget() style commands. +enum class TargetDomain : unsigned +{ + // Native, unaliased CMake targets, generated via add_library or + // add_executable + NATIVE, + // Alias index, must include another domain + ALIAS, + // Foreign domain targets, generated directly inside CMake + FOREIGN +}; +using TargetDomainSet = cm::enum_set; +static const TargetDomainSet AllTargetDomains{ TargetDomain::NATIVE, + TargetDomain::ALIAS, + TargetDomain::FOREIGN }; + enum CacheEntryType { BOOL = 0, diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index a0088e1116..2c79d116ac 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2940,6 +2940,7 @@ bool cmTarget::IsNormal() const case Visibility::Generated: case Visibility::Imported: case Visibility::ImportedGlobally: + case Visibility::Foreign: return false; } assert(false && "unknown visibility (IsNormal)"); @@ -2954,6 +2955,7 @@ bool cmTarget::IsSynthetic() const case Visibility::Normal: case Visibility::Imported: case Visibility::ImportedGlobally: + case Visibility::Foreign: return false; } assert(false && "unknown visibility (IsSynthetic)"); @@ -2965,6 +2967,7 @@ bool cmTargetInternals::IsImported() const switch (this->TargetVisibility) { case cmTarget::Visibility::Imported: case cmTarget::Visibility::ImportedGlobally: + case cmTarget::Visibility::Foreign: return true; case cmTarget::Visibility::Normal: case cmTarget::Visibility::Generated: @@ -2987,12 +2990,28 @@ bool cmTarget::IsImportedGloballyVisible() const case Visibility::Normal: case Visibility::Generated: case Visibility::Imported: + case Visibility::Foreign: return false; } assert(false && "unknown visibility (IsImportedGloballyVisible)"); return false; } +bool cmTarget::IsForeign() const +{ + switch (this->impl->TargetVisibility) { + case Visibility::Foreign: + return true; + case Visibility::Normal: + case Visibility::Generated: + case Visibility::Imported: + case Visibility::ImportedGlobally: + return false; + } + assert(false && "unknown visibility (isForeign)"); + return false; +} + bool cmTarget::IsPerConfig() const { return this->impl->PerConfig; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index d0e9e3dd67..28b738cb5c 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -49,6 +49,7 @@ public: Generated, Imported, ImportedGlobally, + Foreign, }; enum class PerConfig @@ -218,6 +219,7 @@ public: bool IsSynthetic() const; bool IsImported() const; bool IsImportedGloballyVisible() const; + bool IsForeign() const; bool IsPerConfig() const; bool IsRuntimeBinary() const; bool CanCompileSources() const; diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 48f4d4f047..43623cb09e 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -88,7 +88,8 @@ bool cmTargetLinkLibrariesCommand(std::vector const& args, cmTarget* target = mf.GetGlobalGenerator()->FindTarget(args[0]); if (!target) { for (const auto& importedTarget : mf.GetOwnedImportedTargets()) { - if (importedTarget->GetName() == args[0]) { + if (importedTarget->GetName() == args[0] && + !importedTarget->IsForeign()) { target = importedTarget.get(); break; }