cmMakefile: add support for a "synthesized" target

It is a normal target, but will end up copying its internals from
another target. Keep track of this state so that such copying can only
occur when intended.
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 2202507..b99892b 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1242,6 +1242,11 @@
   return this->Target->IsNormal();
 }
 
+bool cmGeneratorTarget::IsSynthetic() const
+{
+  return this->Target->IsSynthetic();
+}
+
 bool cmGeneratorTarget::IsImported() const
 {
   return this->Target->IsImported();
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 210022e..e46c719 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -51,6 +51,7 @@
 
   bool IsInBuildSystem() const;
   bool IsNormal() const;
+  bool IsSynthetic() const;
   bool IsImported() const;
   bool IsImportedGloballyVisible() const;
   bool CanCompileSources() const;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 457204a..d963a5a 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2115,12 +2115,21 @@
   return &this->CreateNewTarget(name, type).first;
 }
 
+cmTarget* cmMakefile::AddSynthesizedTarget(cmStateEnums::TargetType type,
+                                           const std::string& name)
+{
+  return &this
+            ->CreateNewTarget(name, type, cmTarget::PerConfig::Yes,
+                              cmTarget::Visibility::Generated)
+            .first;
+}
+
 std::pair<cmTarget&, bool> cmMakefile::CreateNewTarget(
   const std::string& name, cmStateEnums::TargetType type,
-  cmTarget::PerConfig perConfig)
+  cmTarget::PerConfig perConfig, cmTarget::Visibility vis)
 {
-  auto ib = this->Targets.emplace(
-    name, cmTarget(name, type, cmTarget::Visibility::Normal, this, perConfig));
+  auto ib =
+    this->Targets.emplace(name, cmTarget(name, type, vis, this, perConfig));
   auto it = ib.first;
   if (!ib.second) {
     return std::make_pair(std::ref(it->second), false);
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 3866aca..7b19c97 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -241,10 +241,13 @@
 
   std::pair<cmTarget&, bool> CreateNewTarget(
     const std::string& name, cmStateEnums::TargetType type,
-    cmTarget::PerConfig perConfig = cmTarget::PerConfig::Yes);
+    cmTarget::PerConfig perConfig = cmTarget::PerConfig::Yes,
+    cmTarget::Visibility vis = cmTarget::Visibility::Normal);
 
   cmTarget* AddNewTarget(cmStateEnums::TargetType type,
                          const std::string& name);
+  cmTarget* AddSynthesizedTarget(cmStateEnums::TargetType type,
+                                 const std::string& name);
 
   /** Create a target instance for the utility.  */
   cmTarget* AddNewUtilityTarget(const std::string& utilityName,
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 48f92b5..91d5de6 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -2559,6 +2559,7 @@
   switch (this->impl->TargetVisibility) {
     case Visibility::Normal:
       return true;
+    case Visibility::Generated:
     case Visibility::Imported:
     case Visibility::ImportedGlobally:
       return false;
@@ -2567,6 +2568,20 @@
   return false;
 }
 
+bool cmTarget::IsSynthetic() const
+{
+  switch (this->impl->TargetVisibility) {
+    case Visibility::Generated:
+      return true;
+    case Visibility::Normal:
+    case Visibility::Imported:
+    case Visibility::ImportedGlobally:
+      return false;
+  }
+  assert(false && "unknown visibility (IsSynthetic)");
+  return false;
+}
+
 bool cmTargetInternals::IsImported() const
 {
   switch (this->TargetVisibility) {
@@ -2574,6 +2589,7 @@
     case cmTarget::Visibility::ImportedGlobally:
       return true;
     case cmTarget::Visibility::Normal:
+    case cmTarget::Visibility::Generated:
       return false;
   }
   assert(false && "unknown visibility (IsImported)");
@@ -2591,6 +2607,7 @@
     case Visibility::ImportedGlobally:
       return true;
     case Visibility::Normal:
+    case Visibility::Generated:
     case Visibility::Imported:
       return false;
   }
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index b96bdf2..95539fa 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -49,6 +49,7 @@
   enum class Visibility
   {
     Normal,
+    Generated,
     Imported,
     ImportedGlobally,
   };
@@ -206,6 +207,7 @@
   bool IsAIX() const;
 
   bool IsNormal() const;
+  bool IsSynthetic() const;
   bool IsImported() const;
   bool IsImportedGloballyVisible() const;
   bool IsPerConfig() const;