1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-15 20:46:37 +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."));
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,

View File

@@ -189,7 +189,8 @@ bool cmAddLibraryCommand(std::vector<std::string> 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,

View File

@@ -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();

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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<cmGeneratorTarget>(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(

View File

@@ -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<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;

View File

@@ -711,7 +711,8 @@ bool HandleTargetsMode(std::vector<std::string> 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<std::string> 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;
}

View File

@@ -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<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
// 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

View File

@@ -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<cmTarget&, bool> 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<std::string, std::string> GetAliasTargets() const

View File

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

View File

@@ -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;

View File

@@ -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;

View File

@@ -88,7 +88,8 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> 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;
}