From 83ddc4d2891a0bbb06fb1e3daa00245b3c23eddc Mon Sep 17 00:00:00 2001
From: Gilles Khouzam <gillesk@microsoft.com>
Date: Mon, 7 Aug 2017 10:38:50 -0700
Subject: VS: Do not select a Windows SDK too high for current VS version

Add an internal API for the maximum Windows 10 SDK version supported by
a toolset.  For Visual Studio 14 2015 that would be the version
"10.0.14393.0".

Fixes: #17788
---
 Source/cmGlobalVisualStudio14Generator.cxx | 26 ++++++++++++++++++++++++++
 Source/cmGlobalVisualStudio14Generator.h   |  4 ++++
 Source/cmGlobalVisualStudio15Generator.cxx |  5 +++++
 Source/cmGlobalVisualStudio15Generator.h   |  2 ++
 4 files changed, 37 insertions(+)

diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index b0db146..c3ddb3e 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -212,6 +212,12 @@ bool cmGlobalVisualStudio14Generator::IsWindowsStoreToolsetInstalled() const
                                           cmSystemTools::KeyWOW64_32);
 }
 
+std::string cmGlobalVisualStudio14Generator::GetWindows10SDKMaxVersion() const
+{
+  // The last Windows 10 SDK version that VS 2015 can target is 10.0.14393.0.
+  return "10.0.14393.0";
+}
+
 #if defined(_WIN32) && !defined(__CYGWIN__)
 struct NoWindowsH
 {
@@ -220,6 +226,20 @@ struct NoWindowsH
     return !cmSystemTools::FileExists(p + "/um/windows.h", true);
   }
 };
+class WindowsSDKTooRecent
+{
+  std::string const& MaxVersion;
+
+public:
+  WindowsSDKTooRecent(std::string const& maxVersion)
+    : MaxVersion(maxVersion)
+  {
+  }
+  bool operator()(std::string const& v)
+  {
+    return cmSystemTools::VersionCompareGreater(v, MaxVersion);
+  }
+};
 #endif
 
 std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion()
@@ -276,6 +296,12 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion()
     // Sort the results to make sure we select the most recent one.
     std::sort(sdks.begin(), sdks.end(), cmSystemTools::VersionCompareGreater);
 
+    // Skip SDKs that cannot be used with our toolset.
+    std::string maxVersion = this->GetWindows10SDKMaxVersion();
+    if (!maxVersion.empty()) {
+      cmEraseIf(sdks, WindowsSDKTooRecent(maxVersion));
+    }
+
     // Look for a SDK exactly matching the requested target version.
     for (std::string const& i : sdks) {
       if (cmSystemTools::VersionCompareEqual(i, this->SystemVersion)) {
diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h
index 4868df0..9f5bb4e 100644
--- a/Source/cmGlobalVisualStudio14Generator.h
+++ b/Source/cmGlobalVisualStudio14Generator.h
@@ -37,6 +37,10 @@ protected:
   // of the toolset is installed
   bool IsWindowsStoreToolsetInstalled() const;
 
+  // Used to make sure that the Windows 10 SDK selected can work with the
+  // version of the toolset.
+  virtual std::string GetWindows10SDKMaxVersion() const;
+
   const char* GetIDEVersion() override { return "14.0"; }
   virtual bool SelectWindows10SDK(cmMakefile* mf, bool required);
 
diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx
index 9983a43..23fd2d5 100644
--- a/Source/cmGlobalVisualStudio15Generator.cxx
+++ b/Source/cmGlobalVisualStudio15Generator.cxx
@@ -258,6 +258,11 @@ bool cmGlobalVisualStudio15Generator::IsWin81SDKInstalled() const
   return false;
 }
 
+std::string cmGlobalVisualStudio15Generator::GetWindows10SDKMaxVersion() const
+{
+  return std::string();
+}
+
 std::string cmGlobalVisualStudio15Generator::FindMSBuildCommand()
 {
   std::string msbuild;
diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h
index cdc97ad..8ab63f1 100644
--- a/Source/cmGlobalVisualStudio15Generator.h
+++ b/Source/cmGlobalVisualStudio15Generator.h
@@ -52,6 +52,8 @@ protected:
   // Check for a Win 8 SDK known to the registry or VS installer tool.
   bool IsWin81SDKInstalled() const;
 
+  std::string GetWindows10SDKMaxVersion() const override;
+
   std::string FindMSBuildCommand() override;
   std::string FindDevEnvCommand() override;
 
-- 
cgit v0.12