mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-01 19:30:13 -06:00
VS: Add CMAKE_GENERATOR_PLATFORM field to control Windows SDK selection
Add a `version=` field to explicitly control the SDK version selection without relying on `CMAKE_SYSTEM_VERSION`. Fixes: #16713
This commit is contained in:
@@ -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
|
||||
---------------------------------
|
||||
|
||||
7
Help/release/dev/vs-sdk-selection.rst
Normal file
7
Help/release/dev/vs-sdk-selection.rst
Normal file
@@ -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`.
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
11
Tests/RunCMake/GeneratorPlatform/BadVersionEmpty-stderr.txt
Normal file
11
Tests/RunCMake/GeneratorPlatform/BadVersionEmpty-stderr.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
^CMake Error at CMakeLists.txt:[0-9]+ \(project\):
|
||||
Generator
|
||||
|
||||
Visual Studio [^
|
||||
]+
|
||||
|
||||
given platform specification with empty
|
||||
|
||||
version=
|
||||
|
||||
field\.$
|
||||
1
Tests/RunCMake/GeneratorPlatform/BadVersionEmpty.cmake
Normal file
1
Tests/RunCMake/GeneratorPlatform/BadVersionEmpty.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "This should not be reached!")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -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\.$
|
||||
1
Tests/RunCMake/GeneratorPlatform/BadVersionMissing.cmake
Normal file
1
Tests/RunCMake/GeneratorPlatform/BadVersionMissing.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "This should not be reached!")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -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\.)$
|
||||
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "This should not be reached!")
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
1
Tests/RunCMake/GeneratorPlatform/VersionExists.cmake
Normal file
1
Tests/RunCMake/GeneratorPlatform/VersionExists.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(STATUS "CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION='${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}'")
|
||||
Reference in New Issue
Block a user