Old visual studio generators in recent cmake

Hi,
I use cmake with conan to generate prebuild version of libraries for different Visual Studio version and architecture.

We mostly use Visual Studio 2022 and 2019, but we still need to support new library version (bug fixes) for Visual Studio 2013 and 2008.

Unfortunately, I just discover that cmake version 3.31 drops support for Visual Studio 2013 generator and the support for Visual Studio 2008 was dropped too in a previous version.

Beside, installing an older cmake version, how can I get back these generators?
Can I extract them from older version an place somewhere in my cmake forlder?

The main problem is that often people/developers have to rebuild a library in their laptops because they need a specific version with specific option that is not available in our repository and I’m sure that most of them have a cmake version that does not support anymore these generators.

I read I can use for instance the generator for VS 2015 setting vc120 as toolchain but this mean that I have to install another visual studio version and I’m not sure if conan is happy to have a library version for VS2013 build with another version of the compiler.

Thanks

With VS 2022 installer, you may install the older toolchains too until VS2015 AFAIK

I know that, but I need VS2013 that is not ABI compatible.

The main problem is that even if I can “solve” by installing a new version of VS and set the toolset for an older one, to make it works I have to change all the build scripts.

We have hundred of libraries and thousands installation by customers and this is not a practical solution.

This is really a breaking change and a big problem for us

I’d really go with the “use older CMake” for those cases where VS2013 is required. It easy enough to have multiple CMake versions extracted in different directories, and that route has always been pretty efficient for me.

Couldn’t you also just use developer command prompts and use the Ninja generator?

Note that the v120 toolchain is the VS2013 compiler, just shipped with the VS2015 IDE.

Theoretically possible. But none of this helps unless that specific version — e.g. v120is supported by rules in the newer VS. And you’ll have to have the respective toolsets installed, too. The mere presence of these compatibility rules doesn’t imply you’ll be able to build with the respective compilers (yes, XP compatibility could be had by installing the respective deprecated toolset; so there you get rules and toolset in tandem; for the rest you need to have an older VS version installed). You can find out by going to your $(VSInstallRoot)\MSBuild (aka %VCINSTALLDIR%MSBuild from the developer prompt) inside the subdirectory Microsoft\VC. There you can find the supported older toolsets and the latest one. So for example inside VS2022 (%ProgramFiles%\Microsoft Visual Studio\2022\Professional\MSBuild\Microsoft\VC) you may find v150, v160 and v170. Now the problem here is that the XML elements supported inside ItemDefinitionGroup and ItemGroup etc. vary across these versions. Mostly they get expanded by newer versions. This means even though you could just change that single value not all of the settings may take effect on account of the older MSBuild ruleset (and potentially MSBuild tasks like CL) not being aware of those settings (unless given in the form of command line options).

By bending MSBuild to your will, a lot is possible here. For example it is possible to use MSBuild to drive a (Windows-targeting) build using the MSVC toolchain from Linux. But alone the fact how CMake-generated VC projects hardcode data points not normally found in vanilla VC projects will likely undermine anything you’d be able to do otherwise.

Frankly, CMake is the wrong tool for what you are trying. CMake may be good for a lot of things, but VC project generation is not one of them. The project generation takes ages on Windows compared to Linux and all those configure-style tests of the compiler/runtime/libraries is a totally moot point with VC projects. And the end result are generated projects that are tied to your exact system (path layouts, CMake version etc.).

There are plenty of generators out there which do a much better job at creating VC projects. So my recommendation would be either to switch to those for the purpose or switch to a different build tool such as Ninja. The only real thing that should be necessary then is a proper toolchain file or a properly prepared environment (which in scripts can be a breeze, if the scripts were well-designed).

And of course there’s the option of using an older CMake version. It’s not the coolest option (because it also means you are constraining what can go into your CMakeLists.txt files), but sounds pragmatic enough if you’re willing to swallow that bitter pill.

PS: If your generated MSBuild (.vcxproj/.vcproj) projects were generic enough — as mentioned this is something that CMake isn’t capable of — you could simply start the build from an environment where you place alternative locations for cl.exe, link.exe, rc.exe and friends at the beginning of PATH for the actual build. This has been done successfully in the past, including by myself. It was one of the tricks of building Windows drivers with the WDK toolchain despite doing it from within VS with an otherwise vanilla project file.

