diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 635db0023..211690050 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/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 diff --git a/Help/release/dev/vs-win10-sdk.rst b/Help/release/dev/vs-win10-sdk.rst new file mode 100644 index 000000000..50eb39133 --- /dev/null +++ b/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. diff --git a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst new file mode 100644 index 000000000..639284963 --- /dev/null +++ b/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``. diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index df6daf372..81c25090c 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/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 "${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") + endif() if(id_platform STREQUAL ARM) set(id_WindowsSDKDesktopARMSupport "true") else() diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in index a17d03d0d..2870a11ca 100644 --- a/Modules/CompilerId/VS-10.vcxproj.in +++ b/Modules/CompilerId/VS-10.vcxproj.in @@ -12,6 +12,7 @@ Win32Proj @id_system@ @id_system_version@ + @id_WindowsTargetPlatformVersion@ @id_WindowsSDKDesktopARMSupport@ diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 49c561601..f4861dc6d 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/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; diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index d73eedf92..74679d842 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/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 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::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::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(); +} diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index 02c6274f5..fcade852c 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/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; }; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 6c71313e9..91f24766b 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -3006,6 +3006,8 @@ IsXamlSource(const std::string& sourceFile) void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings() { + cmGlobalVisualStudio10Generator* gg = + static_cast(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("true" "\n", 2); } + std::string const& targetPlatformVersion = + gg->GetWindowsTargetPlatformVersion(); + if (!targetPlatformVersion.empty()) + { + this->WriteString("", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion) << + "\n"; + } } void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles()