Skip to content

Proposed improvements to Visual Studio generator and toolset variables

Hi all

I recently struggled to get CMake to detect a variety of Visual Studio configurations, and I want to propose some documentation improvements that would've helped me a lot. In addition to my proposal in #22256 (mention vswhere.exe), it'd help to cross-link and explain the toolchain selection related command line arguments and variables.

Right now it's very far from obvious that when compiling with a downlevel Visual Studio tools, e.g. a VS 2019 Build Tools install of the VS 14 C/C++ compiler, the user should set -G to the MSVC installer version, then set -T to a specific MSBuild Platform Toolkit. All you need is:

cmake -G "Visual Studio 16 2019" -T "vs140"

instead of the intuitive but wrong

cmake -G "Visual Studio 14 2015"

There are a lot of VS, generator and platform related variables, but their effects and intended uses aren't always clear, and may obfuscate how simple the actual setup is. I've made some suggestions about possible improvements below, covering the vars:

  • CMAKE_GENERATOR_PLATFORM
  • CMAKE_GENERATOR_TOOLSET
  • CMAKE_VS_PLATFORM_TOOLSET
  • CMAKE_VS_PLATFORM_TOOLSET_VERSION
  • CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION (SDK)
  • CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE

Specifically:

CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION

The docs for CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION should more explicitly state that it's for selecting the Windows SDK to use.

It does not select the MSVC toolset. For that use CMAKE_GENERATOR_TOOLSET and if needed, CMAKE_VS_PLATFORM_TOOLSET_VERSION as documented in "Visual Studio Generators".

CMAKE_VS_PLATFORM_TOOLSET

This variable is what determines the PlatformToolset property in the generated MSBuild files, but that's not clear from the docs.

The docs for CMAKE_VS_PLATFORM_TOOLSET should link to "Visual Studio Generators" in "cmake-generators" and to CMAKE_GENERATOR_TOOLSET.

The docs should recommend that users set CMAKE_GENERATOR_TOOLSET (-T) rather than CMAKE_VS_PLATFORM_TOOLSET; This should be a read-only variable.

It'd be good if this referenced CMAKE_VS_PLATFORM_TOOLSET_VERSION to point out that minor versions within one toolset are selected with CMAKE_VS_PLATFORM_TOOLSET_VERSION.

Also reference CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION for Windows SDK selection.

CMAKE_GENERATOR_TOOLSET (or the Visual Studio section of the generators docs)

It would be immensely helpful if this variable gave the reader a way to discover the accepted toolset names as understood by MSBuild when using a Visual Studio generator.

Unfortunately Microsoft's documentation in this area is lacking and confusing, but https://docs.microsoft.com/en-us/cpp/build/reference/msbuild-visual-cpp-overview?view=msvc-160 seems to be helpful. The best I was able to concoct was this Powershell code:

Get-ChildItem -Path @("${Env:ProgramFiles}","${Env:ProgramFiles(x86)") -Filter "PlatformToolsets" -Recurse | Get-ChildItem  | Format-Table -Property Name,FullName

Even just a hint would help. Like stating that "Typical toolset names are vNNN where NNN is the Visual Studio version including minor release number, e.g. v140 for Visual Studio 14.0 tools". Then mention that toolsets are subdirectories of MSBuild PlatformToolsets directories.

Visual Studio Generators section of "cmake-generators" docs

The Visual Studio Generators should explain that the generator specifies the version of the Visual Studio platform itself, including msbuild.exe, and where to find it. If you need to use a downlevel toolset (compiler, etc) installed using a newer Visual Studio, you must specify the visual studio installer version as the generator then set the toolset to the downlevel version. See CMAKE_GENERATOR_PLATFORM (cmake -A) and CMAKE_GENERATOR_TOOLSET (cmake -T).

For example, if you have installed Visual Studio Build Tools 2019 and selected the optional workload component ID Microsoft.VisualStudio.Component.VC.140 to install the toolset MSVC v140 - VS 2015 C++ build tools (v14.00), you must use cmake -G "Visual Studio 16 2019" -T "vs140" or equivalently set CMAKE_GENERATOR_PLATFORM=x64 and CMAKE_GENERATOR_TOOLSET=vs140.

You cannot use cmake -G "Visual Studio 14 2015" to use the VS 14 compilers installed by VS 16. If you try to use an old MSVC generator to select a toolset installed by a newer Visual Studio you may get errors like *Failed to run MSBuild command: MSBuild.exe to get the value of VCTargetsPath" with details like "The system cannot find the file specified" or "exited unexpectedly".

Running the vcvarsall.bat from the downlevel toolset will not cause CMake to generate the project correctly. You may get MSBuild error output containing something like C:\Microsoft.Cpp.Default.props" was not found in this case.

It should mention CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION for SDK selection too.

Each VS generator page should link to some common info about configuration and discovery

In each individual VS generator's documentation link to the Visual Studio Generators subsection of cmake-generators with text like "For details on selecting the compiler version and Windows SDK to use, see Visual Studio Generators".

CMAKE_VS_PLATFORM_TOOLSET, CMAKE_VS_PLATFORM_TOOLSET_VERSION, CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE

The docs for these variables should preferably be more explicit that the user should not set the CMAKE_VS_PLATFORM_TOOLSET, CMAKE_VS_PLATFORM_TOOLSET_VERSION or CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE in project files or on the command line. They should set CMAKE_GENERATOR_TOOLSET or use cmake -A.

The docs for CMAKE_VS_PLATFORM_TOOLSET_VERSION should link to CMAKE_VS_PLATFORM_TOOLSET and vice versa in a "see also".

Improved cmake error output

If cmake running msbuild.exe to find VSTargetsPath fails, print a hint that points to the Visual Studio generators documentation URL for the selected generator, and mentions the CMAKE_GENERATOR_PLATFORM (-A) and CMAKE_GENERATOR_TOOLSET (-T) options.

Hint in cmake --help

While cmake(1) documents that -A sets CMAKE_GENERATOR_PLATFORM and the doc page for it mentions cmake -A it would be nice to have it in cmake --help as something like "See CMAKE_GENERATOR_PLATFORM". Same for -G and -T. Or have cmake --help list variable/argument equivalencies separately.

Edited by Craig Ringer
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information