From d8ed309d0529d9a7b28da561c3640290a8041b68 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 9 Jan 2019 09:40:53 -0500 Subject: VS: Parameterize cmVSSetupAPIHelper instances with VS version --- Source/cmCMakeHostSystemInformationCommand.cxx | 2 +- Source/cmGlobalVisualStudio15Generator.cxx | 3 ++- Source/cmVSSetupHelper.cxx | 18 +++++++++--------- Source/cmVSSetupHelper.h | 6 ++++-- Source/cmake.cxx | 3 +-- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 8822942..a2423ac 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -141,7 +141,7 @@ bool cmCMakeHostSystemInformationCommand::GetValue( } // Otherwise, find a VS 15 instance ourselves. - cmVSSetupAPIHelper vsSetupAPIHelper; + cmVSSetupAPIHelper vsSetupAPIHelper(15); if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { cmSystemTools::ConvertToUnixSlashes(value); } diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index eb49e87..f9fcbdf 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -79,6 +79,7 @@ cmGlobalVisualStudio15Generator::cmGlobalVisualStudio15Generator( cmake* cm, const std::string& name, std::string const& platformInGeneratorName) : cmGlobalVisualStudio14Generator(cm, name, platformInGeneratorName) + , vsSetupAPIHelper(15) { this->ExpressEdition = false; this->DefaultPlatformToolset = "v141"; @@ -215,7 +216,7 @@ bool cmGlobalVisualStudio15Generator::SelectWindowsStoreToolset( bool cmGlobalVisualStudio15Generator::IsWindowsDesktopToolsetInstalled() const { - return vsSetupAPIHelper.IsVS2017Installed(); + return vsSetupAPIHelper.IsVSInstalled(); } bool cmGlobalVisualStudio15Generator::IsWindowsStoreToolsetInstalled() const diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx index d80b5a2..9187c29 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -57,8 +57,9 @@ std::string VSInstanceInfo::GetInstallLocation() const return loc; } -cmVSSetupAPIHelper::cmVSSetupAPIHelper() - : setupConfig(NULL) +cmVSSetupAPIHelper::cmVSSetupAPIHelper(unsigned int version) + : Version(version) + , setupConfig(NULL) , setupConfig2(NULL) , setupHelper(NULL) , initializationFailure(false) @@ -88,7 +89,7 @@ bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation) return this->EnumerateAndChooseVSInstance(); } -bool cmVSSetupAPIHelper::IsVS2017Installed() +bool cmVSSetupAPIHelper::IsVSInstalled() { return this->EnumerateAndChooseVSInstance(); } @@ -312,11 +313,11 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() return false; std::string envVSCommonToolsDir; + std::string envVSCommonToolsDirEnvName = + "VS" + std::to_string(this->Version) + "0COMNTOOLS"; - // FIXME: When we support VS versions beyond 2017, the version - // to choose will be passed in by the caller. We need to map that - // to a per-version name of this environment variable. - if (cmSystemTools::GetEnv("VS150COMNTOOLS", envVSCommonToolsDir)) { + if (cmSystemTools::GetEnv(envVSCommonToolsDirEnvName.c_str(), + envVSCommonToolsDir)) { cmSystemTools::ConvertToUnixSlashes(envVSCommonToolsDir); } @@ -328,8 +329,7 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() return false; } - // FIXME: Add a way for caller to specify other versions. - std::wstring wantVersion = std::to_wstring(15) + L'.'; + std::wstring const wantVersion = std::to_wstring(this->Version) + L'.'; SmartCOMPtr instance; while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) { diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index b9cca45..4748a7a 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -120,12 +120,12 @@ struct VSInstanceInfo class cmVSSetupAPIHelper { public: - cmVSSetupAPIHelper(); + cmVSSetupAPIHelper(unsigned int version); ~cmVSSetupAPIHelper(); bool SetVSInstance(std::string const& vsInstallLocation); - bool IsVS2017Installed(); + bool IsVSInstalled(); bool GetVSInstanceInfo(std::string& vsInstallLocation); bool GetVCToolsetVersion(std::string& vsToolsetVersion); bool IsWin10SDKInstalled(); @@ -140,6 +140,8 @@ private: int ChooseVSInstance(const std::vector& vecVSInstances); bool EnumerateAndChooseVSInstance(); + unsigned int Version; + // COM ptrs to query about VS instances SmartCOMPtr setupConfig; SmartCOMPtr setupConfig2; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index e1bae34..195956b 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1538,8 +1538,7 @@ void cmake::CreateDefaultGlobalGenerator() "\\Setup\\VC;ProductDir", // ";InstallDir" // }; - cmVSSetupAPIHelper vsSetupAPIHelper; - if (vsSetupAPIHelper.IsVS2017Installed()) { + if (cmVSSetupAPIHelper(15).IsVSInstalled()) { found = "Visual Studio 15 2017"; } else { for (VSVersionedGenerator const* g = cm::cbegin(vsGenerators); -- cgit v0.12 From 68d316e0cf278021d9fa4553471d29803d09a394 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 9 Jan 2019 10:26:49 -0500 Subject: VS: Rename VS 2017 generator sources to be version-independent Rename `cmGlobalVisualStudio{15 => Versioned}Generator`. Rename `Factory` to `Factory15` since that part still needs to be version-specific. --- Source/CMakeLists.txt | 4 +- Source/cmCMakeHostSystemInformationCommand.cxx | 6 +- Source/cmGlobalVisualStudio15Generator.cxx | 286 --------------------- Source/cmGlobalVisualStudio15Generator.h | 60 ----- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 291 ++++++++++++++++++++++ Source/cmGlobalVisualStudioVersionedGenerator.h | 62 +++++ Source/cmake.cxx | 5 +- 7 files changed, 361 insertions(+), 353 deletions(-) delete mode 100644 Source/cmGlobalVisualStudio15Generator.cxx delete mode 100644 Source/cmGlobalVisualStudio15Generator.h create mode 100644 Source/cmGlobalVisualStudioVersionedGenerator.cxx create mode 100644 Source/cmGlobalVisualStudioVersionedGenerator.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 91c45bc..c87ceba 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -696,10 +696,10 @@ if (WIN32) cmGlobalVisualStudio12Generator.cxx cmGlobalVisualStudio14Generator.h cmGlobalVisualStudio14Generator.cxx - cmGlobalVisualStudio15Generator.h - cmGlobalVisualStudio15Generator.cxx cmGlobalVisualStudioGenerator.cxx cmGlobalVisualStudioGenerator.h + cmGlobalVisualStudioVersionedGenerator.h + cmGlobalVisualStudioVersionedGenerator.cxx cmIDEFlagTable.h cmIDEOptions.cxx cmIDEOptions.h diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index a2423ac..ddc32c0 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -10,7 +10,7 @@ #if defined(_WIN32) # include "cmAlgorithms.h" # include "cmGlobalGenerator.h" -# include "cmGlobalVisualStudio15Generator.h" +# include "cmGlobalVisualStudioVersionedGenerator.h" # include "cmSystemTools.h" # include "cmVSSetupHelper.h" # define HAVE_VS_SETUP_HELPER @@ -133,8 +133,8 @@ bool cmCMakeHostSystemInformationCommand::GetValue( // If generating for the VS 15 IDE, use the same instance. cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) { - cmGlobalVisualStudio15Generator* vs15gen = - static_cast(gg); + cmGlobalVisualStudioVersionedGenerator* vs15gen = + static_cast(gg); if (vs15gen->GetVSInstance(value)) { return true; } diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx deleted file mode 100644 index f9fcbdf..0000000 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ /dev/null @@ -1,286 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmGlobalVisualStudio15Generator.h" - -#include "cmAlgorithms.h" -#include "cmDocumentationEntry.h" -#include "cmLocalVisualStudio10Generator.h" -#include "cmMakefile.h" -#include "cmVSSetupHelper.h" - -static const char vs15generatorName[] = "Visual Studio 15 2017"; - -// Map generator name without year to name with year. -static const char* cmVS15GenName(const std::string& name, std::string& genName) -{ - if (strncmp(name.c_str(), vs15generatorName, - sizeof(vs15generatorName) - 6) != 0) { - return 0; - } - const char* p = name.c_str() + sizeof(vs15generatorName) - 6; - if (cmHasLiteralPrefix(p, " 2017")) { - p += 5; - } - genName = std::string(vs15generatorName) + p; - return p; -} - -class cmGlobalVisualStudio15Generator::Factory - : public cmGlobalGeneratorFactory -{ -public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override - { - std::string genName; - const char* p = cmVS15GenName(name, genName); - if (!p) { - return 0; - } - if (!*p) { - return new cmGlobalVisualStudio15Generator(cm, genName, ""); - } - if (*p++ != ' ') { - return 0; - } - if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio15Generator(cm, genName, "x64"); - } - if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio15Generator(cm, genName, "ARM"); - } - return 0; - } - - void GetDocumentation(cmDocumentationEntry& entry) const override - { - entry.Name = std::string(vs15generatorName) + " [arch]"; - entry.Brief = "Generates Visual Studio 2017 project files. " - "Optional [arch] can be \"Win64\" or \"ARM\"."; - } - - void GetGenerators(std::vector& names) const override - { - names.push_back(vs15generatorName); - names.push_back(vs15generatorName + std::string(" ARM")); - names.push_back(vs15generatorName + std::string(" Win64")); - } - - bool SupportsToolset() const override { return true; } - bool SupportsPlatform() const override { return true; } -}; - -cmGlobalGeneratorFactory* cmGlobalVisualStudio15Generator::NewFactory() -{ - return new Factory; -} - -cmGlobalVisualStudio15Generator::cmGlobalVisualStudio15Generator( - cmake* cm, const std::string& name, - std::string const& platformInGeneratorName) - : cmGlobalVisualStudio14Generator(cm, name, platformInGeneratorName) - , vsSetupAPIHelper(15) -{ - this->ExpressEdition = false; - this->DefaultPlatformToolset = "v141"; - this->DefaultCLFlagTableName = "v141"; - this->DefaultCSharpFlagTableName = "v141"; - this->DefaultLinkFlagTableName = "v141"; - this->Version = VS15; -} - -bool cmGlobalVisualStudio15Generator::MatchesGeneratorName( - const std::string& name) const -{ - std::string genName; - if (cmVS15GenName(name, genName)) { - return genName == this->GetName(); - } - return false; -} - -bool cmGlobalVisualStudio15Generator::SetGeneratorInstance( - std::string const& i, cmMakefile* mf) -{ - if (!i.empty()) { - if (!this->vsSetupAPIHelper.SetVSInstance(i)) { - std::ostringstream e; - /* clang-format off */ - e << - "Generator\n" - " " << this->GetName() << "\n" - "could not find specified instance of Visual Studio:\n" - " " << i; - /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; - } - } - - std::string vsInstance; - if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) { - std::ostringstream e; - /* clang-format off */ - e << - "Generator\n" - " " << this->GetName() << "\n" - "could not find any instance of Visual Studio.\n"; - /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; - } - - // Save the selected instance persistently. - std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"); - if (vsInstance != genInstance) { - this->CMakeInstance->AddCacheEntry( - "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(), - "Generator instance identifier.", cmStateEnums::INTERNAL); - } - - return true; -} - -bool cmGlobalVisualStudio15Generator::GetVSInstance(std::string& dir) const -{ - return vsSetupAPIHelper.GetVSInstanceInfo(dir); -} - -bool cmGlobalVisualStudio15Generator::IsDefaultToolset( - const std::string& version) const -{ - if (version.empty()) { - return true; - } - - std::string vcToolsetVersion; - if (this->vsSetupAPIHelper.GetVCToolsetVersion(vcToolsetVersion)) { - - cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9]+"); - if (regex.find(version) && regex.find(vcToolsetVersion)) { - const auto majorMinorEnd = vcToolsetVersion.find('.', 3); - const auto majorMinor = vcToolsetVersion.substr(0, majorMinorEnd); - return version == majorMinor; - } - } - - return false; -} - -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 - // the target Windows version. - if (this->IsWin81SDKInstalled()) { - return cmGlobalVisualStudio14Generator::InitializeWindows(mf); - } - // Otherwise we must choose a Win 10 SDK even if we are not targeting - // Windows 10. - return this->SelectWindows10SDK(mf, false); -} - -bool cmGlobalVisualStudio15Generator::SelectWindowsStoreToolset( - std::string& toolset) const -{ - if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { - if (this->IsWindowsStoreToolsetInstalled() && - this->IsWindowsDesktopToolsetInstalled()) { - toolset = "v141"; // VS 15 uses v141 toolset - return true; - } else { - return false; - } - } - return this->cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset( - toolset); -} - -bool cmGlobalVisualStudio15Generator::IsWindowsDesktopToolsetInstalled() const -{ - return vsSetupAPIHelper.IsVSInstalled(); -} - -bool cmGlobalVisualStudio15Generator::IsWindowsStoreToolsetInstalled() const -{ - return vsSetupAPIHelper.IsWin10SDKInstalled(); -} - -bool cmGlobalVisualStudio15Generator::IsWin81SDKInstalled() const -{ - // Does the VS installer tool know about one? - if (vsSetupAPIHelper.IsWin81SDKInstalled()) { - return true; - } - - // Does the registry know about one (e.g. from VS 2015)? - std::string win81Root; - if (cmSystemTools::ReadRegistryValue( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" - "Windows Kits\\Installed Roots;KitsRoot81", - win81Root, cmSystemTools::KeyWOW64_32) || - cmSystemTools::ReadRegistryValue( - "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\" - "Windows Kits\\Installed Roots;KitsRoot81", - win81Root, cmSystemTools::KeyWOW64_32)) { - return cmSystemTools::FileExists(win81Root + "/um/windows.h", true); - } - return false; -} - -std::string cmGlobalVisualStudio15Generator::GetWindows10SDKMaxVersion() const -{ - return std::string(); -} - -std::string cmGlobalVisualStudio15Generator::FindMSBuildCommand() -{ - std::string msbuild; - - // Ask Visual Studio Installer tool. - std::string vs; - if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { - msbuild = vs + "/MSBuild/15.0/Bin/MSBuild.exe"; - if (cmSystemTools::FileExists(msbuild)) { - return msbuild; - } - } - - msbuild = "MSBuild.exe"; - return msbuild; -} - -std::string cmGlobalVisualStudio15Generator::FindDevEnvCommand() -{ - std::string devenv; - - // Ask Visual Studio Installer tool. - std::string vs; - if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { - devenv = vs + "/Common7/IDE/devenv.com"; - if (cmSystemTools::FileExists(devenv)) { - return devenv; - } - } - - devenv = "devenv.com"; - return devenv; -} diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h deleted file mode 100644 index da85d23..0000000 --- a/Source/cmGlobalVisualStudio15Generator.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudio15Generator_h -#define cmGlobalVisualStudio15Generator_h - -#include "cmConfigure.h" // IWYU pragma: keep - -#include -#include - -#include "cmGlobalVisualStudio14Generator.h" -#include "cmVSSetupHelper.h" - -class cmGlobalGeneratorFactory; -class cmake; - -/** \class cmGlobalVisualStudio15Generator */ -class cmGlobalVisualStudio15Generator : public cmGlobalVisualStudio14Generator -{ -public: - static cmGlobalGeneratorFactory* NewFactory(); - - bool MatchesGeneratorName(const std::string& name) const override; - - bool SetGeneratorInstance(std::string const& i, cmMakefile* mf) override; - - bool GetVSInstance(std::string& dir) const; - - bool IsDefaultToolset(const std::string& version) const override; - std::string GetAuxiliaryToolset() const override; - -protected: - cmGlobalVisualStudio15Generator(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 - // installed on the machine. - bool IsWindowsDesktopToolsetInstalled() const override; - - // These aren't virtual because we need to check if the selected version - // of the toolset is installed - bool IsWindowsStoreToolsetInstalled() const; - - // Check for a Win 8 SDK known to the registry or VS installer tool. - bool IsWin81SDKInstalled() const; - - std::string GetWindows10SDKMaxVersion() const override; - - std::string FindMSBuildCommand() override; - std::string FindDevEnvCommand() override; - -private: - class Factory; - friend class Factory; - mutable cmVSSetupAPIHelper vsSetupAPIHelper; -}; -#endif diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx new file mode 100644 index 0000000..354af72 --- /dev/null +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -0,0 +1,291 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmGlobalVisualStudioVersionedGenerator.h" + +#include "cmAlgorithms.h" +#include "cmDocumentationEntry.h" +#include "cmLocalVisualStudio10Generator.h" +#include "cmMakefile.h" +#include "cmVSSetupHelper.h" + +static const char vs15generatorName[] = "Visual Studio 15 2017"; + +// Map generator name without year to name with year. +static const char* cmVS15GenName(const std::string& name, std::string& genName) +{ + if (strncmp(name.c_str(), vs15generatorName, + sizeof(vs15generatorName) - 6) != 0) { + return 0; + } + const char* p = name.c_str() + sizeof(vs15generatorName) - 6; + if (cmHasLiteralPrefix(p, " 2017")) { + p += 5; + } + genName = std::string(vs15generatorName) + p; + return p; +} + +class cmGlobalVisualStudioVersionedGenerator::Factory15 + : public cmGlobalGeneratorFactory +{ +public: + cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, + cmake* cm) const override + { + std::string genName; + const char* p = cmVS15GenName(name, genName); + if (!p) { + return 0; + } + if (!*p) { + return new cmGlobalVisualStudioVersionedGenerator(cm, genName, ""); + } + if (*p++ != ' ') { + return 0; + } + if (strcmp(p, "Win64") == 0) { + return new cmGlobalVisualStudioVersionedGenerator(cm, genName, "x64"); + } + if (strcmp(p, "ARM") == 0) { + return new cmGlobalVisualStudioVersionedGenerator(cm, genName, "ARM"); + } + return 0; + } + + void GetDocumentation(cmDocumentationEntry& entry) const override + { + entry.Name = std::string(vs15generatorName) + " [arch]"; + entry.Brief = "Generates Visual Studio 2017 project files. " + "Optional [arch] can be \"Win64\" or \"ARM\"."; + } + + void GetGenerators(std::vector& names) const override + { + names.push_back(vs15generatorName); + names.push_back(vs15generatorName + std::string(" ARM")); + names.push_back(vs15generatorName + std::string(" Win64")); + } + + bool SupportsToolset() const override { return true; } + bool SupportsPlatform() const override { return true; } +}; + +cmGlobalGeneratorFactory* +cmGlobalVisualStudioVersionedGenerator::NewFactory15() +{ + return new Factory15; +} + +cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator( + cmake* cm, const std::string& name, + std::string const& platformInGeneratorName) + : cmGlobalVisualStudio14Generator(cm, name, platformInGeneratorName) + , vsSetupAPIHelper(15) +{ + this->ExpressEdition = false; + this->DefaultPlatformToolset = "v141"; + this->DefaultCLFlagTableName = "v141"; + this->DefaultCSharpFlagTableName = "v141"; + this->DefaultLinkFlagTableName = "v141"; + this->Version = VS15; +} + +bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName( + const std::string& name) const +{ + std::string genName; + if (cmVS15GenName(name, genName)) { + return genName == this->GetName(); + } + return false; +} + +bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( + std::string const& i, cmMakefile* mf) +{ + if (!i.empty()) { + if (!this->vsSetupAPIHelper.SetVSInstance(i)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "could not find specified instance of Visual Studio:\n" + " " << i; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + } + + std::string vsInstance; + if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "could not find any instance of Visual Studio.\n"; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + + // Save the selected instance persistently. + std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"); + if (vsInstance != genInstance) { + this->CMakeInstance->AddCacheEntry( + "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(), + "Generator instance identifier.", cmStateEnums::INTERNAL); + } + + return true; +} + +bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance( + std::string& dir) const +{ + return vsSetupAPIHelper.GetVSInstanceInfo(dir); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsDefaultToolset( + const std::string& version) const +{ + if (version.empty()) { + return true; + } + + std::string vcToolsetVersion; + if (this->vsSetupAPIHelper.GetVCToolsetVersion(vcToolsetVersion)) { + + cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9]+"); + if (regex.find(version) && regex.find(vcToolsetVersion)) { + const auto majorMinorEnd = vcToolsetVersion.find('.', 3); + const auto majorMinor = vcToolsetVersion.substr(0, majorMinorEnd); + return version == majorMinor; + } + } + + return false; +} + +std::string cmGlobalVisualStudioVersionedGenerator::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 cmGlobalVisualStudioVersionedGenerator::InitializeWindows(cmMakefile* mf) +{ + // If the Win 8.1 SDK is installed then we can select a SDK matching + // the target Windows version. + if (this->IsWin81SDKInstalled()) { + return cmGlobalVisualStudio14Generator::InitializeWindows(mf); + } + // Otherwise we must choose a Win 10 SDK even if we are not targeting + // Windows 10. + return this->SelectWindows10SDK(mf, false); +} + +bool cmGlobalVisualStudioVersionedGenerator::SelectWindowsStoreToolset( + std::string& toolset) const +{ + if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { + if (this->IsWindowsStoreToolsetInstalled() && + this->IsWindowsDesktopToolsetInstalled()) { + toolset = "v141"; // VS 15 uses v141 toolset + return true; + } else { + return false; + } + } + return this->cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset( + toolset); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsWindowsDesktopToolsetInstalled() + const +{ + return vsSetupAPIHelper.IsVSInstalled(); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsWindowsStoreToolsetInstalled() + const +{ + return vsSetupAPIHelper.IsWin10SDKInstalled(); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsWin81SDKInstalled() const +{ + // Does the VS installer tool know about one? + if (vsSetupAPIHelper.IsWin81SDKInstalled()) { + return true; + } + + // Does the registry know about one (e.g. from VS 2015)? + std::string win81Root; + if (cmSystemTools::ReadRegistryValue( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot81", + win81Root, cmSystemTools::KeyWOW64_32) || + cmSystemTools::ReadRegistryValue( + "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot81", + win81Root, cmSystemTools::KeyWOW64_32)) { + return cmSystemTools::FileExists(win81Root + "/um/windows.h", true); + } + return false; +} + +std::string cmGlobalVisualStudioVersionedGenerator::GetWindows10SDKMaxVersion() + const +{ + return std::string(); +} + +std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand() +{ + std::string msbuild; + + // Ask Visual Studio Installer tool. + std::string vs; + if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { + msbuild = vs + "/MSBuild/15.0/Bin/MSBuild.exe"; + if (cmSystemTools::FileExists(msbuild)) { + return msbuild; + } + } + + msbuild = "MSBuild.exe"; + return msbuild; +} + +std::string cmGlobalVisualStudioVersionedGenerator::FindDevEnvCommand() +{ + std::string devenv; + + // Ask Visual Studio Installer tool. + std::string vs; + if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { + devenv = vs + "/Common7/IDE/devenv.com"; + if (cmSystemTools::FileExists(devenv)) { + return devenv; + } + } + + devenv = "devenv.com"; + return devenv; +} diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h new file mode 100644 index 0000000..2ffd568 --- /dev/null +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -0,0 +1,62 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmGlobalVisualStudioVersionedGenerator_h +#define cmGlobalVisualStudioVersionedGenerator_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include + +#include "cmGlobalVisualStudio14Generator.h" +#include "cmVSSetupHelper.h" + +class cmGlobalGeneratorFactory; +class cmake; + +/** \class cmGlobalVisualStudioVersionedGenerator */ +class cmGlobalVisualStudioVersionedGenerator + : public cmGlobalVisualStudio14Generator +{ +public: + static cmGlobalGeneratorFactory* NewFactory15(); + + bool MatchesGeneratorName(const std::string& name) const override; + + bool SetGeneratorInstance(std::string const& i, cmMakefile* mf) override; + + bool GetVSInstance(std::string& dir) const; + + bool IsDefaultToolset(const std::string& version) const override; + std::string GetAuxiliaryToolset() const override; + +protected: + cmGlobalVisualStudioVersionedGenerator( + 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 + // installed on the machine. + bool IsWindowsDesktopToolsetInstalled() const override; + + // These aren't virtual because we need to check if the selected version + // of the toolset is installed + bool IsWindowsStoreToolsetInstalled() const; + + // Check for a Win 8 SDK known to the registry or VS installer tool. + bool IsWin81SDKInstalled() const; + + std::string GetWindows10SDKMaxVersion() const override; + + std::string FindMSBuildCommand() override; + std::string FindDevEnvCommand() override; + +private: + class Factory15; + friend class Factory15; + mutable cmVSSetupAPIHelper vsSetupAPIHelper; +}; +#endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 195956b..1d062f4 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -55,8 +55,8 @@ # include "cmGlobalVisualStudio11Generator.h" # include "cmGlobalVisualStudio12Generator.h" # include "cmGlobalVisualStudio14Generator.h" -# include "cmGlobalVisualStudio15Generator.h" # include "cmGlobalVisualStudio9Generator.h" +# include "cmGlobalVisualStudioVersionedGenerator.h" # include "cmVSSetupHelper.h" # define CMAKE_HAVE_VS_GENERATORS @@ -1792,7 +1792,8 @@ void cmake::AddDefaultGenerators() { #if defined(_WIN32) && !defined(__CYGWIN__) # if !defined(CMAKE_BOOT_MINGW) - this->Generators.push_back(cmGlobalVisualStudio15Generator::NewFactory()); + this->Generators.push_back( + cmGlobalVisualStudioVersionedGenerator::NewFactory15()); this->Generators.push_back(cmGlobalVisualStudio14Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio12Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio11Generator::NewFactory()); -- cgit v0.12 From bdef729646a5a559c295ef9c0fb83eb8a6b34905 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 9 Jan 2019 11:39:32 -0500 Subject: VS: Parameterize VS 2017 generator to support future versions --- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 49 +++++++++++++++++++---- Source/cmGlobalVisualStudioVersionedGenerator.h | 2 +- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 354af72..7d04be2 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -8,6 +8,26 @@ #include "cmMakefile.h" #include "cmVSSetupHelper.h" +static unsigned int VSVersionToMajor( + cmGlobalVisualStudioGenerator::VSVersion v) +{ + switch (v) { + case cmGlobalVisualStudioGenerator::VS9: + return 9; + case cmGlobalVisualStudioGenerator::VS10: + return 10; + case cmGlobalVisualStudioGenerator::VS11: + return 11; + case cmGlobalVisualStudioGenerator::VS12: + return 12; + case cmGlobalVisualStudioGenerator::VS14: + return 14; + case cmGlobalVisualStudioGenerator::VS15: + return 15; + } + return 0; +} + static const char vs15generatorName[] = "Visual Studio 15 2017"; // Map generator name without year to name with year. @@ -38,16 +58,19 @@ public: return 0; } if (!*p) { - return new cmGlobalVisualStudioVersionedGenerator(cm, genName, ""); + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, ""); } if (*p++ != ' ') { return 0; } if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudioVersionedGenerator(cm, genName, "x64"); + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "x64"); } if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudioVersionedGenerator(cm, genName, "ARM"); + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "ARM"); } return 0; } @@ -77,25 +100,35 @@ cmGlobalVisualStudioVersionedGenerator::NewFactory15() } cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator( - cmake* cm, const std::string& name, + VSVersion version, cmake* cm, const std::string& name, std::string const& platformInGeneratorName) : cmGlobalVisualStudio14Generator(cm, name, platformInGeneratorName) - , vsSetupAPIHelper(15) + , vsSetupAPIHelper(VSVersionToMajor(version)) { this->ExpressEdition = false; this->DefaultPlatformToolset = "v141"; this->DefaultCLFlagTableName = "v141"; this->DefaultCSharpFlagTableName = "v141"; this->DefaultLinkFlagTableName = "v141"; - this->Version = VS15; + this->Version = version; } bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName( const std::string& name) const { std::string genName; - if (cmVS15GenName(name, genName)) { - return genName == this->GetName(); + switch (this->Version) { + case cmGlobalVisualStudioGenerator::VS9: + case cmGlobalVisualStudioGenerator::VS10: + case cmGlobalVisualStudioGenerator::VS11: + case cmGlobalVisualStudioGenerator::VS12: + case cmGlobalVisualStudioGenerator::VS14: + break; + case cmGlobalVisualStudioGenerator::VS15: + if (cmVS15GenName(name, genName)) { + return genName == this->GetName(); + } + break; } return false; } diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index 2ffd568..531f5a6 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -32,7 +32,7 @@ public: protected: cmGlobalVisualStudioVersionedGenerator( - cmake* cm, const std::string& name, + VSVersion version, cmake* cm, const std::string& name, std::string const& platformInGeneratorName); bool InitializeWindows(cmMakefile* mf) override; -- cgit v0.12 From 57e48f16f2c3b73fb27057267c8092a41005bb75 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 9 Jan 2019 14:30:10 -0500 Subject: VS: Add Visual Studio 16 2019 generator Add this generator *without* support for specifying the target architecture in the generator name. cmake-gui will be taught to provide a field for this, and command-line builds can use -A. Also, teach this generator to select a default target architecture based on the host architecture. Fixes: #18689 Inspired-by: Egor Pugin --- Help/generator/Visual Studio 16 2019.rst | 49 ++++++++ Help/manual/cmake-generators.7.rst | 1 + Help/release/dev/vs2019.rst | 13 +++ Help/variable/MSVC_VERSION.rst | 1 + Source/cmCMakeHostSystemInformationCommand.cxx | 16 +++ Source/cmGlobalVisualStudio10Generator.cxx | 2 + Source/cmGlobalVisualStudioGenerator.cxx | 11 ++ Source/cmGlobalVisualStudioGenerator.h | 3 +- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 126 ++++++++++++++++++++- Source/cmGlobalVisualStudioVersionedGenerator.h | 3 + Source/cmVisualStudioGeneratorOptions.cxx | 1 + Source/cmake.cxx | 6 +- Tests/RunCMake/CMakeLists.txt | 2 +- .../RunCMake/GeneratorPlatform/RunCMakeTest.cmake | 4 +- Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake | 8 +- .../include_external_msproject/check_utils.cmake | 2 + Tests/VSExternalInclude/CMakeLists.txt | 4 +- 17 files changed, 235 insertions(+), 17 deletions(-) create mode 100644 Help/generator/Visual Studio 16 2019.rst create mode 100644 Help/release/dev/vs2019.rst diff --git a/Help/generator/Visual Studio 16 2019.rst b/Help/generator/Visual Studio 16 2019.rst new file mode 100644 index 0000000..6f2bc56 --- /dev/null +++ b/Help/generator/Visual Studio 16 2019.rst @@ -0,0 +1,49 @@ +Visual Studio 16 2019 +--------------------- + +Generates Visual Studio 16 (VS 2019) project files. + +Project Types +^^^^^^^^^^^^^ + +Only Visual C++ and C# projects may be generated. Other types of +projects (JavaScript, Powershell, Python, etc.) are not supported. + +Instance Selection +^^^^^^^^^^^^^^^^^^ + +VS 2019 supports multiple installations on the same machine. +The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a +cache entry containing the absolute path to a Visual Studio instance. +If the value is not specified explicitly by the user or a toolchain file, +CMake queries the Visual Studio Installer to locate VS instances, chooses +one, and sets the variable as a cache entry to hold the value persistently. + +When CMake first chooses an instance, if the ``VS160COMNTOOLS`` environment +variable is set and points to the ``Common7/Tools`` directory within +one of the instances, that instance will be used. Otherwise, if more +than one instance is installed we do not define which one is chosen +by default. + +Platform Selection +^^^^^^^^^^^^^^^^^^ + +The default target platform name (architecture) is that of the host. + +The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps +via the :manual:`cmake(1)` ``-A`` option, to specify a target platform +name (architecture). For example: + +* ``cmake -G "Visual Studio 16 2019" -A Win32`` +* ``cmake -G "Visual Studio 16 2019" -A x64`` +* ``cmake -G "Visual Studio 16 2019" -A ARM`` +* ``cmake -G "Visual Studio 16 2019" -A ARM64`` + +Toolset Selection +^^^^^^^^^^^^^^^^^ + +The ``v142`` toolset that comes with Visual Studio 16 2019 is selected by +default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps +via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. + +.. include:: VS_TOOLSET_HOST_ARCH.txt diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst index 1de10c4..41f7652 100644 --- a/Help/manual/cmake-generators.7.rst +++ b/Help/manual/cmake-generators.7.rst @@ -87,6 +87,7 @@ Visual Studio Generators /generator/Visual Studio 12 2013 /generator/Visual Studio 14 2015 /generator/Visual Studio 15 2017 + /generator/Visual Studio 16 2019 Other Generators ^^^^^^^^^^^^^^^^ diff --git a/Help/release/dev/vs2019.rst b/Help/release/dev/vs2019.rst new file mode 100644 index 0000000..1ffdeec --- /dev/null +++ b/Help/release/dev/vs2019.rst @@ -0,0 +1,13 @@ +vs2019 +------ + +* The :generator:`Visual Studio 16 2019` generator was added. This is + experimental and based on "Visual Studio 2019 Preview 1.1" because this + version of VS has not been released. + + The VS 2019 generator differs from generators for earlier versions + in that it does not provide variants that specify the target platform + in the generator name. Instead :variable:`CMAKE_GENERATOR_PLATFORM` + must be used, e.g. through the ``-A`` command-line option. Furthermore, + the default target platform (architecture) is now based on the *host* + platform. diff --git a/Help/variable/MSVC_VERSION.rst b/Help/variable/MSVC_VERSION.rst index 4ef43d8..45df37f 100644 --- a/Help/variable/MSVC_VERSION.rst +++ b/Help/variable/MSVC_VERSION.rst @@ -18,6 +18,7 @@ Known version numbers are:: 1800 = VS 12.0 (v120 toolset) 1900 = VS 14.0 (v140 toolset) 1910-1919 = VS 15.0 (v141 toolset) + 1920-1929 = VS 16.0 (v142 toolset) See also the :variable:`CMAKE__COMPILER_VERSION` and :variable:`MSVC_TOOLSET_VERSION` variable. diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index ddc32c0..54f08bb 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -145,6 +145,22 @@ bool cmCMakeHostSystemInformationCommand::GetValue( if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { cmSystemTools::ConvertToUnixSlashes(value); } + } else if (key == "VS_16_DIR") { + // If generating for the VS 16 IDE, use the same instance. + cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 16 ")) { + cmGlobalVisualStudioVersionedGenerator* vs16gen = + static_cast(gg); + if (vs16gen->GetVSInstance(value)) { + return true; + } + } + + // Otherwise, find a VS 16 instance ourselves. + cmVSSetupAPIHelper vsSetupAPIHelper(16); + if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { + cmSystemTools::ConvertToUnixSlashes(value); + } #endif } else { std::string e = "does not recognize " + key; diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index a6bec4b..2932970 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1032,6 +1032,8 @@ const char* cmGlobalVisualStudio10Generator::GetToolsVersion() const return "14.0"; case cmGlobalVisualStudioGenerator::VS15: return "15.0"; + case cmGlobalVisualStudioGenerator::VS16: + return "16.0"; } return ""; } diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index dc8de03..57510df 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -86,6 +86,8 @@ const char* cmGlobalVisualStudioGenerator::GetIDEVersion() const return "14.0"; case cmGlobalVisualStudioGenerator::VS15: return "15.0"; + case cmGlobalVisualStudioGenerator::VS16: + return "16.0"; } return ""; } @@ -139,6 +141,15 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout) fout << "# Visual Studio 15\n"; } break; + case cmGlobalVisualStudioGenerator::VS16: + // Visual Studio 16 writes .sln format 12.00 + fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; + if (this->ExpressEdition) { + fout << "# Visual Studio Express 16 for Windows Desktop\n"; + } else { + fout << "# Visual Studio 16\n"; + } + break; } } diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index d44f5a5..039191c 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -38,7 +38,8 @@ public: VS12 = 120, /* VS13 = 130 was skipped */ VS14 = 140, - VS15 = 150 + VS15 = 150, + VS16 = 160 }; virtual ~cmGlobalVisualStudioGenerator(); diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 7d04be2..f06c019 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -8,6 +8,16 @@ #include "cmMakefile.h" #include "cmVSSetupHelper.h" +#if defined(_M_ARM64) +# define HOST_PLATFORM_NAME "ARM64"; +#elif defined(_M_ARM) +# define HOST_PLATFORM_NAME "ARM"; +#elif defined(_M_IA64) +# define HOST_PLATFORM_NAME "Itanium"; +#else +# include "cmsys/SystemInformation.hxx" +#endif + static unsigned int VSVersionToMajor( cmGlobalVisualStudioGenerator::VSVersion v) { @@ -24,10 +34,35 @@ static unsigned int VSVersionToMajor( return 14; case cmGlobalVisualStudioGenerator::VS15: return 15; + case cmGlobalVisualStudioGenerator::VS16: + return 16; } return 0; } +static const char* VSVersionToToolset( + cmGlobalVisualStudioGenerator::VSVersion v) +{ + switch (v) { + case cmGlobalVisualStudioGenerator::VS9: + return "v90"; + case cmGlobalVisualStudioGenerator::VS10: + return "v100"; + case cmGlobalVisualStudioGenerator::VS11: + return "v110"; + case cmGlobalVisualStudioGenerator::VS12: + return "v120"; + case cmGlobalVisualStudioGenerator::VS14: + return "v140"; + case cmGlobalVisualStudioGenerator::VS15: + return "v141"; + case cmGlobalVisualStudioGenerator::VS16: + // FIXME: VS 2019 Preview 1.1 uses v141 but preview 2 will use v142. + return "v141"; + } + return ""; +} + static const char vs15generatorName[] = "Visual Studio 15 2017"; // Map generator name without year to name with year. @@ -99,18 +134,88 @@ cmGlobalVisualStudioVersionedGenerator::NewFactory15() return new Factory15; } +static const char vs16generatorName[] = "Visual Studio 16 2019"; + +// Map generator name without year to name with year. +static const char* cmVS16GenName(const std::string& name, std::string& genName) +{ + if (strncmp(name.c_str(), vs16generatorName, + sizeof(vs16generatorName) - 6) != 0) { + return 0; + } + const char* p = name.c_str() + sizeof(vs16generatorName) - 6; + if (cmHasLiteralPrefix(p, " 2019")) { + p += 5; + } + genName = std::string(vs16generatorName) + p; + return p; +} + +class cmGlobalVisualStudioVersionedGenerator::Factory16 + : public cmGlobalGeneratorFactory +{ +public: + virtual cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, + cmake* cm) const + { + std::string genName; + const char* p = cmVS16GenName(name, genName); + if (!p) { + return 0; + } + if (!*p) { + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS16, cm, genName, ""); + } + return 0; + } + + virtual void GetDocumentation(cmDocumentationEntry& entry) const + { + entry.Name = std::string(vs16generatorName); + entry.Brief = "Generates Visual Studio 2019 project files. " + "Use -A option to specify architecture."; + } + + virtual void GetGenerators(std::vector& names) const + { + names.push_back(vs16generatorName); + } + + bool SupportsToolset() const override { return true; } + bool SupportsPlatform() const override { return true; } +}; + +cmGlobalGeneratorFactory* +cmGlobalVisualStudioVersionedGenerator::NewFactory16() +{ + return new Factory16; +} + cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator( VSVersion version, cmake* cm, const std::string& name, std::string const& platformInGeneratorName) : cmGlobalVisualStudio14Generator(cm, name, platformInGeneratorName) , vsSetupAPIHelper(VSVersionToMajor(version)) { - this->ExpressEdition = false; - this->DefaultPlatformToolset = "v141"; - this->DefaultCLFlagTableName = "v141"; - this->DefaultCSharpFlagTableName = "v141"; - this->DefaultLinkFlagTableName = "v141"; this->Version = version; + this->ExpressEdition = false; + this->DefaultPlatformToolset = VSVersionToToolset(this->Version); + this->DefaultCLFlagTableName = VSVersionToToolset(this->Version); + this->DefaultCSharpFlagTableName = VSVersionToToolset(this->Version); + this->DefaultLinkFlagTableName = VSVersionToToolset(this->Version); + if (this->Version >= cmGlobalVisualStudioGenerator::VS16) { +#ifdef HOST_PLATFORM_NAME + this->DefaultPlatformName = HOST_PLATFORM_NAME; +#else + cmsys::SystemInformation info; + if (info.Is64Bits()) { + this->DefaultPlatformName = "x64"; + } else { + this->DefaultPlatformName = "Win32"; + } +#endif + } } bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName( @@ -129,6 +234,11 @@ bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName( return genName == this->GetName(); } break; + case cmGlobalVisualStudioGenerator::VS16: + if (cmVS16GenName(name, genName)) { + return genName == this->GetName(); + } + break; } return false; } @@ -239,7 +349,7 @@ bool cmGlobalVisualStudioVersionedGenerator::SelectWindowsStoreToolset( if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { if (this->IsWindowsStoreToolsetInstalled() && this->IsWindowsDesktopToolsetInstalled()) { - toolset = "v141"; // VS 15 uses v141 toolset + toolset = VSVersionToToolset(this->Version); return true; } else { return false; @@ -296,6 +406,10 @@ std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand() // Ask Visual Studio Installer tool. std::string vs; if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { + msbuild = vs + "/MSBuild/Current/Bin/MSBuild.exe"; + if (cmSystemTools::FileExists(msbuild)) { + return msbuild; + } msbuild = vs + "/MSBuild/15.0/Bin/MSBuild.exe"; if (cmSystemTools::FileExists(msbuild)) { return msbuild; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index 531f5a6..466816b 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -20,6 +20,7 @@ class cmGlobalVisualStudioVersionedGenerator { public: static cmGlobalGeneratorFactory* NewFactory15(); + static cmGlobalGeneratorFactory* NewFactory16(); bool MatchesGeneratorName(const std::string& name) const override; @@ -57,6 +58,8 @@ protected: private: class Factory15; friend class Factory15; + class Factory16; + friend class Factory16; mutable cmVSSetupAPIHelper vsSetupAPIHelper; }; #endif diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index afe9230..5c3e533 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -70,6 +70,7 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() case cmGlobalVisualStudioGenerator::VS12: case cmGlobalVisualStudioGenerator::VS14: case cmGlobalVisualStudioGenerator::VS15: + case cmGlobalVisualStudioGenerator::VS16: // by default VS puts empty // for a project, to make our projects look the same put a new line // and space over for the closing as the default diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 1d062f4..1541810 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1538,7 +1538,9 @@ void cmake::CreateDefaultGlobalGenerator() "\\Setup\\VC;ProductDir", // ";InstallDir" // }; - if (cmVSSetupAPIHelper(15).IsVSInstalled()) { + if (cmVSSetupAPIHelper(16).IsVSInstalled()) { + found = "Visual Studio 16 2019"; + } else if (cmVSSetupAPIHelper(15).IsVSInstalled()) { found = "Visual Studio 15 2017"; } else { for (VSVersionedGenerator const* g = cm::cbegin(vsGenerators); @@ -1793,6 +1795,8 @@ void cmake::AddDefaultGenerators() #if defined(_WIN32) && !defined(__CYGWIN__) # if !defined(CMAKE_BOOT_MINGW) this->Generators.push_back( + cmGlobalVisualStudioVersionedGenerator::NewFactory16()); + this->Generators.push_back( cmGlobalVisualStudioVersionedGenerator::NewFactory15()); this->Generators.push_back(cmGlobalVisualStudio14Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio12Generator::NewFactory()); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 5afa242..2b6519a 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -334,7 +334,7 @@ if (GTK2_FOUND) endif() if("${CMAKE_GENERATOR}" MATCHES "Visual Studio") - add_RunCMake_test(include_external_msproject) + add_RunCMake_test(include_external_msproject -DVS_PLATFORM_NAME=${CMAKE_VS_PLATFORM_NAME}) if("${CMAKE_GENERATOR}" MATCHES "Visual Studio (9|10)" AND NOT CMAKE_VS_DEVENV_COMMAND) set(NO_USE_FOLDERS 1) endif() diff --git a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake index 27250cb..27ede06 100644 --- a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake @@ -3,7 +3,7 @@ include(RunCMake) set(RunCMake_GENERATOR_PLATFORM "") run_cmake(NoPlatform) -if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[01245])( 20[0-9][0-9])?$") +if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[012456])( 20[0-9][0-9])?$") set(RunCMake_GENERATOR_PLATFORM "x64") run_cmake(x64Platform) else() @@ -17,7 +17,7 @@ set(RunCMake_TEST_OPTIONS -A "Extra Platform") run_cmake(TwoPlatforms) unset(RunCMake_TEST_OPTIONS) -if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[01245])( 20[0-9][0-9])?$") +if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[012456])( 20[0-9][0-9])?$") set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/TestPlatform-toolchain.cmake) run_cmake(TestPlatformToolchain) unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index d1738a0..ccf58b4 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -3,7 +3,7 @@ include(RunCMake) set(RunCMake_GENERATOR_TOOLSET "") run_cmake(NoToolset) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]") +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset") run_cmake(TestToolset) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,cuda=Test Cuda") @@ -12,7 +12,7 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]") run_cmake(TestToolsetCudaOnly) set(RunCMake_GENERATOR_TOOLSET "cuda=Test Cuda") run_cmake(TestToolsetCudaOnly) - if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[245]") + if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[2456]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(TestToolsetHostArchBoth) set(RunCMake_GENERATOR_TOOLSET ",host=x64") @@ -25,7 +25,7 @@ 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") + if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[56]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version") run_cmake(TestToolsetVersionBoth) set(RunCMake_GENERATOR_TOOLSET ",version=Test Toolset Version") @@ -59,7 +59,7 @@ set(RunCMake_TEST_OPTIONS -T "Extra Toolset") run_cmake(TwoToolsets) unset(RunCMake_TEST_OPTIONS) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode") +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]|Xcode") set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/TestToolset-toolchain.cmake) run_cmake(TestToolsetToolchain) unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/include_external_msproject/check_utils.cmake b/Tests/RunCMake/include_external_msproject/check_utils.cmake index e9e9cac..0a2ba63 100644 --- a/Tests/RunCMake/include_external_msproject/check_utils.cmake +++ b/Tests/RunCMake/include_external_msproject/check_utils.cmake @@ -100,6 +100,8 @@ function(check_project test name guid type platform imported_release_config_name set(platform "${RunCMake_GENERATOR_PLATFORM}") elseif("${RunCMake_GENERATOR}" MATCHES "Win64") set(platform "x64") + elseif(VS_PLATFORM_NAME) + set(platform "${VS_PLATFORM_NAME}") else() set(platform "Win32") endif() diff --git a/Tests/VSExternalInclude/CMakeLists.txt b/Tests/VSExternalInclude/CMakeLists.txt index 7465243..8ca7252 100644 --- a/Tests/VSExternalInclude/CMakeLists.txt +++ b/Tests/VSExternalInclude/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required (VERSION 2.6) project(VSExternalInclude) -if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[01245]") +if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[012456]") set(PROJECT_EXT vcxproj) else() set(PROJECT_EXT vcproj) @@ -55,7 +55,7 @@ add_dependencies(VSExternalInclude lib2) # and the sln file can no longer be the only source # of that depend. So, for VS 10 make the executable # depend on lib1 and lib2 -if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[01245]") +if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[012456]") add_dependencies(VSExternalInclude lib1) endif() -- cgit v0.12