Browse Source

VS: Add support for selecting the Windows 10 SDK (#15670)

Teach the VS 2015 generator to produce a WindowsTargetPlatformVersion
value.  Use the CMAKE_SYSTEM_VERSION to specify the version and if not
set choose a default based on available SDKs.  Activate this behavior
when targeting Windows 10.

Co-Author: Brad King <[email protected]>
Gilles Khouzam 10 years ago
parent
commit
3f077996f5

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -82,6 +82,7 @@ Variables that Provide Information
    /variable/CMAKE_VS_NsightTegra_VERSION
    /variable/CMAKE_VS_PLATFORM_NAME
    /variable/CMAKE_VS_PLATFORM_TOOLSET
+   /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
    /variable/CMAKE_XCODE_PLATFORM_TOOLSET
    /variable/PROJECT_BINARY_DIR
    /variable/PROJECT-NAME_BINARY_DIR

+ 6 - 0
Help/release/dev/vs-win10-sdk.rst

@@ -0,0 +1,6 @@
+vs-win10-sdk
+------------
+
+* The :generator:`Visual Studio 14 2015` generator learned to select
+  a Windows 10 SDK based on the value of the :variable:`CMAKE_SYSTEM_VERSION`
+  variable and the SDKs available on the host.

+ 11 - 0
Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst

@@ -0,0 +1,11 @@
+CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
+----------------------------------------
+
+Visual Studio Windows Target Platform Version.
+
+When targeting Windows 10 and above Visual Studio 2015 and above support
+specification of a target Windows version to select a corresponding SDK.
+The :variable:`CMAKE_SYSTEM_VERSION` variable may be set to specify a
+version.  Otherwise CMake computes a default version based on the Windows
+SDK versions available.  The chosen Windows target version number is provided
+in ``CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION``.

+ 3 - 0
Modules/CMakeDetermineCompilerId.cmake

@@ -209,6 +209,9 @@ Id flags: ${testflags}
     else()
       set(id_system_version "")
     endif()
+    if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION)
+      set(id_WindowsTargetPlatformVersion "<WindowsTargetPlatformVersion>${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}</WindowsTargetPlatformVersion>")
+    endif()
     if(id_platform STREQUAL ARM)
       set(id_WindowsSDKDesktopARMSupport "<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>")
     else()

+ 1 - 0
Modules/CompilerId/VS-10.vcxproj.in

@@ -12,6 +12,7 @@
     <Keyword>Win32Proj</Keyword>
     @id_system@
     @id_system_version@
+    @id_WindowsTargetPlatformVersion@
     @id_WindowsSDKDesktopARMSupport@
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+ 5 - 0
Source/cmGlobalVisualStudio10Generator.h

@@ -74,6 +74,10 @@ public:
   /** Return the CMAKE_SYSTEM_VERSION.  */
   std::string const& GetSystemVersion() const { return this->SystemVersion; }
 
+  /** Return the Windows version targeted on VS 2015 and above.  */
+  std::string const& GetWindowsTargetPlatformVersion() const
+    { return this->WindowsTargetPlatformVersion; }
+
   /** Return true if building for WindowsCE */
   bool TargetsWindowsCE() const
     { return this->SystemIsWindowsCE; }
@@ -120,6 +124,7 @@ protected:
 
   std::string GeneratorToolset;
   std::string DefaultPlatformToolset;
+  std::string WindowsTargetPlatformVersion;
   std::string SystemName;
   std::string SystemVersion;
   std::string NsightTegraVersion;

+ 80 - 0
Source/cmGlobalVisualStudio14Generator.cxx

@@ -110,6 +110,34 @@ cmGlobalVisualStudio14Generator::MatchesGeneratorName(
   return false;
 }
 
