VS: Do not use native unity builds on VS 2017 versions less than 15.8

VS 2017 version 15.8 introduced support for unity builds implemented
in part by the `$(VCTargetsPath)/Microsoft.Cpp.Unity.targets` file.
Do not enable unity builds on VS 15 versions that do not have that file.

Fixes: #20284
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 09a49e1..f6472ab 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -230,6 +230,12 @@
     }
   }
 
+  this->SupportsUnityBuilds =
+    this->Version >= cmGlobalVisualStudioGenerator::VS16 ||
+    (this->Version == cmGlobalVisualStudioGenerator::VS15 &&
+     cmSystemTools::PathExists(this->VCTargetsPath +
+                               "/Microsoft.Cpp.Unity.targets"));
+
   if (this->GeneratorToolsetCuda.empty()) {
     // Find the highest available version of the CUDA tools.
     std::vector<std::string> cudaTools;
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 9adcf08..56f1193 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -108,6 +108,8 @@
   virtual bool IsDefaultToolset(const std::string& version) const;
   virtual std::string GetAuxiliaryToolset() const;
 
+  bool GetSupportsUnityBuilds() const { return this->SupportsUnityBuilds; }
+
   bool FindMakeProgram(cmMakefile* mf) override;
 
   bool IsIPOSupported() const override { return true; }
@@ -172,6 +174,7 @@
   std::string DefaultMasmFlagTableName;
   std::string DefaultNasmFlagTableName;
   std::string DefaultRCFlagTableName;
+  bool SupportsUnityBuilds = false;
   bool SystemIsWindowsCE;
   bool SystemIsWindowsPhone;
   bool SystemIsWindowsStore;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 53fc93c..7e8e610 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2085,9 +2085,7 @@
   const bool haveUnityBuild =
     this->GeneratorTarget->GetPropertyAsBool("UNITY_BUILD");
 
-  if (haveUnityBuild &&
-      this->GlobalGenerator->GetVersion() >=
-        cmGlobalVisualStudioGenerator::VS15) {
+  if (haveUnityBuild && this->GlobalGenerator->GetSupportsUnityBuilds()) {
     Elem e1(e0, "PropertyGroup");
     e1.Element("EnableUnitySupport", "true");
   }
@@ -2193,9 +2191,7 @@
       this->WriteSource(e2, si.Source);
 
       bool useNativeUnityBuild = false;
-      if (haveUnityBuild &&
-          this->GlobalGenerator->GetVersion() >=
-            cmGlobalVisualStudioGenerator::VS15) {
+      if (haveUnityBuild && this->GlobalGenerator->GetSupportsUnityBuilds()) {
         // Magic value taken from cmGlobalVisualStudioVersionedGenerator.cxx
         static const std::string vs15 = "141";
         std::string toolset =
@@ -2222,7 +2218,7 @@
             si.Source->GetProperty("UNITY_SOURCE_FILE"));
           e2.Attribute("UnityFilesDirectory", unityDir);
         } else {
-          // Visual Studio versions prior to 2017 do not know about unity
+          // Visual Studio versions prior to 2017 15.8 do not know about unity
           // builds, thus we exclude the files alredy part of unity sources.
           if (!si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")) {
             exclude_configs = si.Configs;