From 5f1316841944198037d6463d3ddd12efcfae45b3 Mon Sep 17 00:00:00 2001 From: Basil Fierz Date: Sat, 19 May 2018 13:23:21 +0200 Subject: VS: Add option to select the version of the toolset used by VS 2017 Add new `version=` parameter in the toolset setting to select the version. Add variable `CMAKE_VS_PLATFORM_TOOLSET_VERSION` to hold the version, if one is set (blank indicates default). Fixes: #17549 --- Help/manual/cmake-variables.7.rst | 1 + Help/release/dev/vs-toolset-version.rst | 7 ++ Help/variable/CMAKE_GENERATOR_TOOLSET.rst | 5 ++ .../variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION.rst | 11 +++ Modules/CMakeDetermineCompilerId.cmake | 4 + Modules/CompilerId/VS-10.vcxproj.in | 1 + Source/cmGlobalVisualStudio10Generator.cxx | 85 ++++++++++++++++++++++ Source/cmGlobalVisualStudio10Generator.h | 7 ++ Source/cmGlobalVisualStudio15Generator.cxx | 19 +++++ Source/cmGlobalVisualStudio15Generator.h | 2 + Source/cmVisualStudio10TargetGenerator.cxx | 5 ++ .../GeneratorToolset/BadToolsetVersion-result.txt | 1 + .../GeneratorToolset/BadToolsetVersion-stderr.txt | 10 +++ .../GeneratorToolset/BadToolsetVersion.cmake | 1 + .../BadToolsetVersionTwice-result.txt | 1 + .../BadToolsetVersionTwice-stderr.txt | 10 +++ .../GeneratorToolset/BadToolsetVersionTwice.cmake | 1 + Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake | 12 +++ .../TestToolsetVersionBoth-stdout.txt | 2 + .../GeneratorToolset/TestToolsetVersionBoth.cmake | 2 + .../TestToolsetVersionOnly-stdout.txt | 2 + .../GeneratorToolset/TestToolsetVersionOnly.cmake | 2 + 22 files changed, 191 insertions(+) create mode 100644 Help/release/dev/vs-toolset-version.rst create mode 100644 Help/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION.rst create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetVersion-result.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetVersion-stderr.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetVersion.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice-result.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice-stderr.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetVersionBoth-stdout.txt create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetVersionBoth.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetVersionOnly-stdout.txt create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetVersionOnly.cmake diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 0f8502c..edfff6c 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -100,6 +100,7 @@ Variables that Provide Information /variable/CMAKE_VS_PLATFORM_TOOLSET /variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA /variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE + /variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION /variable/CMAKE_XCODE_GENERATE_SCHEME /variable/CMAKE_XCODE_PLATFORM_TOOLSET diff --git a/Help/release/dev/vs-toolset-version.rst b/Help/release/dev/vs-toolset-version.rst new file mode 100644 index 0000000..239917e --- /dev/null +++ b/Help/release/dev/vs-toolset-version.rst @@ -0,0 +1,7 @@ +vs-toolset-version +------------------ + +* The :ref:`Visual Studio Generators` for VS 2017 learned to support a + ``version=14.##`` option in the :variable:`CMAKE_GENERATOR_TOOLSET` + value (e.g. via the :manual:`cmake(1)` ``-T`` option) to specify a + toolset version number. diff --git a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst index 11c37d7..3220244 100644 --- a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst +++ b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst @@ -48,3 +48,8 @@ Supported pairs are: Supported by VS 2013 and above. See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE` variable. + +``version=`` + Specify the toolset version to use. Supported by VS 2017 + and above with the specified toolset installed. + See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_VERSION` variable. diff --git a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION.rst b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION.rst new file mode 100644 index 0000000..4d9b978 --- /dev/null +++ b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION.rst @@ -0,0 +1,11 @@ +CMAKE_VS_PLATFORM_TOOLSET_VERSION +--------------------------------- + +Visual Studio Platform Toolset version. + +The :ref:`Visual Studio Generators` for VS 2017 and above allow to +select minor versions of the same toolset. The toolset version number +may be specified by a field in :variable:`CMAKE_GENERATOR_TOOLSET` of +the form ``version=14.11``. If none is specified CMake will choose a default +toolset. The value may be empty if no minor version was selected and the +default is used. diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index ea5465a..1628203 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -213,9 +213,13 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "Intel") set(id_cl icl.exe) endif() + if(CMAKE_VS_PLATFORM_TOOLSET_VERSION) + set(id_toolset_version_props "") + endif() endif() else() set(id_toolset "") + set(id_toolset_version_props "") endif() if(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE) set(id_PreferredToolArchitecture "${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}") diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in index 6b9b361..32c4ffc 100644 --- a/Modules/CompilerId/VS-10.vcxproj.in +++ b/Modules/CompilerId/VS-10.vcxproj.in @@ -15,6 +15,7 @@ @id_WindowsTargetPlatformVersion@ @id_WindowsSDKDesktopARMSupport@ + @id_toolset_version_props@ @id_PreferredToolArchitecture@ diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 205e0d0..eafddd6 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -231,9 +231,66 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( } } + if (!this->GeneratorToolsetVersion.empty() && + this->GeneratorToolsetVersion != "Test Toolset Version") { + // If a specific minor version of the toolset was requested, verify that it + // is compatible to the major version and that is exists on disk. + // If not clear the value. + std::string version = this->GeneratorToolsetVersion; + cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9][0-9]"); + if (regex.find(version)) { + version = "v" + version.erase(2, 1); + } else { + // Version not recognized. Clear it. + version.clear(); + } + + if (version.find(this->GetPlatformToolsetString()) != 0) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset and version specification\n" + " " << this->GetPlatformToolsetString() << ",version=" << + this->GeneratorToolsetVersion << "\n" + "contains an invalid version specification." + ; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + + // Clear the configured tool-set + this->GeneratorToolsetVersion.clear(); + } + + std::string const toolsetPath = this->GetAuxiliaryToolset(); + if (!toolsetPath.empty() && !cmSystemTools::FileExists(toolsetPath)) { + + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset and version specification\n" + " " << this->GetPlatformToolsetString() << ",version=" << + this->GeneratorToolsetVersion << "\n" + "does not seem to be installed at\n" << + " " << toolsetPath; + ; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + + // Clear the configured tool-set + this->GeneratorToolsetVersion.clear(); + } + } + if (const char* toolset = this->GetPlatformToolset()) { mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset); } + if (const char* version = this->GetPlatformToolsetVersion()) { + mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VERSION", version); + } if (const char* hostArch = this->GetPlatformToolsetHostArchitecture()) { mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE", hostArch); } @@ -319,6 +376,10 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( this->GeneratorToolsetCuda = value; return true; } + if (key == "version") { + this->GeneratorToolsetVersion = value; + return true; + } return false; } @@ -512,6 +573,25 @@ std::string const& cmGlobalVisualStudio10Generator::GetPlatformToolsetString() return empty; } +const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetVersion() const +{ + std::string const& version = this->GetPlatformToolsetVersionString(); + if (version.empty()) { + return nullptr; + } + return version.c_str(); +} + +std::string const& +cmGlobalVisualStudio10Generator::GetPlatformToolsetVersionString() const +{ + if (!this->GeneratorToolsetVersion.empty()) { + return this->GeneratorToolsetVersion; + } + static std::string const empty; + return empty; +} + const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitecture() const { @@ -535,6 +615,11 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaString() const return this->GeneratorToolsetCuda; } +std::string cmGlobalVisualStudio10Generator::GetAuxiliaryToolset() const +{ + return {}; +} + bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf) { if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) { diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index f2501c2..dcdab09 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -54,6 +54,10 @@ public: const char* GetPlatformToolset() const; std::string const& GetPlatformToolsetString() const; + /** The toolset version. */ + const char* GetPlatformToolsetVersion() const; + std::string const& GetPlatformToolsetVersionString() const; + /** The toolset host architecture name (e.g. x64 for 64-bit host tools). */ const char* GetPlatformToolsetHostArchitecture() const; @@ -101,6 +105,8 @@ public: std::string Encoding() override; virtual const char* GetToolsVersion() { return "4.0"; } + virtual std::string GetAuxiliaryToolset() const; + bool FindMakeProgram(cmMakefile* mf) override; static std::string GetInstalledNsightTegraVersion(); @@ -135,6 +141,7 @@ protected: std::string const& GetMSBuildCommand(); std::string GeneratorToolset; + std::string GeneratorToolsetVersion; std::string GeneratorToolsetHostArchitecture; std::string GeneratorToolsetCuda; std::string DefaultPlatformToolset; diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index 014d93d..6af5793 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -158,6 +158,25 @@ bool cmGlobalVisualStudio15Generator::GetVSInstance(std::string& dir) const return vsSetupAPIHelper.GetVSInstanceInfo(dir); } +std::string cmGlobalVisualStudio15Generator::GetAuxiliaryToolset() const +{ + const char* version = this->GetPlatformToolsetVersion(); + if (version) { + std::string instancePath; + GetVSInstance(instancePath); + std::stringstream path; + path << instancePath; + path << "/VC/Auxiliary/Build/"; + path << version; + path << "/Microsoft.VCToolsVersion." << version << ".props"; + + std::string toolsetPath = path.str(); + cmSystemTools::ConvertToUnixSlashes(toolsetPath); + return toolsetPath; + } + return {}; +} + bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile* mf) { // If the Win 8.1 SDK is installed then we can select a SDK matching diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h index 4f4e0b9..3b9cfc7 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudio15Generator.h @@ -32,6 +32,8 @@ public: bool GetVSInstance(std::string& dir) const; + std::string GetAuxiliaryToolset() const override; + protected: bool InitializeWindows(cmMakefile* mf) override; bool SelectWindowsStoreToolset(std::string& toolset) const override; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index f3b9c84..f16db76 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -557,6 +557,11 @@ void cmVisualStudio10TargetGenerator::Generate() switch (this->ProjectType) { case vcxproj: + if (this->GlobalGenerator->GetPlatformToolsetVersion()) { + Elem(e0, "Import") + .Attribute("Project", + this->GlobalGenerator->GetAuxiliaryToolset()); + } Elem(e0, "Import").Attribute("Project", VS10_CXX_DEFAULT_PROPS); break; case csproj: diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetVersion-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetVersion-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetVersion-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetVersion-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetVersion-stderr.txt new file mode 100644 index 0000000..c976f59 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetVersion-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + .* + + given toolset and version specification + + Test Toolset,version=Bad Toolset Version + + contains an invalid version specification. diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetVersion.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetVersion.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetVersion.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice-stderr.txt new file mode 100644 index 0000000..b780dad --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + .* + + given toolset specification + + Test Toolset,version=Test Toolset Version,version=Test Toolset Version + + that contains duplicate field key 'version'\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetVersionTwice.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index f89100e..d1738a0 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -25,6 +25,18 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]") run_cmake(BadToolsetHostArch) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x64") run_cmake(BadToolsetHostArchTwice) + if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 15") + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version") + run_cmake(TestToolsetVersionBoth) + set(RunCMake_GENERATOR_TOOLSET ",version=Test Toolset Version") + run_cmake(TestToolsetVersionOnly) + set(RunCMake_GENERATOR_TOOLSET "version=Test Toolset Version") + run_cmake(TestToolsetVersionOnly) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Bad Toolset Version") + run_cmake(BadToolsetVersion) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version,version=Test Toolset Version") + run_cmake(BadToolsetVersionTwice) + endif() else() set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(BadToolsetHostArch) diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetVersionBoth-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetVersionBoth-stdout.txt new file mode 100644 index 0000000..9b91fde --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetVersionBoth-stdout.txt @@ -0,0 +1,2 @@ +-- CMAKE_VS_PLATFORM_TOOLSET='Test Toolset' +-- CMAKE_VS_PLATFORM_TOOLSET_VERSION='Test Toolset Version' diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetVersionBoth.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetVersionBoth.cmake new file mode 100644 index 0000000..fbc75be --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetVersionBoth.cmake @@ -0,0 +1,2 @@ +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'") +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_VERSION='${CMAKE_VS_PLATFORM_TOOLSET_VERSION}'") diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetVersionOnly-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetVersionOnly-stdout.txt new file mode 100644 index 0000000..25c4163 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetVersionOnly-stdout.txt @@ -0,0 +1,2 @@ +-- CMAKE_VS_PLATFORM_TOOLSET='v[0-9]+' +-- CMAKE_VS_PLATFORM_TOOLSET_VERSION='Test Toolset Version' diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetVersionOnly.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetVersionOnly.cmake new file mode 100644 index 0000000..fbc75be --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetVersionOnly.cmake @@ -0,0 +1,2 @@ +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'") +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_VERSION='${CMAKE_VS_PLATFORM_TOOLSET_VERSION}'") -- cgit v0.12