Wait, could it be you’re mixing the PlatformToolset with VCTargetsVersion (e.g. _ToolsetVCTargetsVersion) concept here?

PlatformToolset: VS2013 (v120) , VS2015 (v140), VS2017 (v141), VS2019 (v142), VS2022 (v143)

VCTargetsVersion (from v170\Microsoft.Cpp.Default.props):

  <PropertyGroup>
    <MinSupportedVCTargetsVersion Condition="'$(MinimumVisualStudioVersion)' == '17.0'">v170</MinSupportedVCTargetsVersion>
    <MinSupportedVCTargetsVersion Condition="'$(MinimumVisualStudioVersion)' == '16.0'">v160</MinSupportedVCTargetsVersion>
    <MinSupportedVCTargetsVersion Condition="'$(MinimumVisualStudioVersion)' == '15.0'">v150</MinSupportedVCTargetsVersion>
    <MinSupportedVCTargetsVersion Condition="'$(MinimumVisualStudioVersion)' == '14.0'">v140</MinSupportedVCTargetsVersion>
    <MinSupportedVCTargetsVersion Condition="'$(MinimumVisualStudioVersion)' == '12.0'">v120</MinSupportedVCTargetsVersion>
    <MinSupportedVCTargetsVersion Condition="'$(MinimumVisualStudioVersion)' == '11.0'">v110</MinSupportedVCTargetsVersion>
  </PropertyGroup>

And depending on those determined values one of the Microsoft.Cpp.Redirect.*.props takes effect.

PlatformToolset is what allowed you in newer VS versions — if installed — to use the v141_xp platform toolset (i.e. actually compiler and tools from VS2017).

For the other glue rules for supported VCTargetsVersion it depends if the respective older VS is found when installing the newer one. For example my VS2022 on a machine with VS2019 has v160 and v170 rules, but lacks the rules vor v150 (except for one single Microsoft.Cpp.UnitTest.props file which won’t even suffice to invoke a compiler — because VS2017 isn’t installed).

Practical example: on my system I have VS2019 and VS2022 currently installed. Now if I open the .sln file which was created with VS2022 the Visual Studio Version Selector will determine my sample project is VS2022 and open that IDE. Now I go edit all instances of <PlatformToolset>v143</PlatformToolset> to read <PlatformToolset>v142</PlatformToolset> inside the project. Reopening the .sln will still open the VS2022 IDE but this time I will be prompted to upgrade¹ but decline to do so.

Either way there is now a subtle difference in the Solution Explorer pane: the project shows the project name with (Visual Studio 2019) appended. Provided the code can be built on VS2019, I can build from the VS2022 using the VS2019 compiler and tools on account of having that installed in parallel. Now let’s take it one further and change <PlatformToolset>v142</PlatformToolset> to <PlatformToolset>v141</PlatformToolset>, then reopening the .sln. The VS2022 Solution Explorer shows the desired (Visual Studio 2017) now.

But the Output pane shows the following:

warning : The build tools for Visual Studio 2017 (v141) cannot be found. To build using the Visual Studio 2022 (v143) build tools, either click the Project menu or right-click the solution, and then select “Retarget Solution”. Install Visual Studio 2017 (v141) to build using the Visual Studio 2017 (v141) build tools.

PS: @ben.boeckel I just installed VS2015 Pro (update 3) for giggles in a VM without any other VS version and I’m not sure if I simply misunderstand your statement, but it read to me as if you’re saying the VS2013 compiler was shipped with VS2015; which it wasn’t:

Note that the v120 toolchain is the VS2013 compiler, just shipped with the VS2015 IDE.

In that VM with VS2015 and without VS2013 I tried it. Changed it to <PlatformToolset>v120</PlatformToolset> in a vanilla project I had created with the freshly installed VS2015 and I got:

warning : The build tools for Visual Studio 2013 (v120) cannot be found. To build using the Visual Studio 2015 (v140) build tools, either click the Project menu or right-click the solution, and then select “Upgrade Solution…”. Install Visual Studio 2013 (v120) to build using the Visual Studio 2013 (v120) build tools.

¹ Something I could suppress with <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName> in the global properties.