+//----------------------------------------------------------------------------
+bool cmGlobalVisualStudio14Generator::InitializeWindows(cmMakefile* mf)
+{
+  if (cmHasLiteralPrefix(this->SystemVersion, "10.0"))
+    {
+    return this->SelectWindows10SDK(mf);
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf)
+{
+  // Find the default version of the Windows 10 SDK.
+  this->WindowsTargetPlatformVersion = this->GetWindows10SDKVersion();
+  if (this->WindowsTargetPlatformVersion.empty())
+    {
+    std::ostringstream  e;
+    e << "Could not find an appropriate version of the Windows 10 SDK"
+      << " installed on this machine";
+    mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+    return false;
+    }
+  mf->AddDefinition("CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION",
+                    this->WindowsTargetPlatformVersion.c_str());
+  return true;
+}
+
 //----------------------------------------------------------------------------
 void cmGlobalVisualStudio14Generator::WriteSLNHeader(std::ostream& fout)
 {
@@ -137,3 +165,55 @@ cmGlobalVisualStudio14Generator::IsWindowsDesktopToolsetInstalled() const
   return cmSystemTools::GetRegistrySubKeys(desktop10Key,
     vc14, cmSystemTools::KeyWOW64_32);
 }
+
+//----------------------------------------------------------------------------
+std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion()
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  // This logic is taken from the vcvarsqueryregistry.bat file from VS2015
+  // Try HKLM and then HKCU.
+  std::string win10Root;
+  if (!cmSystemTools::ReadRegistryValue(
+        "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+        "Windows Kits\\Installed Roots;KitsRoot10", win10Root,
+        cmSystemTools::KeyWOW64_32) &&
+      !cmSystemTools::ReadRegistryValue(
+        "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\"
+        "Windows Kits\\Installed Roots;KitsRoot10", win10Root,
+        cmSystemTools::KeyWOW64_32))
+    {
+    return std::string();
+    }
+
+  std::vector<std::string> sdks;
+  std::string path = win10Root + "Include/*";
+  // Grab the paths of the different SDKs that are installed
+  cmSystemTools::GlobDirs(path, sdks);
+  if (!sdks.empty())
+    {
+    // Only use the filename, which will be the SDK version.
+    for (std::vector<std::string>::iterator i = sdks.begin();
+         i != sdks.end(); ++i)
+      {
+      *i = cmSystemTools::GetFilenameName(*i);
+      }
+
+    // Sort the results to make sure we select the most recent one that
+    // has a version less or equal to our version of the operating system
+    std::sort(sdks.begin(), sdks.end(), cmSystemTools::VersionCompareGreater);
+
+    for (std::vector<std::string>::iterator i = sdks.begin();
+         i != sdks.end(); ++i)
+      {
+      // Find the SDK less or equal to our specified version
+      if (!cmSystemTools::VersionCompareGreater(*i, this->SystemVersion))
+        {
+        // This is the most recent SDK that we can run safely
+        return *i;
+        }
+      }
+    }
+#endif
+  // Return an empty string
+  return std::string();
+}

+ 4 - 0
Source/cmGlobalVisualStudio14Generator.h

@@ -30,12 +30,16 @@ public:
 
   virtual const char* GetToolsVersion() { return "14.0"; }
 protected:
+  virtual bool InitializeWindows(cmMakefile* mf);
   virtual const char* GetIDEVersion() { return "14.0"; }
+  virtual bool SelectWindows10SDK(cmMakefile* mf);
 
   // Used to verify that the Desktop toolset for the current generator is
   // installed on the machine.
   virtual bool IsWindowsDesktopToolsetInstalled() const;
 
+  std::string GetWindows10SDKVersion();
+
 private:
   class Factory;
 };

+ 10 - 0
Source/cmVisualStudio10TargetGenerator.cxx

@@ -3006,6 +3006,8 @@ IsXamlSource(const std::string& sourceFile)
 
 void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
 {
+  cmGlobalVisualStudio10Generator* gg =
+    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
   bool isAppContainer = false;
   bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone();
   bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore();
@@ -3062,6 +3064,14 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
     this->WriteString("<WindowsSDKDesktopARMSupport>true"
                       "</WindowsSDKDesktopARMSupport>\n", 2);
     }
+  std::string const& targetPlatformVersion =
+    gg->GetWindowsTargetPlatformVersion();
+  if (!targetPlatformVersion.empty())
+    {
+    this->WriteString("<WindowsTargetPlatformVersion>", 2);
+    (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion) <<
+      "</WindowsTargetPlatformVersion>\n";
+    }
 }
 
 void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles()