Explorar o código

Add support for foreign targets

Vito Gamberini hai 9 meses
pai
achega
e109307c43

+ 2 - 1
Source/cmAddExecutableCommand.cxx

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

+ 2 - 1
Source/cmAddLibraryCommand.cxx

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

+ 7 - 1
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();
 

+ 1 - 0
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;

+ 2 - 1
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();
         }

+ 16 - 8
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<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(

+ 6 - 2
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<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;
 

+ 4 - 2
Source/cmInstallCommand.cxx

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

+ 32 - 7
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<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

+ 6 - 1
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<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

+ 18 - 0
Source/cmStateTypes.h

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

+ 19 - 0
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;

+ 2 - 0
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;

+ 2 - 1
Source/cmTargetLinkLibrariesCommand.cxx

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