Open thorntonryan opened 1 year ago
Hi @thorntonryan
thanks for your detailed report.
Quick question, isn't Conan generating the right toolset inside the conan_toolchain.cmake
? Because it is there:
{% if generator_platform %}
set(CMAKE_GENERATOR_PLATFORM "{{ generator_platform }}" CACHE STRING "" FORCE)
{% endif %}
{% if toolset %}
set(CMAKE_GENERATOR_TOOLSET "{{ toolset }}" CACHE STRING "" FORCE)
{% endif %}
The reason why things are by default if possible in the toolchain file is because conan needs to be compatible down to CMake 3.15, so no presets. The more things we put in the presets, the more complicated is for developers with CMake < 3.20 to issue a command line that will work for them.
Hrmm. Doesn't look like it.
If I run the following:
$ conan new hello/0.1 --template cmake_lib
And then install that project:
$ conan install conanfile.py -pr:b x86_64-windows-msvc143 -pr:h x86-windows-msvc143
Conan generates the following:
Unfortunately, I'm not seeing CMAKE_GENERATOR_PLATFORM
or CMAKE_GENERATOR_TOOLSET
there.
If I try the same thing with the msvc
compiler:
$ conan install conanfile.py -pr:b x86_64-windows-msvc-143 -pr:h x86-windows-msvc-143
Conan generates the following:
If I then add toolset_arch
to my global.conf
:
tools.cmake.cmaketoolchain:generator=Ninja
+tools.cmake.cmaketoolchain:toolset_arch=x64
Then I see toolset partially added to the generated CMakePresets.json:
"generator": "Ninja",
"cacheVariables": {
"CMAKE_POLICY_DEFAULT_CMP0091": "NEW",
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
},
+"toolset": {
+ "value": "host=x64",
+ "strategy": "external"
+},
"architecture": {
"value": "x86",
"strategy": "external"
},
But, in order to get VSCode (and hopefully Qt Creator soon) to detect / pick the right toolset, it needs to be:
"toolset": {
- "value": "host=x64",
+ "value": "v193,host=x64",
"strategy": "external"
},
And like the "Visual Studio" compiler, I'm not seeing CMAKE_GENERATOR_PLATFORM
or CMAKE_GENERATOR_TOOLSET
there either.
The reason why things are by default if possible in the toolchain file is because conan needs to be compatible down to CMake 3.15, so no presets. The more things we put in the presets, the more complicated is for developers with CMake < 3.20 to issue a command line that will work for them.
Completely understandable. I appreciate your commitment to maintaining support/stability for folks on older versions of CMake.
I guess I was under the impression that when external
was used, CMake ignored those values...so I'd be surprised if it complicated command line usage in any way.
That's certainly what the CMake 3.20 cmake-presets doc seems to suggest:
"external" Do not set the value, even if the generator supports it. This is useful if, for example, a preset uses the Ninja generator, and an IDE knows how to set up the Visual C++ environment from the architecture and toolset fields. In that case, CMake will ignore the field, but the IDE can use them to set up the environment before invoking CMake.
Same for the MSDN doc according to Select your target and host architecture when building with the Visual C++ toolset:
The
architecture.strategy
andtoolset.strategy
values tell CMake how to handle the architecture and toolset fields.set
means CMake sets the respective value, andexternal
means CMake won't set the respective value.
As best I can tell, these toolset
/ architecture
fields appear to be the way to tell the IDE what env to load. And since https://github.com/conan-io/conan/pull/11666, Conan already has limited support for this with Visual Studio, so I was hoping it may be possible to extend what we write slightly that way we can support more IDEs like VSCode (and soon Qt Creator and maybe eventually CLion). At least I struggle to see how it could be worse than the status quo.
Conan just needs to prefix the toolset.value
with the toolset version somehow.
https://github.com/conan-io/conan/blob/aef2eea04fa5c457ae28950b836264d969ec1322/conan/tools/cmake/presets.py#L70
Really bad psuedo code:
+toolset_version = msvc_version_to_toolset_version(conanfile.settings.get_safe("compiler.version"))
+toolset_value = toolset_version
+if toolset_arch:
+ toolset_value = toolset_value + "," + toolset_arch
ret["toolset"] = {
- "value": toolset_arch,
+ "value": toolset_value
"strategy": "external"
}
Anyways, I can always work around the issue if needed. I think it'd be consistent and an improvement with what Conan is already doing, and improved CMakePresets support seems like the direction a lot of IDEs are going, but I totally understand the compatibility concerns. If the request is not in alignment with where Conan is going at present, feel free to close the issue :)
Thanks again for considering the request. Conan is a tremendous product and you, your team, and this community do a tremendous job. Keep up the good work!
CMAKE_GENERATOR_TOOLSET only affects the Visual Studio generators (well, and also Xcode and Green Hills MULTI, for non-MSVC usage). And it doesn't set the environment directly even then - it just puts the toolset into the .vcxproj files, leaving the ultimate resolution for MSBuild. It doesn't have any effect at all when you are using Ninja/Make/etc - those rely on you having already called vcvarsall. conan handle that for itself, by putting the vcvars call into conanbuild.bat (and thus into anything launched by the conanfile.py's self.run
. But IDEs mostly don't have any way to make use of a .bat file that would launch a new shell with the environment altered, since the process is already running.
These "strategy": "external"
toolset entries seem to be what the major IDE vendors are coalescing on, so it would be nice if conan would include that information (even though it is semi-redundant to conanvcvars.bat).
@thorntonryan, does this workaround still work for you with Conan 2.0? I am getting "No CMAKE_CXX_COMPILER could be found." which means that the VSCode does not load vcvars
.
@mpusz ,
Using Conan 1.58 and a project using cmake_layout
, looks like I needed to tweak the generated CMakeUserPresets.json in the following way:
```diff
{
"version": 4,
"vendor": {
"conan": {}
},
"include": [
"C:\\path\\to\\build\\Debug\\generators\\CMakePresets.json",
"C:\\path\\to\\buid\\RelWithDebInfo\\generators\\CMakePresets.json"
- ]
+ ],
+ "configurePresets": [
+ {
+ "name": "Debug",
+ "displayName": "Debug",
+ "inherits": "debug",
+ "toolset": {
+ "value": "v143,host=x64",
+ "strategy": "external"
+ },
+ "cacheVariables": {
+ "CMAKE_CXX_COMPILER": "cl.exe",
+ "CMAKE_MAKE_PROGRAM": "ninja.exe"
+ }
+ },
+ {
+ "name": "RelWithDebInfo",
+ "displayName": "RelWithDebInfo",
+ "inherits": "relwithdebinfo",
+ "toolset": {
+ "value": "v143,host=x64",
+ "strategy": "external"
+ },
+ "cacheVariables": {
+ "CMAKE_CXX_COMPILER": "cl.exe",
+ "CMAKE_MAKE_PROGRAM": "ninja.exe"
+ }
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "Debug",
+ "displayName": "Debug",
+ "configurePreset": "Debug",
+ "configuration": "Debug"
+ },
+ {
+ "name": "RelWithDebInfo",
+ "displayName": "RelWithDebInfo",
+ "configurePreset": "RelWithDebInfo",
+ "configuration": "RelWithDebInfo"
+ }
+ ]
}
Honestly not sure why these need to be defined. I thought I've called cmake
from a VS Dev prompt before and it finds cl.exe
automatically , so I'm not sure why VSCode seems to need it.
But at least it finds the right cl.exe
.
Maybe try that?
Thanks! By adding the following:
{
"version": 3,
"vendor": {
"conan": {}
},
"cmakeMinimumRequired": {
"major": 3,
"minor": 15,
"patch": 0
},
"configurePresets": [
{
"name": "conan-msvc-193",
"displayName": "'conan-msvc-193' config",
"description": "'conan-msvc-193' configure using 'Ninja Multi-Config' generator",
"generator": "Ninja Multi-Config",
"cacheVariables": {
"CMAKE_POLICY_DEFAULT_CMP0091": "NEW",
+ "CMAKE_CXX_COMPILER": "cl.exe"
},
"architecture": {
"value": "x64",
"strategy": "external"
},
+ "toolset": {
+ "value": "v143,host=x64",
+ "strategy": "external"
+ },
"toolchainFile": "D:\\repos\\units\\build\\msvc-193\\generators\\conan_toolchain.cmake",
"binaryDir": "D:\\repos\\units\\build\\msvc-193"
}
],
"buildPresets": [
{
"name": "conan-msvc-193-release",
"configurePreset": "conan-msvc-193",
"configuration": "Release"
}
],
"testPresets": [
{
"name": "conan-msvc-193-release",
"configurePreset": "conan-msvc-193",
"configuration": "Release"
}
]
}
I was able to make MSVC 193 work somehow. The only problem compared to running from VS Dev prompt is that I get the following warning:
warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
However, when I tried to do the same for MSVC 192 installed under VS2022 it didn't work. I also tried with -c tools.microsoft.msbuild:vs_version=17
provided to conan install command line with no luck.
Wonder if this could be accomplished using the new msvs_toolset
helper:
https://github.com/conan-io/conan/pull/13041
There is already conf::tools.cmake.cmaketoolchain:toolset_arch
in place which controls the generation of the toolset
section / injects host=
into the toolset.value
.
Except this is not correctly prefixed with settings::compiler.toolset
, respectively is missing entirely when the config entry for toolset_arch
wasn't overwritten.
Hi all,
I am checking this, but need some guidance, it would be necessary to update the reproduction, it seems that latest Conan 2.0.17 is adding toolset
to the presets, still, it doesn't automatically work for me in VSCode, which seems the ultimate goal.
Steps:
conan new cmake_exe -d name=app -d version=0.1
conan install . -c tools.cmake.cmaketoolchain:generator=Ninja
The resulting presets will have:
"toolset": {
"value": "v143",
"strategy": "external"
},
"architecture": {
"value": "x64",
"strategy": "external"
},
code .
the current folderv143,host=x64
manually to the presets, still doesn't workCan anyone please provide with detailed updated repro? Thanks!
Without host=x64
, "value": "v143"
is under-specified and defaults to the old x86 host toolchain.
I expect you got the warning
[preset] Configure preset ...: No toolset architecture specified for cl.exe, using "host=x86" by default
Did you have the x86 host toolchain installed? Just guessing, but Microsoft may finally have switched to x64 as the default (and only) installed host toolset for v143.
Without host=x64, "value": "v143" is under-specified and defaults to the old x86 host toolchain.
But even if I add it manually to my presets, still same error. (I will clarify in my above steps). Not really a x86 toolchain issue, it seems that even with the host=x64
it is not working.
You clicked here?
When you do that, what messages do you get in the "Output" panel?
[driver] Removing C:/Users/Diego/conanws/kk/build/Release/CMakeCache.txt
[driver] Removing C:\Users\Diego\conanws\kk\build\Release\CMakeFiles
[proc] Executing command: C:\ws\cmake\cmake-3.25.3-windows-x86_64\bin\cmake.EXE -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=C:/Users/memsharded/conanws/kk/build/Release/generators/conan_toolchain.cmake -SC:/Users/memsharded/conanws/kk -BC:/Users/memsharded/conanws/kk/build/Release -G Ninja
[cmake] -- Using Conan toolchain: C:/Users/memsharded/conanws/kk/build/Release/generators/conan_toolchain.cmake
[cmake] -- Conan toolchain: C++ Standard 14 with extensions OFF
[cmake] -- The CXX compiler identification is unknown
[cmake] CMake Error at CMakeLists.txt:2 (project):
[cmake] No CMAKE_CXX_COMPILER could be found.
[cmake]
[cmake] Tell CMake where to find the compiler by setting either the environment
[cmake] variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
[cmake] to the compiler, or to the compiler name if it is in the PATH.
CMAKE_C_COMPILER
and CMAKE_CXX_COMPILER
are both required as cache variables for Ninja. Set both to "cl.exe"
.
No warnings prefixed with [preset]
, so that should have been sane.
The invocation of vswhere is silent in that output
Yes, that is right, adding both
"cacheVariables": {
"CMAKE_POLICY_DEFAULT_CMP0091": "NEW",
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_CXX_COMPILER": "cl.exe",
"CMAKE_C_COMPILER": "cl.exe"
}
Seems to make it work. The output was sometimes confusing, because it runs automatically before adding it, so it is not clear if it is running with your latest changes or running the previous state.
Maybe making
conan install . -c tools.cmake.cmaketoolchain:generator=Ninja
-c tools.build:compiler_executables="{'c': 'cl.exe', 'cpp': 'cl.exe'}"
-c tools.cmake.cmaketoolchain:toolset_arch=x64
to add cl.exe to Presets (at the moment it only adds it to conan_toolchain.cmake
.
By the way, the way to define the x64 toolset is:
conan install . -c tools.cmake.cmaketoolchain:generator=Ninja -c tools.cmake.cmaketoolchain:toolset_arch=x64
and that will make
"toolset": {
"value": "v143,host=x64",
"strategy": "extern
automatically
CMAKE_C_COMPILER and CMAKE_CXX_COMPILER are both required as cache variables for ~Ninja~ ~VSCode~ VSCodes' cmake-tools integration.
Minor correction, but this requirement is a subtle wrinkle of ~VSCode's~ VSCode's cmake-tools implementation: https://github.com/microsoft/vscode-cmake-tools/blob/main/src/preset.ts#L753-L754
Yeah, my understanding is that the integration of cmake-tools for VSCode checks the CMAKE_XX_COMPILER to decide to call vcvars automatically.
One other thing that seems missing here is a way to have the toolset be something like "v143,version=14.29"
when trying to use an installation that contains Side-by-side minor version MSVC toolsets. That's the syntax adopted by cmake -T
in CMake 3.12 and greater and also copied for VScode's handlling of toolset { . strategy: "external" }`, specifically in varsForVSInstallation)
So maybe [conf]tools.cmake.cmaketoolchain:toolset_version
, translated to ,version=...
and appended similarly to toolset_arch
?
Hmm, actually this seems to be partially in place already:
GenericSystemBlock.get_toolset already has code to use settings.compiler.version and settings.compiler.update such that compiler.version=193 and compiler.update=7 would result in toolset=...,version=14.37. Which I think is good enough - Visual Studio doesn't support side-by-side patch versions, just side-by-side minors, so there's little reason to what to specify a 3- or 4-digit version anyway. And if you care, you probably care enough that putting it in settings (and thus getting distinct package_id) is appropriate.
But conan.tools.microsoft.visual._vcvars_vers does not seem to have similar code to consider settings.compiler.update, so it will only do 14.1, 14.2, or 14.3, but never distinguish -vcvars_ver=14.37
vs -vcvars_ver=14.38
. Which means conanbuild.bat wouldn't get the same minor version that CMakePresets does....
Split off the VCvars issue as #15522, since that's not actually about CMakePresets
https://github.com/conan-io/conan/issues/15522 has been merged it will be in Conan 2.3.
I was having another look, this is the current state:
toolset
information"cacheVariables": {
"CMAKE_POLICY_DEFAULT_CMP0091": "NEW",
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_CXX_COMPILER": "cl.exe",
"CMAKE_C_COMPILER": "cl.exe"
}
for VSCode automatically launching vcvars, this is not happening anymore.
Can anyone please confirm this? The only missing gap would be the CMAKE_<LANG>_COMPILER
definitions? Can you make it work with such workaround?
This ticket is going to be closed when https://github.com/conan-io/conan/pull/16762 is merged, hopefully for next Conan 2.7 release, if someone wants to try that PR or give any feedback. Thanks!
Closed by https://github.com/conan-io/conan/pull/16762 for next 2.7.0 release
I'm reopening this and assigning to 2.8.0 as we are reverting these changes and release 2.7.1 without them because of this issue: https://github.com/conan-io/conan/issues/16960 We will try to fix this in Conan 2.8.0
What is your suggestion?
Suggestion
Would it be possible for the Conan generated CMakePresets.json to include
msvc.toolset
version details (i.e.v143
,v142
, etc.) when populating thetoolset.value
field?This would allow IDEs to know which
vcvarsall.bat
environment to use when building the project.Expected Behavior
For example, when cross-compiling with VS2022 x64 to x86, I'd expect to see the conan generated CMakePresets.json look something like:
_I can use
tools.cmake.cmaketoolchain:toolset_arch=x64
to add the "host=x64" portion, but I don't have anyway to getv143
added._VSCode recognizes this
toolset
/architecture
combination and correctly chooses VS2022 and callsvcvarsall.bat amd64_x86
prior to calling CMake.Current Behavior
Conan doesn't include
toolset
details in the generated CMakePresets.json file, so in order to get IDEs like VSCode to find the right environment, we need to adjust CMakePresets.json (as described above) or worse adjust the CMakeUserPresets.json file as follows:Conan already knows which vcvarsall to call, and and ensures the correct one gets called in the generated
conanvcvars.bat
.Conan also appears to know about
msvc.toolset
version information: https://github.com/conan-io/conan/blob/e33b55a486fd208223524dda49cce02dbe70c214/conans/client/conf/__init__.py#L117 At least for the legacy toolsetsAnd seems to know about the mapping: https://github.com/conan-io/conan/blob/e0a8ee058bc8dc2d9811b8aeb6999f69aeb78d85/conan/tools/microsoft/visual.py#L53-L60
It seems like Conan could should be able to use the
msvc.toolset
information from the build profile and populate the version field correctly.Context
Follow up to https://github.com/conan-io/conan/issues/11623
Some IDEs are capable of targeting multiple toolsets (e.g. VS2015, VS2019, VS2022), and
toolset.value
is the way for the IDE to know whichvcvarsall.bat
to load and use internally while compiling.https://github.com/microsoft/vscode-cmake-tools/pull/2524
QTCREATOR-BUG 28693
Thanks for your support!
Have you read the CONTRIBUTING guide?