Commit 57e48f16 authored by Brad King's avatar Brad King

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: #18689Inspired-by: Egor Pugin's avatarEgor Pugin <egor.pugin@gmail.com>
parent bdef7296
Pipeline #127483 passed with stage
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
......@@ -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
^^^^^^^^^^^^^^^^
......
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.
......@@ -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_<LANG>_COMPILER_VERSION` and
:variable:`MSVC_TOOLSET_VERSION` variable.
......@@ -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<cmGlobalVisualStudioVersionedGenerator*>(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> " + key;
......
......@@ -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 "";
}
......
......@@ -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;
}
}
......
......@@ -38,7 +38,8 @@ public:
VS12 = 120,
/* VS13 = 130 was skipped */
VS14 = 140,
VS15 = 150
VS15 = 150,
VS16 = 160
};
virtual ~cmGlobalVisualStudioGenerator();
......
......@@ -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<std::string>& 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;
......
......@@ -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
......@@ -70,6 +70,7 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
case cmGlobalVisualStudioGenerator::VS12:
case cmGlobalVisualStudioGenerator::VS14:
case cmGlobalVisualStudioGenerator::VS15:
case cmGlobalVisualStudioGenerator::VS16:
// by default VS puts <ExceptionHandling></ExceptionHandling> empty
// for a project, to make our projects look the same put a new line
// and space over for the closing </ExceptionHandling> as the default
......
......@@ -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);
......@@ -1792,6 +1794,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());
......
......@@ -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()
......
......@@ -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)
......
......@@ -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)
......
......@@ -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()
......
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()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment