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".
cmake
error output
Improved 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.
cmake --help
Hint in 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.