conan
conan copied to clipboard
[feature] Setting `CMAKE_<LANG>_COMPILER` in a toolchain
Problem statement
Right now it is common to use a different compiler for conan install and CMake configure steps which result in an error during project configuration.
Potential solution
From my observation, it is typical to set CXX and CC environment variables in the Conan profile file. In case a user provides them and uses such a profile during conan install step it would be great if CMakeToolchain would set CMAKE_<LANG>_COMPILER cache variables based on those.
Thanks to that we will always end up with consistent builds and users will just have to call:
conan install .. -pr my_profile
cmake .. -toolchain conan_toolchain.cmake
- [x] I've read the CONTRIBUTING guide.
+1
@mpusz I think that would kind of defeat the purpose of the consistency between profiles and the toolchain. Why not just have different profiles for the different compilers? You can also set the compiler directly in the CMakeToolchain generator, which is what I do for gcc-arm-none-eabi and differently named compilers.
@jwillikers I am not sure if we are on the same page here 😉
I always have different profiles for different compilers. However, fixing a specific compiler (with a specific path in CMakeToolchain) is not the solution as different people will have the binaries in different places, versions, names on their platforms.
What I meant is that right now I have to do something like this:
conan install .. -pr gcc11
cmake .. -toolchain conan_toolchain.cmake -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11
It is common to forget about setting specific compilers in the second-line or make it inconsistent (i.e. when a default gcc link on a platform is upgraded to a new version).
It would be much easier if the compiler path was provided in the conan_toolchain.cmake file based on the [env] profile entry.
@mpusz You can do some more complicated stuff to configure the CMAKE_C_COMPILER and CMAKE_CXX_COMPILER in the generated conan_toolchain.cmake, or provide your own CMake toolchain file to Conan through the related [conf] variables. CMake toolchain files are really meant for that and additional configuration of the toolchain.
But, I completely agree that it's a very common need, and I'd like it to be simpler. I'm not sure the [env] setting is the best approach, since Conan is trying to move away from the use of [env] variables. Configuring different names and locations for a compiler is useful for any generator and compiler, too. Perhaps a set of dedicated [conf] variables could be added to allow specifying a particular suffix and prefix for the various tools in the toolchain, i.e. gcc / g++ and/or an option to add additional compiler search paths may also be helpful. Or maybe it would be simplest to just provide a single option to configure the full path to the compiler. Whichever makes the most sense. This way any generator could make use of the configuration values to set the appropriate compiler.
Here's a possible example using a made up configuration value, tools.c_compiler.path, that sets the path of the C compiler.
[settings]
compiler = gcc
[conf]
tools.c_compiler.path = /path/to/my/toolchain/custom-gcc
The CMakeToolchain generator could then use this value to set CMAKE_C_COMPILER in the conan_toolchain.cmake.
set(CMAKE_C_COMPILER /path/to/my/toolchain/custom-gcc)
You can do some more complicated stuff to configure the
CMAKE_C_COMPILERandCMAKE_CXX_COMPILERin the generatedconan_toolchain.cmake, or provide your own CMake toolchain file to Conan through the related[conf]variables. CMake toolchain files are really meant for that and additional configuration of the toolchain.
Sure, I agree. But this works great for unified corporate environments. You prepare a toolchain file and it works for everyone as long as they are on the same or similar file system.
My suggestion is to make things easier for the Open Source community where everyone has their own file system and preferred compiler. I observe this is a common issue to set a different compiler for Conan and CMake used by the command line or IDE.
I like your idea with dedicated [conf] variables. It should be way better than setting some unspecified variables [env].
@mpusz I just noticed that the generated CMake toolchain file using Conan 1.45.0 now includes the ability to use environment variables to set the C and CXX compilers.
if(NOT DEFINED ENV{CC})
set(CMAKE_C_COMPILER gcc)
endif()
if(NOT DEFINED ENV{CXX})
set(CMAKE_CXX_COMPILER g++)
endif()
I'm experimenting with the CMakeToolchain generator, and I experience the same problem as @mpusz (Conan version 1.45.0). I expected that the generated conan_toolchain.cmake toolchain file would set the C++ compiler (CMAKE_CXX_COMPILER) based on the profile compiler settings, but it does not. It does translate many of my Conan profile settings into the toolchain file though, like C++ standard and standard library (CMAKE_CXX_FLAGS_INIT) and the build type (CMAKE_BUILD_TYPE), but not the compiler itself. In particular, the CMake code snippet above is not present in my toolchain file.
It's useful to be able to customize the toolchain, through configurations like tools.cmake.cmaketoolchain:user_toolchain, but I did not expect I had to do it for simple use cases ("use clang 12, and not the default system compiler").
I had a look at the code (the _get_compiler method in https://github.com/conan-io/conan/blob/develop/conan/tools/cmake/toolchain/blocks.py, around line 704), and it seems suspicious that the returned cpp_compiler is always None on my system.
@stigsand You should be able to just set the CC and CXX environment variables to point to clang-12 and clang++-12 respectively either in your shell or in the [env] section of a profile, but if Conan isn't detecting a compiler at all that sounds like something weird is going on in your particular installation. I don't think I've run in to that before.
Thank you, @jwillikers. As I understand it, it's outside the current scope of the CMakeToolchain generator to deduce/guess CMAKE_CXX_COMPILER based on the compiler settings during conan install.
In some tests, conan create is invoked, and it logs the correct settings to the console:
Configuration:
[settings]
arch=x86_64
arch_build=x86_64
build_type=Debug
compiler=clang
compiler.libcxx=libc++
compiler.version=6.0
os=Linux
os_build=Linux
[options]
[build_requires]
[env]
Then CMake is invoked:
CMake command: cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE="/path/to/generated/conan_toolchain.cmake" ...
-- Using Conan toolchain: /path/to/generated/conan_toolchain.cmake
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
This seems somewhat surprising.
It could be very nice if CMAKE_CXX_COMPILER could be set to the compiler executable name, based on the settings.
For the above example, the result would be clang++-6.0 .
In the Professional CMake book, chapter 21.3. "Tool Selection":
The path to the compiler is controlled by the CMAKE_<LANG>_COMPILER variable,
which can be set in a toolchain file or on the command line to manually control the compiler used,
or it can be omitted to allow CMake to choose one automatically.
If the name of an executable is provided manually without a path, CMake will search for it using find_program().
If a full path to a compiler is provided, it will be used directly.
If no compiler is manually specified, CMake will select a compiler based on an internal set of defaults for the target platform and generator.
The find_program() documentation explains the rules to find the executable.
But, I can understand that this can be tricky.
For example, on Ubuntu 18.04, naming is clang++-6.0, g++-7, g++-8 for system wide installed compilers.
I don't know if other Linux distributions have the same naming.
On a Windows machine, a MinGW distribution have naming like x86_64-w64-mingw32-g++.exe.
Looking at the source code linked by @stigsand , it seems that some work is already done for Windows ?
Whats the state of this feature/issue?
Do I understand it correctly: The recommende way is to use [env] in profiles which specifies CC and CXX?
And how should it be done for compilers which are provided via conan packages?
They already set CC inside package_info via env_info, but it is also not taken into account.
It seems that this feature got even more needed with the introduction of CMake Presets. Now we can generate a bunch of different presets for different compilers but mostly they do not work as expected. I can run them from the CMake command line or an IDE like VS Code, but actually, they do not do anything (or all are doing nearly exactly the same) as they use the same compiler for CMake run. There is no way to change the compiler path in the IDE while changing a preset. That is why I needed to manually adjust the generated CMakePresets.json files to contain something like:
"cacheVariables": {
"CMAKE_POLICY_DEFAULT_CMP0091": "NEW",
"CMAKE_C_COMPILER": "gcc-12",
"CMAKE_CXX_COMPILER": "g++-12"
},
That is inconvenient and really surprising to many. Also, I must be really careful not to run the conan install after that as it might override the changes or new configs for new compilers will just not work.
Before CMake Presets usage the VSCode was using CMake Kits with predefined paths to the compiler and the build directory and everything worked nicely.
Please take into account that the paths set through the conf[] parameter should probably be set automatically by Conan as CC and CXX (or CMAKE_<LANG>_COMPILER) environment variables so conan install --build missing works correctly (such build does not include the toolchain file generated in this step). It would be unfortunate to force the user to set the same path twice in a profile file.