From 1c8d4b4bf186356b82addbac56c14426a7833316 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 5 Apr 2023 07:56:25 -0400 Subject: Tests: Teach RunCMake_TEST_FILTER to account for test variant description --- Tests/RunCMake/RunCMake.cmake | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index e1c923d..8eb23a6 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -11,8 +11,12 @@ foreach( endforeach() function(run_cmake test) - if(DEFINED ENV{RunCMake_TEST_FILTER} AND NOT test MATCHES "$ENV{RunCMake_TEST_FILTER}") - return() + if(DEFINED ENV{RunCMake_TEST_FILTER}) + set(test_and_variant "${test}${RunCMake_TEST_VARIANT_DESCRIPTION}") + if(NOT test_and_variant MATCHES "$ENV{RunCMake_TEST_FILTER}") + return() + endif() + unset(test_and_variant) endif() set(top_src "${RunCMake_SOURCE_DIR}") -- cgit v0.12 From 8499374c6a7114d83a8768edd611caf02d9941a1 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 31 Mar 2023 18:41:25 -0400 Subject: VS: Simplify logic to require SDK for Windows Store Revise logic added by commit d7e863c1c1 (VS: Do not fail on Windows 10 with VS 2015 if no SDK is available, 2016-01-21, v3.4.3~1^2) to make the requirement decision locally and simplify signatures. --- Source/cmGlobalVisualStudio14Generator.cxx | 22 ++++++++++++---------- Source/cmGlobalVisualStudio14Generator.h | 2 +- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 2 +- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 7424ca3..4b59b16 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -140,7 +140,7 @@ bool cmGlobalVisualStudio14Generator::MatchesGeneratorName( bool cmGlobalVisualStudio14Generator::InitializeWindows(cmMakefile* mf) { if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { - return this->SelectWindows10SDK(mf, false); + return this->SelectWindows10SDK(mf); } return true; } @@ -163,7 +163,7 @@ bool cmGlobalVisualStudio14Generator::InitializeWindowsStore(cmMakefile* mf) return false; } if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { - return this->SelectWindows10SDK(mf, true); + return this->SelectWindows10SDK(mf); } return true; } @@ -173,19 +173,21 @@ bool cmGlobalVisualStudio14Generator::InitializeAndroid(cmMakefile*) return true; } -bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf, - bool required) +bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf) { // Find the default version of the Windows 10 SDK. std::string const version = this->GetWindows10SDKVersion(mf); - if (required && version.empty()) { - std::ostringstream e; - e << "Could not find an appropriate version of the Windows 10 SDK" - << " installed on this machine"; - mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); - return false; + if (version.empty()) { + if (this->SystemName == "WindowsStore") { + mf->IssueMessage( + MessageType::FATAL_ERROR, + "Could not find an appropriate version of the Windows 10 SDK" + " installed on this machine"); + return false; + } } + this->SetWindowsTargetPlatformVersion(version, mf); return true; } diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index 7fb9b4b..30e8b18 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -47,7 +47,7 @@ protected: // version of the toolset. virtual std::string GetWindows10SDKMaxVersionDefault(cmMakefile* mf) const; - virtual bool SelectWindows10SDK(cmMakefile* mf, bool required); + virtual bool SelectWindows10SDK(cmMakefile* mf); void SetWindowsTargetPlatformVersion(std::string const& version, cmMakefile* mf); diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 415eb7c..f4a4d3d 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -900,7 +900,7 @@ bool cmGlobalVisualStudioVersionedGenerator::InitializeWindows(cmMakefile* mf) } // Otherwise we must choose a Win 10 SDK even if we are not targeting // Windows 10. - return this->SelectWindows10SDK(mf, false); + return this->SelectWindows10SDK(mf); } bool cmGlobalVisualStudioVersionedGenerator::SelectWindowsStoreToolset( -- cgit v0.12 From e259063b0a52768dfb1960401b363437e30baf40 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 31 Mar 2023 13:21:29 -0400 Subject: VS: Defer Windows SDK selection until CMAKE_GENERATOR_PLATFORM is known Prepare to teach `CMAKE_GENERATOR_PLATFORM` to affect SDK selection. --- Source/cmGlobalVisualStudio10Generator.cxx | 15 +++++++++++++++ Source/cmGlobalVisualStudio10Generator.h | 3 +++ Source/cmGlobalVisualStudio14Generator.cxx | 5 +---- Source/cmGlobalVisualStudio14Generator.h | 3 ++- Source/cmGlobalVisualStudio8Generator.cxx | 9 +++++++++ Source/cmGlobalVisualStudio8Generator.h | 2 ++ Source/cmGlobalVisualStudioVersionedGenerator.cxx | 5 +++-- Source/cmGlobalVisualStudioVersionedGenerator.h | 3 ++- 8 files changed, 37 insertions(+), 8 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 1e01dd6..41d54e5 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -525,6 +525,21 @@ bool cmGlobalVisualStudio10Generator::InitializeAndroid(cmMakefile* mf) return false; } +bool cmGlobalVisualStudio10Generator::InitializePlatform(cmMakefile* mf) +{ + if (this->SystemName == "Windows" || this->SystemName == "WindowsStore") { + if (!this->InitializePlatformWindows(mf)) { + return false; + } + } + return this->cmGlobalVisualStudio8Generator::InitializePlatform(mf); +} + +bool cmGlobalVisualStudio10Generator::InitializePlatformWindows(cmMakefile*) +{ + return true; +} + bool cmGlobalVisualStudio10Generator::SelectWindowsPhoneToolset( std::string& toolset) const { diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index deed206..63cfe72 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -183,6 +183,9 @@ protected: virtual bool InitializeTegraAndroid(cmMakefile* mf); virtual bool InitializeAndroid(cmMakefile* mf); + bool InitializePlatform(cmMakefile* mf) override; + virtual bool InitializePlatformWindows(cmMakefile* mf); + virtual bool ProcessGeneratorToolsetField(std::string const& key, std::string const& value); diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 4b59b16..87c8a5e 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -137,7 +137,7 @@ bool cmGlobalVisualStudio14Generator::MatchesGeneratorName( return false; } -bool cmGlobalVisualStudio14Generator::InitializeWindows(cmMakefile* mf) +bool cmGlobalVisualStudio14Generator::InitializePlatformWindows(cmMakefile* mf) { if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { return this->SelectWindows10SDK(mf); @@ -162,9 +162,6 @@ bool cmGlobalVisualStudio14Generator::InitializeWindowsStore(cmMakefile* mf) mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } - if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { - return this->SelectWindows10SDK(mf); - } return true; } diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index 30e8b18..0f016b3 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -30,7 +30,6 @@ protected: cmGlobalVisualStudio14Generator(cmake* cm, const std::string& name, std::string const& platformInGeneratorName); - bool InitializeWindows(cmMakefile* mf) override; bool InitializeWindowsStore(cmMakefile* mf) override; bool InitializeAndroid(cmMakefile* mf) override; bool SelectWindowsStoreToolset(std::string& toolset) const override; @@ -39,6 +38,8 @@ protected: // of the toolset is installed bool IsWindowsStoreToolsetInstalled() const; + bool InitializePlatformWindows(cmMakefile* mf) override; + // Used to adjust the max-SDK-version calculation to accommodate user // configuration. std::string GetWindows10SDKMaxVersion(cmMakefile* mf) const; diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 2e2c8b6..c33a3c9 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -114,12 +114,21 @@ bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p, *targetFrameworkTargetsVersion); } + if (!this->InitializePlatform(mf)) { + return false; + } + // The generator name does not contain the platform name, and so supports // explicit platform specification. We handled that above, so pass an // empty platform name to our base class implementation so it does not error. return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf); } +bool cmGlobalVisualStudio8Generator::InitializePlatform(cmMakefile*) +{ + return true; +} + cm::optional const& cmGlobalVisualStudio8Generator::GetTargetFrameworkVersion() const { diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index fe57c54..34e9fab 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -60,6 +60,8 @@ protected: cmGlobalVisualStudio8Generator(cmake* cm, const std::string& name, std::string const& platformInGeneratorName); + virtual bool InitializePlatform(cmMakefile* mf); + void AddExtraIDETargets() override; std::string FindDevEnvCommand() override; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index f4a4d3d..f3936ce 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -885,7 +885,8 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset( return AuxToolset::PropsMissing; } -bool cmGlobalVisualStudioVersionedGenerator::InitializeWindows(cmMakefile* mf) +bool cmGlobalVisualStudioVersionedGenerator::InitializePlatformWindows( + cmMakefile* mf) { // If the Win 8.1 SDK is installed then we can select a SDK matching // the target Windows version. @@ -896,7 +897,7 @@ bool cmGlobalVisualStudioVersionedGenerator::InitializeWindows(cmMakefile* mf) this->SetWindowsTargetPlatformVersion("8.1", mf); return true; } - return cmGlobalVisualStudio14Generator::InitializeWindows(mf); + return cmGlobalVisualStudio14Generator::InitializePlatformWindows(mf); } // Otherwise we must choose a Win 10 SDK even if we are not targeting // Windows 10. diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index 45aca74..fb4b1d7 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -61,7 +61,6 @@ protected: VSVersion version, cmake* cm, const std::string& name, std::string const& platformInGeneratorName); - bool InitializeWindows(cmMakefile* mf) override; bool SelectWindowsStoreToolset(std::string& toolset) const override; // Used to verify that the Desktop toolset for the current generator is @@ -72,6 +71,8 @@ protected: // of the toolset is installed bool IsWindowsStoreToolsetInstalled() const; + bool InitializePlatformWindows(cmMakefile* mf) override; + // Check for a Win 8 SDK known to the registry or VS installer tool. bool IsWin81SDKInstalled() const; -- cgit v0.12 From f0a67b629192466cec463c41df56ef3244817f70 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 31 Mar 2023 12:41:52 -0400 Subject: VS: Parse comma-separated fields from CMAKE_GENERATOR_PLATFORM --- Help/variable/CMAKE_GENERATOR_PLATFORM.rst | 16 ++++- Source/cmGlobalVisualStudio8Generator.cxx | 83 +++++++++++++++++++++- Source/cmGlobalVisualStudio8Generator.h | 6 ++ .../GeneratorPlatform/BadFieldNoComma-result.txt | 1 + .../GeneratorPlatform/BadFieldNoComma-stderr.txt | 11 +++ .../GeneratorPlatform/BadFieldNoComma.cmake | 1 + .../GeneratorPlatform/BadFieldUnknown-result.txt | 1 + .../GeneratorPlatform/BadFieldUnknown-stderr.txt | 11 +++ .../GeneratorPlatform/BadFieldUnknown.cmake | 1 + .../RunCMake/GeneratorPlatform/RunCMakeTest.cmake | 7 ++ 10 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 Tests/RunCMake/GeneratorPlatform/BadFieldNoComma-result.txt create mode 100644 Tests/RunCMake/GeneratorPlatform/BadFieldNoComma-stderr.txt create mode 100644 Tests/RunCMake/GeneratorPlatform/BadFieldNoComma.cmake create mode 100644 Tests/RunCMake/GeneratorPlatform/BadFieldUnknown-result.txt create mode 100644 Tests/RunCMake/GeneratorPlatform/BadFieldUnknown-stderr.txt create mode 100644 Tests/RunCMake/GeneratorPlatform/BadFieldUnknown.cmake diff --git a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst index acb7b2e..0238183 100644 --- a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst +++ b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst @@ -29,5 +29,17 @@ See native build system documentation for allowed platform names. Visual Studio Platform Selection ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -On :ref:`Visual Studio Generators` the selected platform name -is provided in the :variable:`CMAKE_VS_PLATFORM_NAME` variable. +The :ref:`Visual Studio Generators` support platform specification +using one of these forms: + +* ``platform`` +* ``platform[,key=value]*`` +* ``key=value[,key=value]*`` + +The ``platform`` specifies the target platform (VS target architecture), +such as ``x64``, ``ARM64``, or ``Win32``. The selected platform +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. diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index c33a3c9..2aba46f 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -94,7 +94,9 @@ bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p, return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform(p, mf); } - this->GeneratorPlatform = p; + if (!this->ParseGeneratorPlatform(p, mf)) { + return false; + } // FIXME: Add CMAKE_GENERATOR_PLATFORM field to set the framework. // For now, just report the generator's default, if any. @@ -124,6 +126,85 @@ bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p, return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf); } +bool cmGlobalVisualStudio8Generator::ParseGeneratorPlatform( + std::string const& p, cmMakefile* mf) +{ + this->GeneratorPlatform.clear(); + + std::vector const fields = cmTokenize(p, ","); + auto fi = fields.begin(); + if (fi == fields.end()) { + return true; + } + + // The first field may be the VS platform. + if (fi->find('=') == fi->npos) { + this->GeneratorPlatform = *fi; + ++fi; + } + + std::set handled; + + // The rest of the fields must be key=value pairs. + for (; fi != fields.end(); ++fi) { + std::string::size_type pos = fi->find('='); + if (pos == fi->npos) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given platform specification\n" + " " << p << "\n" + "that contains a field after the first ',' with no '='." + ; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + std::string const key = fi->substr(0, pos); + std::string const value = fi->substr(pos + 1); + if (!handled.insert(key).second) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given platform specification\n" + " " << p << "\n" + "that contains duplicate field key '" << key << "'." + ; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + if (!this->ProcessGeneratorPlatformField(key, value)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given platform specification\n" + " " << p << "\n" + "that contains invalid field '" << *fi << "'." + ; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + } + + return true; +} + +bool cmGlobalVisualStudio8Generator::ProcessGeneratorPlatformField( + std::string const& key, std::string const& value) +{ + static_cast(key); + static_cast(value); + return false; +} + bool cmGlobalVisualStudio8Generator::InitializePlatform(cmMakefile*) { return true; diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index 34e9fab..5555e9b 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -62,6 +62,9 @@ protected: virtual bool InitializePlatform(cmMakefile* mf); + virtual bool ProcessGeneratorPlatformField(std::string const& key, + std::string const& value); + void AddExtraIDETargets() override; std::string FindDevEnvCommand() override; @@ -98,4 +101,7 @@ protected: cm::optional DefaultTargetFrameworkVersion; cm::optional DefaultTargetFrameworkIdentifier; cm::optional DefaultTargetFrameworkTargetsVersion; + +private: + bool ParseGeneratorPlatform(std::string const& is, cmMakefile* mf); }; diff --git a/Tests/RunCMake/GeneratorPlatform/BadFieldNoComma-result.txt b/Tests/RunCMake/GeneratorPlatform/BadFieldNoComma-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadFieldNoComma-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorPlatform/BadFieldNoComma-stderr.txt b/Tests/RunCMake/GeneratorPlatform/BadFieldNoComma-stderr.txt new file mode 100644 index 0000000..b2098bd --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadFieldNoComma-stderr.txt @@ -0,0 +1,11 @@ +^CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + Visual Studio [^ +]+ + + given platform specification + + Test Platform,nocomma + + that contains a field after the first ',' with no '='\.$ diff --git a/Tests/RunCMake/GeneratorPlatform/BadFieldNoComma.cmake b/Tests/RunCMake/GeneratorPlatform/BadFieldNoComma.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadFieldNoComma.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorPlatform/BadFieldUnknown-result.txt b/Tests/RunCMake/GeneratorPlatform/BadFieldUnknown-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadFieldUnknown-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorPlatform/BadFieldUnknown-stderr.txt b/Tests/RunCMake/GeneratorPlatform/BadFieldUnknown-stderr.txt new file mode 100644 index 0000000..654f920 --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadFieldUnknown-stderr.txt @@ -0,0 +1,11 @@ +^CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + Visual Studio [^ +]+ + + given platform specification + + Test Platform,unknown= + + that contains invalid field 'unknown='\.$ diff --git a/Tests/RunCMake/GeneratorPlatform/BadFieldUnknown.cmake b/Tests/RunCMake/GeneratorPlatform/BadFieldUnknown.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorPlatform/BadFieldUnknown.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 a7519c3..fac15b8 100644 --- a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake @@ -26,3 +26,10 @@ else() run_cmake(BadPlatformToolchain) unset(RunCMake_TEST_OPTIONS) endif() + +if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio (1[4567])( 20[0-9][0-9])?$") + set(RunCMake_GENERATOR_PLATFORM "Test Platform,nocomma") + run_cmake(BadFieldNoComma) + set(RunCMake_GENERATOR_PLATFORM "Test Platform,unknown=") + run_cmake(BadFieldUnknown) +endif() -- cgit v0.12 From 2f3d945f8382fef4139c7d0c3879f6ff2f3756a0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 3 Apr 2023 10:11:49 -0400 Subject: 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 --- Help/manual/cmake-toolchains.7.rst | 9 +-- Help/release/dev/vs-sdk-selection.rst | 7 +++ Help/variable/CMAKE_GENERATOR_PLATFORM.rst | 24 +++++++- .../CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst | 18 ++++-- ..._VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM.rst | 4 +- Source/cmGlobalVisualStudio10Generator.cxx | 9 +++ Source/cmGlobalVisualStudio10Generator.h | 2 + Source/cmGlobalVisualStudio14Generator.cxx | 71 +++++++++++++++++++++- Source/cmGlobalVisualStudio14Generator.h | 10 +++ Source/cmGlobalVisualStudioVersionedGenerator.cxx | 3 +- .../GeneratorPlatform/BadVersionEmpty-result.txt | 1 + .../GeneratorPlatform/BadVersionEmpty-stderr.txt | 11 ++++ .../GeneratorPlatform/BadVersionEmpty.cmake | 1 + .../GeneratorPlatform/BadVersionMissing-result.txt | 1 + .../GeneratorPlatform/BadVersionMissing-stderr.txt | 11 ++++ .../GeneratorPlatform/BadVersionMissing.cmake | 1 + .../BadVersionPlatform-result.txt | 1 + .../BadVersionPlatform-stderr.txt | 19 ++++++ .../GeneratorPlatform/BadVersionPlatform.cmake | 1 + .../RunCMake/GeneratorPlatform/RunCMakeTest.cmake | 49 +++++++++++++++ .../GeneratorPlatform/VersionExists-check.cmake | 9 +++ .../RunCMake/GeneratorPlatform/VersionExists.cmake | 1 + 22 files changed, 248 insertions(+), 15 deletions(-) create mode 100644 Help/release/dev/vs-sdk-selection.rst create mode 100644 Tests/RunCMake/GeneratorPlatform/BadVersionEmpty-result.txt create mode 100644 Tests/RunCMake/GeneratorPlatform/BadVersionEmpty-stderr.txt create mode 100644 Tests/RunCMake/GeneratorPlatform/BadVersionEmpty.cmake create mode 100644 Tests/RunCMake/GeneratorPlatform/BadVersionMissing-result.txt create mode 100644 Tests/RunCMake/GeneratorPlatform/BadVersionMissing-stderr.txt create mode 100644 Tests/RunCMake/GeneratorPlatform/BadVersionMissing.cmake create mode 100644 Tests/RunCMake/GeneratorPlatform/BadVersionPlatform-result.txt create mode 100644 Tests/RunCMake/GeneratorPlatform/BadVersionPlatform-stderr.txt create mode 100644 Tests/RunCMake/GeneratorPlatform/BadVersionPlatform.cmake create mode 100644 Tests/RunCMake/GeneratorPlatform/VersionExists-check.cmake create mode 100644 Tests/RunCMake/GeneratorPlatform/VersionExists.cmake 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=`` + .. 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 ```` may be one of: + + ``10.0..`` + 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) 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 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 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 #include +#include + #include "cmGlobalVisualStudio12Generator.h" class cmGlobalGeneratorFactory; @@ -39,6 +41,12 @@ protected: bool IsWindowsStoreToolsetInstalled() const; bool InitializePlatformWindows(cmMakefile* mf) override; + bool VerifyNoGeneratorPlatformVersion( + cmMakefile* mf, + cm::optional 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 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}'") -- cgit v0.12 From b512c53d43b6078c97e06231ccbfa8599a66a4f4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 3 Apr 2023 10:56:47 -0400 Subject: VS: Add support for setting WindowsTargetPlatformVersion to 10.0 VS 2019 and above support this value to select a SDK version automatically. Fixes: #21403 --- Help/variable/CMAKE_GENERATOR_PLATFORM.rst | 4 ++++ Source/cmGlobalVisualStudio14Generator.cxx | 10 ++++++++++ Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake | 8 ++++++++ 3 files changed, 22 insertions(+) diff --git a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst index 3b6932a..416ff60 100644 --- a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst +++ b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst @@ -56,6 +56,10 @@ Supported pairs are: The ```` may be one of: + ``10.0`` + Specify that any 10.0 SDK version may be used, and let Visual Studio + pick one. This is supported by VS 2019 and above. + ``10.0..`` 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 diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 9ae80bb..57082f4 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -355,6 +355,16 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion( cmMakefile* mf) { #if defined(_WIN32) && !defined(__CYGWIN__) + // Accept specific version requests as-is. + if (this->GeneratorPlatformVersion) { + std::string const& ver = *this->GeneratorPlatformVersion; + + // VS 2019 and above support specifying plain "10.0". + if (this->Version >= VSVersion::VS16 && ver == "10.0") { + return ver; + } + } + std::vector win10Roots; { diff --git a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake index 00a32a2..96c2b6b 100644 --- a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake @@ -39,6 +39,14 @@ if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio (1[4567])( 20[0-9][0-9])?$") set(RunCMake_GENERATOR_PLATFORM "version=8.1") run_cmake_with_options(BadVersionPlatform -DCMAKE_SYSTEM_VERSION=8.1) + if(NOT RunCMake_GENERATOR MATCHES "^Visual Studio (1[45]) ") + set(expect_version "10.0") + 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) + endif() + set(kits "") cmake_host_system_information(RESULT kitsRoot10 QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/Microsoft/Windows Kits/Installed Roots" -- cgit v0.12 From f90c8ab54ebd751600f525a3e548841e6aa16049 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 3 Apr 2023 11:12:18 -0400 Subject: VS: Select latest available Windows SDK version by default Add policy `CMP0149` to stop preferring SDKs exactly matching `CMAKE_SYSTEM_VERSION` over the latest SDK. Fixes: #16202 --- Help/manual/cmake-policies.7.rst | 1 + Help/policy/CMP0149.rst | 47 ++++++++++++++++++++++ .../CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst | 3 ++ Source/cmGlobalVisualStudio14Generator.cxx | 11 +++-- Source/cmPolicies.h | 3 ++ .../RunCMake/GeneratorPlatform/RunCMakeTest.cmake | 11 +++++ .../RunCMake/GeneratorPlatform/VersionExists.cmake | 3 ++ 7 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 Help/policy/CMP0149.rst diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 158bf62..8c7189a 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.27 .. toctree:: :maxdepth: 1 + CMP0149: Visual Studio generators select latest Windows SDK by default. CMP0148: The FindPythonInterp and FindPythonLibs modules are removed. CMP0147: Visual Studio generators build custom commands in parallel. CMP0146: The FindCUDA module is removed. diff --git a/Help/policy/CMP0149.rst b/Help/policy/CMP0149.rst new file mode 100644 index 0000000..714eeaf --- /dev/null +++ b/Help/policy/CMP0149.rst @@ -0,0 +1,47 @@ +CMP0149 +------- + +.. versionadded:: 3.27 + +:ref:`Visual Studio Generators` select latest Windows SDK by default. + +Visual Studio Generators select a Windows SDK version to put in the +``WindowsTargetPlatformVersion`` setting in ``.vcxproj`` files. +CMake sets the :variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION` +variable to the selected SDK version. + +Prior to CMake 3.27, the SDK version was always selected by the value of +the :variable:`CMAKE_SYSTEM_VERSION` variable. Users or toolchain files +could set that variable to one of the exact Windows SDK versions available +on the host system. Since :variable:`CMAKE_SYSTEM_VERSION` defaults to +:variable:`CMAKE_HOST_SYSTEM_VERSION`, and it is not guaranteed that a +matching Windows SDK version is available, CMake had to fall back to +using the latest Windows SDK version if no exact match was available. +This approach was problematic: + +* The latest Windows SDK might or might not be selected based on whether + the host version of Windows happens to match an available SDK version. + +* An old Windows SDK version might be selected that has not been updated + for newer language standards such as C11. + +CMake 3.27 and higher prefer to ignore the exact value of +:variable:`CMAKE_SYSTEM_VERSION` and by default select the latest SDK +version available. An exact SDK version may be specified explicitly +using a ``version=`` field in the :variable:`CMAKE_GENERATOR_PLATFORM` +variable. See :ref:`Visual Studio Platform Selection`. + +This policy provides compatibility for projects, toolchain files, and +build scripts that have not been ported away from using +:variable:`CMAKE_SYSTEM_VERSION` to specify an exact SDK version. + +The ``OLD`` behavior for this policy is to use the exact value of +:variable:`CMAKE_SYSTEM_VERSION` if possible. The ``NEW`` behavior +for this policy is to ignore it. + +This policy was introduced in CMake version 3.27. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike many policies, CMake version |release| does *not* warn +when this policy is not set and simply uses ``OLD`` behavior. + +.. include:: DEPRECATED.txt diff --git a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst index 4a3ef47..d69bb7b 100644 --- a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst +++ b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst @@ -15,6 +15,9 @@ VS 2015 and above support specification of a Windows SDK version: * Otherwise, if :variable:`CMAKE_SYSTEM_VERSION` is set to an available SDK version, that version is selected. + .. versionchanged:: 3.27 + This is disabled by policy :policy:`CMP0149`. + * Otherwise, CMake uses the latest Windows SDK version available. The chosen Windows target version number is provided diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 57082f4..0f9a334 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -12,6 +12,7 @@ #include "cmGlobalVisualStudioGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -436,10 +437,12 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion( 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; + if (mf->GetPolicyStatus(cmPolicies::CMP0149) != cmPolicies::NEW) { + // 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/cmPolicies.h b/Source/cmPolicies.h index 37d697f..fe88382 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -447,6 +447,9 @@ class cmMakefile; 27, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0148, \ "The FindPythonInterp and FindPythonLibs modules are removed.", 3, \ + 27, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0149, \ + "Visual Studio generators select latest Windows SDK by default.", 3, \ 27, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) diff --git a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake index 96c2b6b..ffd105c 100644 --- a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake @@ -88,5 +88,16 @@ if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio (1[4567])( 20[0-9][0-9])?$") run_cmake_with_options(VersionExists -DCMAKE_SYSTEM_VERSION=10.0) unset(RunCMake_GENERATOR_PLATFORM) endforeach() + foreach(expect_version IN LISTS kits) + set(RunCMake_TEST_VARIANT_DESCRIPTION "-CMP0149-OLD-${expect_version}") + run_cmake_with_options(VersionExists -DCMAKE_SYSTEM_VERSION=${expect_version} -DCMAKE_POLICY_DEFAULT_CMP0149=OLD) + endforeach() + if(kits MATCHES "(^|;)([0-9.]+)$") + set(expect_version "${CMAKE_MATCH_2}") + foreach(test_version IN LISTS kits) + set(RunCMake_TEST_VARIANT_DESCRIPTION "-CMP0149-NEW-${test_version}") + run_cmake_with_options(VersionExists -DCMAKE_SYSTEM_VERSION=${test_version} -DCMAKE_POLICY_DEFAULT_CMP0149=NEW) + endforeach() + endif() endif() endif() diff --git a/Tests/RunCMake/GeneratorPlatform/VersionExists.cmake b/Tests/RunCMake/GeneratorPlatform/VersionExists.cmake index 0d7a9ba..5369ca0 100644 --- a/Tests/RunCMake/GeneratorPlatform/VersionExists.cmake +++ b/Tests/RunCMake/GeneratorPlatform/VersionExists.cmake @@ -1 +1,4 @@ +cmake_policy(GET CMP0149 cmp0149) +message(STATUS "CMP0149='${cmp0149}'") +message(STATUS "CMAKE_SYSTEM_VERSION='${CMAKE_SYSTEM_VERSION}'") message(STATUS "CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION='${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}'") -- cgit v0.12 From 8ecb6459345c550b77d8f689ed397137f2855fca Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 3 Apr 2023 11:24:55 -0400 Subject: VS: Select Windows SDK matching WindowsSDKVersion env var In an environment established by `vcvarsall.bat` or similar, this environment variable may be set to select a Windows SDK version. If the VS generator is used in such an environment, use that SDK. This is similar to how `CMAKE_GENERATOR_INSTANCE` defaults using a `VS##0COMNTOOLS` environment variable. Fixes: #17992 --- Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst | 8 ++++++++ Source/cmGlobalVisualStudio14Generator.cxx | 12 +++++++++++- Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake | 8 ++++++++ Tests/RunCMake/GeneratorPlatform/VersionExists.cmake | 1 + 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst index d69bb7b..2c14d39 100644 --- a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst +++ b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst @@ -12,6 +12,14 @@ VS 2015 and above support specification of a Windows SDK version: as documented by :ref:`Visual Studio Platform Selection`, that SDK version is selected. +* Otherwise, if the ``WindowsSDKVersion`` environment variable + is set to an available SDK version, that version is selected. + This is intended for use in environments established by ``vcvarsall.bat`` + or similar scripts. + + .. versionadded:: 3.27 + This is enabled by policy :policy:`CMP0149`. + * Otherwise, if :variable:`CMAKE_SYSTEM_VERSION` is set to an available SDK version, that version is selected. diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 0f9a334..4300d5c 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -437,7 +437,17 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion( return std::string(); } - if (mf->GetPolicyStatus(cmPolicies::CMP0149) != cmPolicies::NEW) { + if (mf->GetPolicyStatus(cmPolicies::CMP0149) == cmPolicies::NEW) { + if (cm::optional const envVer = + cmSystemTools::GetEnvVar("WindowsSDKVersion")) { + // Look for a SDK exactly matching the environment variable. + for (std::string const& i : sdks) { + if (cmSystemTools::VersionCompareEqual(i, *envVer)) { + return i; + } + } + } + } else { // Look for a SDK exactly matching the target Windows version. for (std::string const& i : sdks) { if (cmSystemTools::VersionCompareEqual(i, this->SystemVersion)) { diff --git a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake index ffd105c..233eb0a 100644 --- a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake @@ -28,6 +28,8 @@ else() endif() if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio (1[4567])( 20[0-9][0-9])?$") + unset(ENV{WindowsSDKVersion}) + set(RunCMake_GENERATOR_PLATFORM "Test Platform,nocomma") run_cmake(BadFieldNoComma) set(RunCMake_GENERATOR_PLATFORM "Test Platform,unknown=") @@ -99,5 +101,11 @@ if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio (1[4567])( 20[0-9][0-9])?$") run_cmake_with_options(VersionExists -DCMAKE_SYSTEM_VERSION=${test_version} -DCMAKE_POLICY_DEFAULT_CMP0149=NEW) endforeach() endif() + foreach(expect_version IN LISTS kits) + set(RunCMake_TEST_VARIANT_DESCRIPTION "-WindowsSDKVersion-${expect_version}") + set(ENV{WindowsSDKVersion} "${expect_version}\\") + run_cmake_with_options(VersionExists -DCMAKE_SYSTEM_VERSION=10.0 -DCMAKE_POLICY_DEFAULT_CMP0149=NEW) + unset(ENV{WindowsSDKVersion}) + endforeach() endif() endif() diff --git a/Tests/RunCMake/GeneratorPlatform/VersionExists.cmake b/Tests/RunCMake/GeneratorPlatform/VersionExists.cmake index 5369ca0..5c30e2b 100644 --- a/Tests/RunCMake/GeneratorPlatform/VersionExists.cmake +++ b/Tests/RunCMake/GeneratorPlatform/VersionExists.cmake @@ -1,4 +1,5 @@ cmake_policy(GET CMP0149 cmp0149) message(STATUS "CMP0149='${cmp0149}'") message(STATUS "CMAKE_SYSTEM_VERSION='${CMAKE_SYSTEM_VERSION}'") +message(STATUS "ENV{WindowsSDKVersion}='$ENV{WindowsSDKVersion}'") message(STATUS "CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION='${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}'") -- cgit v0.12