1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-17 15:32:10 +08:00

Add support for foreign targets

This commit is contained in:
Vito Gamberini
2025-01-14 11:23:34 -05:00
parent c36ba41bee
commit e109307c43
14 changed files with 119 additions and 25 deletions

View File

@@ -107,7 +107,8 @@ bool cmAddExecutableCommand(std::vector<std::string> const& args,
"\" is itself an ALIAS.")); "\" is itself an ALIAS."));
return false; return false;
} }
cmTarget* aliasedTarget = mf.FindTargetToUse(aliasedName, true); cmTarget* aliasedTarget =
mf.FindTargetToUse(aliasedName, { cmStateEnums::TargetDomain::NATIVE });
if (!aliasedTarget) { if (!aliasedTarget) {
status.SetError(cmStrCat("cannot create ALIAS target \"", exename, status.SetError(cmStrCat("cannot create ALIAS target \"", exename,
"\" because target \"", aliasedName, "\" because target \"", aliasedName,

View File

@@ -189,7 +189,8 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args,
"\" is itself an ALIAS.")); "\" is itself an ALIAS."));
return false; return false;
} }
cmTarget* aliasedTarget = mf.FindTargetToUse(aliasedName, true); cmTarget* aliasedTarget =
mf.FindTargetToUse(aliasedName, { cmStateEnums::TargetDomain::NATIVE });
if (!aliasedTarget) { if (!aliasedTarget) {
status.SetError(cmStrCat("cannot create ALIAS target \"", libName, status.SetError(cmStrCat("cannot create ALIAS target \"", libName,
"\" because target \"", aliasedName, "\" because target \"", aliasedName,

View File

@@ -1149,6 +1149,11 @@ bool cmGeneratorTarget::IsImportedGloballyVisible() const
return this->Target->IsImportedGloballyVisible(); return this->Target->IsImportedGloballyVisible();
} }
bool cmGeneratorTarget::IsForeign() const
{
return this->Target->IsForeign();
}
bool cmGeneratorTarget::CanCompileSources() const bool cmGeneratorTarget::CanCompileSources() const
{ {
return this->Target->CanCompileSources(); return this->Target->CanCompileSources();
@@ -5396,7 +5401,8 @@ bool cmGeneratorTarget::AddHeaderSetVerification()
cmTarget* verifyTarget = nullptr; cmTarget* verifyTarget = nullptr;
cmTarget* allVerifyTarget = cmTarget* allVerifyTarget =
this->GlobalGenerator->GetMakefiles().front()->FindTargetToUse( this->GlobalGenerator->GetMakefiles().front()->FindTargetToUse(
"all_verify_interface_header_sets", true); "all_verify_interface_header_sets",
{ cmStateEnums::TargetDomain::NATIVE });
auto interfaceFileSetEntries = this->Target->GetInterfaceHeaderSetsEntries(); auto interfaceFileSetEntries = this->Target->GetInterfaceHeaderSetsEntries();

View File

@@ -60,6 +60,7 @@ public:
bool IsSynthetic() const; bool IsSynthetic() const;
bool IsImported() const; bool IsImported() const;
bool IsImportedGloballyVisible() const; bool IsImportedGloballyVisible() const;
bool IsForeign() const;
bool CanCompileSources() const; bool CanCompileSources() const;
bool HasKnownRuntimeArtifactLocation(std::string const& config) const; bool HasKnownRuntimeArtifactLocation(std::string const& config) const;
const std::string& GetLocation(const std::string& config) const; const std::string& GetLocation(const std::string& config) const;

View File

@@ -1362,7 +1362,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
std::string name = this->CheckCMP0004(lib); std::string name = this->CheckCMP0004(lib);
if (this->GetPolicyStatusCMP0108() == cmPolicies::NEW) { if (this->GetPolicyStatusCMP0108() == cmPolicies::NEW) {
// resolve alias name // resolve alias name
auto* target = this->Makefile->FindTargetToUse(name); auto* target = this->Makefile->FindTargetToUse(
name, cmStateEnums::AllTargetDomains);
if (target) { if (target) {
name = target->GetName(); name = target->GetName();
} }

View File

@@ -1929,7 +1929,8 @@ bool cmGlobalGenerator::AddHeaderSetVerification()
} }
cmTarget* allVerifyTarget = this->Makefiles.front()->FindTargetToUse( cmTarget* allVerifyTarget = this->Makefiles.front()->FindTargetToUse(
"all_verify_interface_header_sets", true); "all_verify_interface_header_sets",
{ cmStateEnums::TargetDomain::NATIVE });
if (allVerifyTarget) { if (allVerifyTarget) {
this->LocalGenerators.front()->AddGeneratorTarget( this->LocalGenerators.front()->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(allVerifyTarget, cm::make_unique<cmGeneratorTarget>(allVerifyTarget,
@@ -2671,11 +2672,18 @@ void cmGlobalGenerator::IndexLocalGenerator(cmLocalGenerator* lg)
this->LocalGeneratorSearchIndex[id.String] = 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); auto const it = this->TargetSearchIndex.find(name);
if (it != this->TargetSearchIndex.end()) { if (it != this->TargetSearchIndex.end()) {
return it->second; if (it->second->IsForeign() ? useForeign : useNative) {
return it->second;
}
} }
return nullptr; return nullptr;
} }
@@ -2690,16 +2698,16 @@ cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTargetImpl(
return nullptr; return nullptr;
} }
cmTarget* cmGlobalGenerator::FindTarget(const std::string& name, cmTarget* cmGlobalGenerator::FindTarget(
bool excludeAliases) const const std::string& name, cmStateEnums::TargetDomainSet domains) const
{ {
if (!excludeAliases) { if (domains.contains(cmStateEnums::TargetDomain::ALIAS)) {
auto const ai = this->AliasTargets.find(name); auto const ai = this->AliasTargets.find(name);
if (ai != this->AliasTargets.end()) { 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( cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTarget(

View File

@@ -25,6 +25,7 @@
#include "cmExportSet.h" #include "cmExportSet.h"
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmStateSnapshot.h" #include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h" #include "cmStringAlgorithms.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"
#include "cmTarget.h" #include "cmTarget.h"
@@ -380,7 +381,9 @@ public:
//! Find a target by name by searching the local generators. //! Find a target by name by searching the local generators.
cmTarget* FindTarget(const std::string& name, 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; cmGeneratorTarget* FindGeneratorTarget(const std::string& name) const;
@@ -783,7 +786,8 @@ protected:
std::map<std::string, std::string> AliasTargets; std::map<std::string, std::string> 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; cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const;

View File

@@ -711,7 +711,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
if (!target) { if (!target) {
// If no local target has been found, find it in the global scope. // If no local target has been found, find it in the global scope.
cmTarget* const global_target = cmTarget* const global_target =
helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true); helper.Makefile->GetGlobalGenerator()->FindTarget(
tgt, { cmStateEnums::TargetDomain::NATIVE });
if (global_target && !global_target->IsImported()) { if (global_target && !global_target->IsImported()) {
target = global_target; target = global_target;
} }
@@ -1402,7 +1403,8 @@ bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args,
if (!target || !target->IsImported()) { if (!target || !target->IsImported()) {
// If no local target has been found, find it in the global scope. // If no local target has been found, find it in the global scope.
cmTarget* const global_target = cmTarget* const global_target =
helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true); helper.Makefile->GetGlobalGenerator()->FindTarget(
tgt, { cmStateEnums::TargetDomain::NATIVE });
if (global_target && global_target->IsImported()) { if (global_target && global_target->IsImported()) {
target = global_target; target = global_target;
} }

View File

@@ -4357,31 +4357,56 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name,
return this->ImportedTargetsOwned.back().get(); return this->ImportedTargetsOwned.back().get();
} }
cmTarget* cmMakefile::FindTargetToUse(const std::string& name, cmTarget* cmMakefile::AddForeignTarget(const std::string& origin,
bool excludeAliases) const const std::string& name)
{
std::unique_ptr<cmTarget> 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 // Look for an imported target. These take priority because they
// are more local in scope and do not have to be globally unique. // are more local in scope and do not have to be globally unique.
auto targetName = name; auto targetName = name;
if (!excludeAliases) { if (domains.contains(cmStateEnums::TargetDomain::ALIAS)) {
// Look for local alias targets. // Look for local alias targets.
auto alias = this->AliasTargets.find(name); auto alias = this->AliasTargets.find(name);
if (alias != this->AliasTargets.end()) { if (alias != this->AliasTargets.end()) {
targetName = alias->second; 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()) { 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. // Look for a target built in this directory.
if (cmTarget* t = this->FindLocalNonAliasTarget(name)) { if (cmTarget* t = this->FindLocalNonAliasTarget(name)) {
return t; if (t->IsForeign() ? useForeign : useNative) {
return t;
}
} }
// Look for a target built in this project. // 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 bool cmMakefile::IsAlias(const std::string& name) const

View File

@@ -260,6 +260,9 @@ public:
cmTarget* AddImportedTarget(const std::string& name, cmTarget* AddImportedTarget(const std::string& name,
cmStateEnums::TargetType type, bool global); cmStateEnums::TargetType type, bool global);
cmTarget* AddForeignTarget(const std::string& origin,
const std::string& name);
std::pair<cmTarget&, bool> CreateNewTarget( std::pair<cmTarget&, bool> CreateNewTarget(
const std::string& name, cmStateEnums::TargetType type, const std::string& name, cmStateEnums::TargetType type,
cmTarget::PerConfig perConfig = cmTarget::PerConfig::Yes, cmTarget::PerConfig perConfig = cmTarget::PerConfig::Yes,
@@ -493,7 +496,9 @@ public:
/** Find a target to use in place of the given name. The target /** Find a target to use in place of the given name. The target
returned may be imported or built within the project. */ returned may be imported or built within the project. */
cmTarget* FindTargetToUse(const std::string& name, 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; bool IsAlias(const std::string& name) const;
std::map<std::string, std::string> GetAliasTargets() const std::map<std::string, std::string> GetAliasTargets() const

View File

@@ -5,6 +5,8 @@
#include "cmConfigure.h" // IWYU pragma: keep #include "cmConfigure.h" // IWYU pragma: keep
#include <cmext/enum_set>
#include "cmLinkedTree.h" #include "cmLinkedTree.h"
namespace cmStateDetail { namespace cmStateDetail {
@@ -43,6 +45,22 @@ enum TargetType
UNKNOWN_LIBRARY 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<TargetDomain>;
static const TargetDomainSet AllTargetDomains{ TargetDomain::NATIVE,
TargetDomain::ALIAS,
TargetDomain::FOREIGN };
enum CacheEntryType enum CacheEntryType
{ {
BOOL = 0, BOOL = 0,

View File

@@ -2940,6 +2940,7 @@ bool cmTarget::IsNormal() const
case Visibility::Generated: case Visibility::Generated:
case Visibility::Imported: case Visibility::Imported:
case Visibility::ImportedGlobally: case Visibility::ImportedGlobally:
case Visibility::Foreign:
return false; return false;
} }
assert(false && "unknown visibility (IsNormal)"); assert(false && "unknown visibility (IsNormal)");
@@ -2954,6 +2955,7 @@ bool cmTarget::IsSynthetic() const
case Visibility::Normal: case Visibility::Normal:
case Visibility::Imported: case Visibility::Imported:
case Visibility::ImportedGlobally: case Visibility::ImportedGlobally:
case Visibility::Foreign:
return false; return false;
} }
assert(false && "unknown visibility (IsSynthetic)"); assert(false && "unknown visibility (IsSynthetic)");
@@ -2965,6 +2967,7 @@ bool cmTargetInternals::IsImported() const
switch (this->TargetVisibility) { switch (this->TargetVisibility) {
case cmTarget::Visibility::Imported: case cmTarget::Visibility::Imported:
case cmTarget::Visibility::ImportedGlobally: case cmTarget::Visibility::ImportedGlobally:
case cmTarget::Visibility::Foreign:
return true; return true;
case cmTarget::Visibility::Normal: case cmTarget::Visibility::Normal:
case cmTarget::Visibility::Generated: case cmTarget::Visibility::Generated:
@@ -2987,12 +2990,28 @@ bool cmTarget::IsImportedGloballyVisible() const
case Visibility::Normal: case Visibility::Normal:
case Visibility::Generated: case Visibility::Generated:
case Visibility::Imported: case Visibility::Imported:
case Visibility::Foreign:
return false; return false;
} }
assert(false && "unknown visibility (IsImportedGloballyVisible)"); assert(false && "unknown visibility (IsImportedGloballyVisible)");
return false; 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 bool cmTarget::IsPerConfig() const
{ {
return this->impl->PerConfig; return this->impl->PerConfig;

View File

@@ -49,6 +49,7 @@ public:
Generated, Generated,
Imported, Imported,
ImportedGlobally, ImportedGlobally,
Foreign,
}; };
enum class PerConfig enum class PerConfig
@@ -218,6 +219,7 @@ public:
bool IsSynthetic() const; bool IsSynthetic() const;
bool IsImported() const; bool IsImported() const;
bool IsImportedGloballyVisible() const; bool IsImportedGloballyVisible() const;
bool IsForeign() const;
bool IsPerConfig() const; bool IsPerConfig() const;
bool IsRuntimeBinary() const; bool IsRuntimeBinary() const;
bool CanCompileSources() const; bool CanCompileSources() const;

View File

@@ -88,7 +88,8 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args,
cmTarget* target = mf.GetGlobalGenerator()->FindTarget(args[0]); cmTarget* target = mf.GetGlobalGenerator()->FindTarget(args[0]);
if (!target) { if (!target) {
for (const auto& importedTarget : mf.GetOwnedImportedTargets()) { for (const auto& importedTarget : mf.GetOwnedImportedTargets()) {
if (importedTarget->GetName() == args[0]) { if (importedTarget->GetName() == args[0] &&
!importedTarget->IsForeign()) {
target = importedTarget.get(); target = importedTarget.get();
break; break;
} }