cmTarget: refactor PRECOMPILE_HEADERS usage requirements
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 412df23..f6a3119 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -305,7 +305,6 @@
   std::map<std::string, BTs<std::string>> LanguageStandardProperties;
   std::map<cmTargetExport const*, std::vector<std::string>>
     InstallIncludeDirectoriesEntries;
-  std::vector<BT<std::string>> PrecompileHeadersEntries;
   std::vector<BT<std::string>> SourceEntries;
   std::vector<BT<std::string>> LinkOptionsEntries;
   std::vector<BT<std::string>> LinkDirectoriesEntries;
@@ -322,6 +321,7 @@
   UsageRequirementProperty CompileOptions;
   UsageRequirementProperty CompileFeatures;
   UsageRequirementProperty CompileDefinitions;
+  UsageRequirementProperty PrecompileHeaders;
 
   FileSetType HeadersFileSets;
   FileSetType CxxModulesFileSets;
@@ -362,6 +362,7 @@
   , CompileOptions("COMPILE_OPTIONS"_s)
   , CompileFeatures("COMPILE_FEATURES"_s)
   , CompileDefinitions("COMPILE_DEFINITIONS"_s)
+  , PrecompileHeaders("PRECOMPILE_HEADERS"_s)
   , HeadersFileSets("HEADERS"_s, "HEADER_DIRS"_s, "HEADER_SET"_s,
                     "HEADER_DIRS_"_s, "HEADER_SET_"_s, "Header"_s,
                     "The default header set"_s, "Header set"_s,
@@ -1481,7 +1482,7 @@
 
 cmBTStringRange cmTarget::GetPrecompileHeadersEntries() const
 {
-  return cmMakeRange(this->impl->PrecompileHeadersEntries);
+  return cmMakeRange(this->impl->PrecompileHeaders.Entries);
 }
 
 cmBTStringRange cmTarget::GetSourceEntries() const
@@ -1646,10 +1647,9 @@
   }
 
   UsageRequirementProperty* usageRequirements[] = {
-    &this->impl->IncludeDirectories,
-    &this->impl->CompileOptions,
-    &this->impl->CompileFeatures,
-    &this->impl->CompileDefinitions,
+    &this->impl->IncludeDirectories, &this->impl->CompileOptions,
+    &this->impl->CompileFeatures,    &this->impl->CompileDefinitions,
+    &this->impl->PrecompileHeaders,
   };
 
   for (auto* usageRequirement : usageRequirements) {
@@ -1684,12 +1684,6 @@
       cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
       this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt);
     }
-  } else if (prop == propPRECOMPILE_HEADERS) {
-    this->impl->PrecompileHeadersEntries.clear();
-    if (value) {
-      cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
-      this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt);
-    }
   } else if (prop == propLINK_LIBRARIES) {
     this->impl->LinkImplementationPropertyEntries.clear();
     if (value) {
@@ -1826,12 +1820,20 @@
     this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
     return;
   }
+  if (prop == propPRECOMPILE_HEADERS &&
+      this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
+    std::ostringstream e;
+    e << "PRECOMPILE_HEADERS_REUSE_FROM property is already set on target "
+         "(\""
+      << this->impl->Name << "\")\n";
+    this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+    return;
+  }
 
   UsageRequirementProperty* usageRequirements[] = {
-    &this->impl->IncludeDirectories,
-    &this->impl->CompileOptions,
-    &this->impl->CompileFeatures,
-    &this->impl->CompileDefinitions,
+    &this->impl->IncludeDirectories, &this->impl->CompileOptions,
+    &this->impl->CompileFeatures,    &this->impl->CompileDefinitions,
+    &this->impl->PrecompileHeaders,
   };
 
   for (auto* usageRequirement : usageRequirements) {
@@ -1864,19 +1866,6 @@
       cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
       this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt);
     }
-  } else if (prop == "PRECOMPILE_HEADERS") {
-    if (this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
-      std::ostringstream e;
-      e << "PRECOMPILE_HEADERS_REUSE_FROM property is already set on target "
-           "(\""
-        << this->impl->Name << "\")\n";
-      this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
-      return;
-    }
-    if (!value.empty()) {
-      cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
-      this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt);
-    }
   } else if (prop == "LINK_LIBRARIES") {
     if (!value.empty()) {
       cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt);
@@ -2183,7 +2172,8 @@
 
 void cmTarget::InsertPrecompileHeader(BT<std::string> const& entry)
 {
-  this->impl->PrecompileHeadersEntries.push_back(entry);
+  this->impl->PrecompileHeaders.WriteDirect(
+    entry, UsageRequirementProperty::Action::Append);
 }
 
 namespace {
@@ -2330,10 +2320,9 @@
     }
 
     UsageRequirementProperty const* usageRequirements[] = {
-      &this->impl->IncludeDirectories,
-      &this->impl->CompileOptions,
-      &this->impl->CompileFeatures,
-      &this->impl->CompileDefinitions,
+      &this->impl->IncludeDirectories, &this->impl->CompileOptions,
+      &this->impl->CompileFeatures,    &this->impl->CompileDefinitions,
+      &this->impl->PrecompileHeaders,
     };
 
     for (auto const* usageRequirement : usageRequirements) {
@@ -2420,15 +2409,6 @@
       output = cmJoin(utilities, ";");
       return cmValue(output);
     }
-    if (prop == propPRECOMPILE_HEADERS) {
-      if (this->impl->PrecompileHeadersEntries.empty()) {
-        return nullptr;
-      }
-
-      static std::string output;
-      output = cmJoin(this->impl->PrecompileHeadersEntries, ";");
-      return cmValue(output);
-    }
     if (prop == propIMPORTED) {
       return this->IsImported() ? cmValue(propTRUE) : cmValue(propFALSE);
     }