diff options
22 files changed, 248 insertions, 15 deletions
diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst index 9feb4d2..a831fa6 100644 --- a/Help/manual/cmake-toolchains.7.rst +++ b/Help/manual/cmake-toolchains.7.rst @@ -273,7 +273,7 @@ supported out of the box. Other versions may require one to set Cross Compiling for Windows 10 Universal Applications ----------------------------------------------------- -A toolchain file to configure a Visual Studio generator for a +A toolchain file to configure :ref:`Visual Studio Generators` for a Windows 10 Universal Application may look like this: .. code-block:: cmake @@ -283,9 +283,10 @@ Windows 10 Universal Application may look like this: A Windows 10 Universal Application targets both Windows Store and Windows Phone. Specify the :variable:`CMAKE_SYSTEM_VERSION` variable -to be ``10.0`` to build with the latest available Windows 10 SDK. -Specify a more specific version (e.g. ``10.0.10240.0`` for RTM) -to build with the corresponding SDK. +to be ``10.0`` or higher. + +CMake selects a Windows SDK as described by documentation of the +:variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION` variable. Cross Compiling for Windows Phone --------------------------------- diff --git a/Help/release/dev/vs-sdk-selection.rst b/Help/release/dev/vs-sdk-selection.rst new file mode 100644 index 0000000..856a203 --- /dev/null +++ b/Help/release/dev/vs-sdk-selection.rst @@ -0,0 +1,7 @@ +vs-sdk-selection +---------------- + +* The :ref:`Visual Studio Generators` for VS 2015 and above learned to + select the Windows SDK version explicitly using a ``version=`` field + in the :variable:`CMAKE_GENERATOR_PLATFORM` variable. + See :ref:`Visual Studio Platform Selection`. diff --git a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst index 0238183..3b6932a 100644 --- a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst +++ b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst @@ -26,6 +26,8 @@ Platform specification is supported only on specific generators: See native build system documentation for allowed platform names. +.. _`Visual Studio Platform Selection`: + Visual Studio Platform Selection ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,4 +44,24 @@ name is provided in the :variable:`CMAKE_VS_PLATFORM_NAME` variable. The ``key=value`` pairs form a comma-separated list of options to specify generator-specific details of the platform selection. -There are no supported pairs: this syntax is reserved for future use. +Supported pairs are: + +``version=<version>`` + .. versionadded:: 3.27 + + Specify the Windows SDK version to use. This is supported by VS 2015 and + above when targeting Windows 10.0+ or Windows Store. CMake will set the + :variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION` variable to the + selected SDK version. + + The ``<version>`` may be one of: + + ``10.0.<build>.<increment>`` + Specify the exact 4-component SDK version, e.g., ``10.0.19041.0``. + The specified version of the SDK must be installed. It may not exceed + the value of :variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM`, + if that variable is set. + + If the ``version`` field is not specified, CMake selects a version as + described in the :variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION` + variable documentation. diff --git a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst index eb71049..4a3ef47 100644 --- a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst +++ b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst @@ -5,11 +5,19 @@ 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 +When targeting Windows 10 and above, :ref:`Visual Studio Generators` for +VS 2015 and above support specification of a Windows SDK version: + +* If :variable:`CMAKE_GENERATOR_PLATFORM` specifies a ``version=`` field, + as documented by :ref:`Visual Studio Platform Selection`, that SDK + version is selected. + +* Otherwise, if :variable:`CMAKE_SYSTEM_VERSION` is set to an available + SDK version, that version is selected. + +* Otherwise, CMake uses the latest Windows SDK version available. + +The chosen Windows target version number is provided in ``CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION``. If no Windows 10 SDK is available this value will be empty. diff --git a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM.rst b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM.rst index f1a1977..727ccc9 100644 --- a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM.rst +++ b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM.rst @@ -10,5 +10,5 @@ be set to a false value (e.g. ``OFF``, ``FALSE``, or ``0``) or the SDK version to use as the maximum (e.g. ``10.0.14393.0``). If unset, the default depends on which version of Visual Studio is targeted by the current generator. -This can be used in conjunction with :variable:`CMAKE_SYSTEM_VERSION`, which -CMake uses to select :variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION`. +This can be used to exclude Windows SDK versions from consideration for +:variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION`. diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 41d54e5..321f377 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -531,6 +531,9 @@ bool cmGlobalVisualStudio10Generator::InitializePlatform(cmMakefile* mf) if (!this->InitializePlatformWindows(mf)) { return false; } + } else if (!this->SystemName.empty() && + !this->VerifyNoGeneratorPlatformVersion(mf)) { + return false; } return this->cmGlobalVisualStudio8Generator::InitializePlatform(mf); } @@ -540,6 +543,12 @@ bool cmGlobalVisualStudio10Generator::InitializePlatformWindows(cmMakefile*) return true; } +bool cmGlobalVisualStudio10Generator::VerifyNoGeneratorPlatformVersion( + cmMakefile*, cm::optional<std::string>) const +{ + return true; +} + bool cmGlobalVisualStudio10Generator::SelectWindowsPhoneToolset( std::string& toolset) const { diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 63cfe72..6917ffc 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -185,6 +185,8 @@ protected: bool InitializePlatform(cmMakefile* mf) override; virtual bool InitializePlatformWindows(cmMakefile* mf); + virtual bool VerifyNoGeneratorPlatformVersion( + cmMakefile* mf, cm::optional<std::string> reason = cm::nullopt) const; virtual bool ProcessGeneratorToolsetField(std::string const& key, std::string const& value); diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 87c8a5e..9ae80bb 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -142,7 +142,31 @@ bool cmGlobalVisualStudio14Generator::InitializePlatformWindows(cmMakefile* mf) if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { return this->SelectWindows10SDK(mf); } - return true; + return this->VerifyNoGeneratorPlatformVersion(mf); +} + +bool cmGlobalVisualStudio14Generator::VerifyNoGeneratorPlatformVersion( + cmMakefile* mf, cm::optional<std::string> reason) const +{ + if (!this->GeneratorPlatformVersion) { + return true; + } + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given platform specification containing a\n" + " version=" << *this->GeneratorPlatformVersion << "\n" + "field. The version field is not supported when targeting\n" + " " << this->SystemName << " " << this->SystemVersion << "\n" + ; + /* clang-format on */ + if (reason) { + e << *reason << "."; + } + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; } bool cmGlobalVisualStudio14Generator::InitializeWindowsStore(cmMakefile* mf) @@ -170,12 +194,42 @@ bool cmGlobalVisualStudio14Generator::InitializeAndroid(cmMakefile*) return true; } +bool cmGlobalVisualStudio14Generator::ProcessGeneratorPlatformField( + std::string const& key, std::string const& value) +{ + if (key == "version") { + this->GeneratorPlatformVersion = value; + return true; + } + return false; +} + bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf) { + if (this->GeneratorPlatformVersion && + this->GeneratorPlatformVersion->empty()) { + mf->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Generator\n ", this->GetName(), + "\ngiven platform specification with empty\n version=\n" + "field.")); + return false; + } + // Find the default version of the Windows 10 SDK. std::string const version = this->GetWindows10SDKVersion(mf); if (version.empty()) { + if (this->GeneratorPlatformVersion) { + mf->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Generator\n ", this->GetName(), + "\ngiven platform specification with\n version=", + *this->GeneratorPlatformVersion, + "\nfield, but no Windows SDK with that version was found.")); + return false; + } + if (this->SystemName == "WindowsStore") { mf->IssueMessage( MessageType::FATAL_ERROR, @@ -359,7 +413,20 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion( // Sort the results to make sure we select the most recent one. std::sort(sdks.begin(), sdks.end(), cmSystemTools::VersionCompareGreater); - // Look for a SDK exactly matching the requested target version. + // Look for a SDK exactly matching the requested version, if any. + if (this->GeneratorPlatformVersion) { + for (std::string const& i : sdks) { + if (cmSystemTools::VersionCompareEqual( + i, *this->GeneratorPlatformVersion)) { + return i; + } + } + // An exact version was requested but not found. + // Our caller will issue the error message. + return std::string(); + } + + // Look for a SDK exactly matching the target Windows version. for (std::string const& i : sdks) { if (cmSystemTools::VersionCompareEqual(i, this->SystemVersion)) { return i; diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index 0f016b3..f59a323 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -7,6 +7,8 @@ #include <memory> #include <string> +#include <cm/optional> + #include "cmGlobalVisualStudio12Generator.h" class cmGlobalGeneratorFactory; @@ -39,6 +41,12 @@ protected: bool IsWindowsStoreToolsetInstalled() const; bool InitializePlatformWindows(cmMakefile* mf) override; + bool VerifyNoGeneratorPlatformVersion( + cmMakefile* mf, + cm::optional<std::string> reason = cm::nullopt) const override; + + bool ProcessGeneratorPlatformField(std::string const& key, + std::string const& value) override; // Used to adjust the max-SDK-version calculation to accommodate user // configuration. @@ -62,4 +70,6 @@ protected: private: class Factory; friend class Factory; + + cm::optional<std::string> GeneratorPlatformVersion; }; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index f3936ce..f28419a 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -895,7 +895,8 @@ bool cmGlobalVisualStudioVersionedGenerator::InitializePlatformWindows( if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS16 && !cmSystemTools::VersionCompareGreater(this->SystemVersion, "8.1")) { this->SetWindowsTargetPlatformVersion("8.1", mf); - return true; + return this->VerifyNoGeneratorPlatformVersion( + mf, "with the Windows 8.1 SDK installed"); } return cmGlobalVisualStudio14Generator::InitializePlatformWindows(mf); } diff --git a/Tests/RunCMake/GeneratorPlatform/BadVersionEmpty-result.txt b/Tests/RunCMake/GeneratorPlatform/BadVersionEmpty-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadVersionEmpty-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorPlatform/BadVersionEmpty-stderr.txt b/Tests/RunCMake/GeneratorPlatform/BadVersionEmpty-stderr.txt new file mode 100644 index 0000000..1b7804d --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadVersionEmpty-stderr.txt @@ -0,0 +1,11 @@ +^CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + Visual Studio [^ +]+ + + given platform specification with empty + + version= + + field\.$ diff --git a/Tests/RunCMake/GeneratorPlatform/BadVersionEmpty.cmake b/Tests/RunCMake/GeneratorPlatform/BadVersionEmpty.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadVersionEmpty.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorPlatform/BadVersionMissing-result.txt b/Tests/RunCMake/GeneratorPlatform/BadVersionMissing-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadVersionMissing-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorPlatform/BadVersionMissing-stderr.txt b/Tests/RunCMake/GeneratorPlatform/BadVersionMissing-stderr.txt new file mode 100644 index 0000000..d82eb0b --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadVersionMissing-stderr.txt @@ -0,0 +1,11 @@ +^CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + Visual Studio [^ +]+ + + given platform specification with + + version=1\.2\.3\.4 + + field, but no Windows SDK with that version was found\.$ diff --git a/Tests/RunCMake/GeneratorPlatform/BadVersionMissing.cmake b/Tests/RunCMake/GeneratorPlatform/BadVersionMissing.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadVersionMissing.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorPlatform/BadVersionPlatform-result.txt b/Tests/RunCMake/GeneratorPlatform/BadVersionPlatform-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadVersionPlatform-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorPlatform/BadVersionPlatform-stderr.txt b/Tests/RunCMake/GeneratorPlatform/BadVersionPlatform-stderr.txt new file mode 100644 index 0000000..d3c62e3 --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadVersionPlatform-stderr.txt @@ -0,0 +1,19 @@ +^CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + Visual Studio [^ +]+ + + given platform specification (containing a + + version=8\.1 + + field\. The version field is not supported when targeting + + Windows 8\.1( + + with the Windows 8\.1 SDK installed\.)?|with + + version=8\.1 + + field, but no Windows SDK with that version was found\.)$ diff --git a/Tests/RunCMake/GeneratorPlatform/BadVersionPlatform.cmake b/Tests/RunCMake/GeneratorPlatform/BadVersionPlatform.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadVersionPlatform.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake index fac15b8..00a32a2 100644 --- a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake @@ -32,4 +32,53 @@ if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio (1[4567])( 20[0-9][0-9])?$") run_cmake(BadFieldNoComma) set(RunCMake_GENERATOR_PLATFORM "Test Platform,unknown=") run_cmake(BadFieldUnknown) + set(RunCMake_GENERATOR_PLATFORM "version=") + run_cmake(BadVersionEmpty) + set(RunCMake_GENERATOR_PLATFORM "version=1.2.3.4") + run_cmake(BadVersionMissing) + set(RunCMake_GENERATOR_PLATFORM "version=8.1") + run_cmake_with_options(BadVersionPlatform -DCMAKE_SYSTEM_VERSION=8.1) + + set(kits "") + cmake_host_system_information(RESULT kitsRoot10 + QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/Microsoft/Windows Kits/Installed Roots" + VALUE "KitsRoot10" + VIEW 64_32 + ERROR_VARIABLE kitsRoot10Error + ) + if(NOT kitsRoot10Error AND IS_DIRECTORY "${kitsRoot10}/include") + cmake_path(SET kitsInclude "${kitsRoot10}/include") + file(GLOB kits RELATIVE "${kitsInclude}" "${kitsInclude}/*/um/windows.h") + list(TRANSFORM kits REPLACE "/.*" "") + endif() + if(kits) + message(STATUS "Available Kits: ${kits}") + if(RunCMake_GENERATOR MATCHES "^Visual Studio 14 ") + set(kitMax 10.0.14393.0) + else() + set(kitMax "") + endif() + if(kitMax) + set(kitsIn "${kits}") + set(kits "") + foreach(kit IN LISTS kitsIn) + if(kit VERSION_LESS_EQUAL "${kitMax}") + list(APPEND kits "${kit}") + else() + message(STATUS "Excluding Kit ${kit} > ${kitMax}") + endif() + endforeach() + endif() + elseif(NOT RunCMake_GENERATOR MATCHES "^Visual Studio 14 ") + message(FATAL_ERROR "Could not find any Windows SDKs to drive test cases.") + endif() + + if(kits) + foreach(expect_version IN LISTS kits) + set(RunCMake_GENERATOR_PLATFORM "version=${expect_version}") + set(RunCMake_TEST_VARIANT_DESCRIPTION "-${expect_version}") + run_cmake_with_options(VersionExists -DCMAKE_SYSTEM_VERSION=10.0) + unset(RunCMake_GENERATOR_PLATFORM) + endforeach() + endif() endif() diff --git a/Tests/RunCMake/GeneratorPlatform/VersionExists-check.cmake b/Tests/RunCMake/GeneratorPlatform/VersionExists-check.cmake new file mode 100644 index 0000000..6c3c8e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/VersionExists-check.cmake @@ -0,0 +1,9 @@ +if(actual_stdout MATCHES "CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION='([^']+)'") + set(actual_version "${CMAKE_MATCH_1}") + if(NOT "${actual_version}" STREQUAL "${expect_version}") + set(RunCMake_TEST_FAILED "Actual SDK version '${actual_version}' did not match expected '${expect_version}'") + return() + endif() +else() + set(RunCMake_TEST_FAILED "No CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION found in output.") +endif() diff --git a/Tests/RunCMake/GeneratorPlatform/VersionExists.cmake b/Tests/RunCMake/GeneratorPlatform/VersionExists.cmake new file mode 100644 index 0000000..0d7a9ba --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/VersionExists.cmake @@ -0,0 +1 @@ +message(STATUS "CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION='${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}'") |