conan icon indicating copy to clipboard operation
conan copied to clipboard

[question] Can CMakeToolchain tell CMake the correct compilers?

Open fschoenm opened this issue 2 years ago • 2 comments

My understanding of the new CMakeToolchain's purpose was that it can also be used to guarantee that CMake uses the correct compiler versions. However, that doesn't seem to be the case?

See the examples below. As I understand so far, the user is responsible for selecting the correct compiler when using CMake? Is there a way to force CMake to use the correct compiler that has been defined in the conan profile or is that not in scope of the CMakeToolchain generator?

Linux example

I have a gcc10 profile (with CC/CXX environment variables). As you can see, CMake uses the (default) GCC 11 compiler instead of GCC 10, which has been defined in the conan profile.

$ cat ~/.conan/profiles/gcc10
[settings]
os=Linux
os_build=Linux
arch=x86_64
arch_build=x86_64
compiler=gcc
compiler.version=10
compiler.libcxx=libstdc++11
[options]
[build_requires]
[env]
CC=gcc-10
CXX=g++-10

$ conan install -s build_type=Debug -pr gcc10 .
$ cmake --preset debug ../..
Preset CMake variables:

  CMAKE_BUILD_TYPE="Debug"
  CMAKE_POLICY_DEFAULT_CMP0091="NEW"
  CMAKE_TOOLCHAIN_FILE:FILEPATH="/home/fschoenm/devel/project/build/generators/conan_toolchain.cmake"

-- Using Conan toolchain: /home/fschoenm/devel/project/build/generators/conan_toolchain.cmake
-- The CXX compiler identification is GNU 11.2.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
    ...

Windows example

Same issue here: CMake doesn't know about the compiler specified in the conan toolchain. In my IDE (e.g. CLion) the compiler that was selected in the IDE is used instead of the one specified in the conan install call.

> conan install . -pr msvc193 -s build_type=Debug
Configuration:
[settings]
arch=x86_64
arch_build=x86_64
build_type=Debug
compiler=msvc
compiler.cppstd=20
compiler.runtime=dynamic
compiler.runtime_type=Debug
compiler.version=193
os=Windows
os_build=Windows
[options]
[build_requires]
[env]
[conf]
tools.cmake.cmaketoolchain.presets:max_schema_version=3
tools.cmake.cmaketoolchain:generator=Ninja

...

> cmake --preset debug
Preset CMake variables:

  CMAKE_BUILD_TYPE="Debug"
  CMAKE_POLICY_DEFAULT_CMP0091="NEW"
  CMAKE_TOOLCHAIN_FILE="C:\devel\project\cmake-build\generators\conan_toolchain.cmake"

-- Using Conan toolchain: C:/devel/project/cmake-build/generators/conan_toolchain.cmake
-- Conan toolchain: C++ Standard 20 with extensions OFF
-- The CXX compiler identification is unknown
CMake Error at CMakeLists.txt:20 (project):
  The CMAKE_CXX_COMPILER:

    cl

  is not a full path and was not found in the PATH.

  Tell CMake where to find the compiler by setting either the environment
  variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
  to the compiler, or to the compiler name if it is in the PATH.


-- Configuring incomplete, errors occurred!

fschoenm avatar Aug 11 '22 08:08 fschoenm

The problem is that CMake is not a toolchain responsibility in general. For example, for Visual Studio compilers, it is defined in the CMake generator and not in the toolchain. So the approach that Conan follows hasn't changed much from the legacy build system integrations, and it is still the responsibility of the users to have the dev environment that matches the declared configuration.

But at least, the new tools provide some more explicit helpers. For example for Visual Studio compilers, it can generate a conanvcvars script (that will be called automatically from conanbuild.bat), that activates the correct Visual Studio environment that some setups (Ninja, etc) might need to correctly find the compilers.

franramirez688 avatar Aug 11 '22 10:08 franramirez688

Why is that though? conan could easily set the correct compilers in the toolchain file or the CMake preset to make sure that everything fits together. So far there isn't even a check that the CMake-selected compiler matches the one specified in the conan profile.

fschoenm avatar Aug 11 '22 11:08 fschoenm

conan could easily set the correct compilers

Because it is not that easy. The previous integration, the cmake generator had some compiler checks. We had to provide a escape CONAN_DISABLE_CHECK_COMPILER to disable it, because it would be raising false positives more often that we would have desired. And it was only checking some known compilers and some known versions. There are too many different compilers setups, toolchain variants, locations, way to use them, etc. to be able to provide such robustness. And even with that effort, that will still not cover all the cases, just some of them, for example when the Visual Studio vcvars needs to be activated to be able to build with that compiler version in build systems like Ninja or NMake.

memsharded avatar Aug 11 '22 14:08 memsharded

I trust that you have more insight into all possible problems with that but according to the CMake Wiki it's easy to switch to a different compiler. Conan already knows which compiler to use when calling conan install so I'm wondering if there's a way to initialize CMake with it, regardless of what the IDE or CMake think the correct/default setting might be.

I'm curious why the CMakeToolchain generators doesn't even try to e.g. set environment variables from the profile like CC/CXX because that alone might already be enough to let CMake select the corresponding compiler.

See what happens if I manually add the environment variables to the CMake preset:

$ cmake --preset debug ../..

  CMAKE_BUILD_TYPE="Debug"
  CMAKE_POLICY_DEFAULT_CMP0091="NEW"
  CMAKE_TOOLCHAIN_FILE:FILEPATH="/home/fschoenm/devel/project/build/generators/conan_toolchain.cmake"

Preset environment variables:

  CC="gcc-10"
  CXX="g++-10"

-- Using Conan toolchain: /home/fschoenm/devel/project/build/generators/conan_toolchain.cmake
-- The CXX compiler identification is GNU 10.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/g++-10 - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done

fschoenm avatar Aug 11 '22 15:08 fschoenm

Why is that though? conan could easily set the correct compilers in the toolchain file or the CMake preset to make sure that everything fits together.

Conan knows which compiler and compiler version you intend to use, however, Conan does not necessarily know where that compiler lives, and different Linux distributions follow different conventions with regards to being able to install multiple versioned copies of the GNU Toolchain side by side.

I trust that you have more insight into all possible problems with that but according to the CMake Wiki it's easy to switch to a different compiler.

Thanks for bringing this example to our attention, @fschoenm! In this example, CMake is assuming two things:

  • That the gcc-4.2 can be found in the default search path (usually contents of PATH)
  • That /usr/bin/g++-4.2 exists - note that the /usr/bin location is typically reserved for Linux distribution maintainers - so here we depend on Linux distros system packages to use that convention, and specific system package installed that places a compiler executable in that location.

Unfortunately this convention of is not uniform across Linux distributions - and as such there isn't any "safe" assumption that we can make. Traditionally on Linux distros you will find the C and C++ compilers in the cc and c++ executables (likely to be /usr/bin/cc and /usr/bin/c++). Since gcc is the default compiler in most GNU Linux, these will be symliked to a gcc executable. That is the assumption that most build systems on Linux makes to locate the "default" compiler, this includes CMake, and AutoMake files that are compliant with the GNU build system. We also rely on this in Conan to populate the values of the default profile.

For example, on Ubuntu Linux you will find that if you have the "default" g++ installed, you have /usr/bin/g++-11 (alonsgide /usr/bin/c++ and /usr/bin/g++ which will all point to the same).

However, on other Linux distributions, the name of the compiler executable that includes the version may follows a different convention, for example aarch64-redhat-linux-gcc-8 can be found on CentOS (for the GCC 8 C compiler). However, the C++ compiler (g++) is only available either as c++, g++, or aarch64-redhat-linux-g++. There is no "versioned" executable to choose - so even if a Conan profile knew that we need gcc-8.

jcar87 avatar Aug 11 '22 18:08 jcar87

Sure, I agree that it might be complicated to cover all cases. But somebody somewhere has to know where the compiler lives. It can even be configured in the profile. Obviously, the profile has to be correct for the machine and its installation paths.

When using conan create to create a package, the compiler specified in the profile (via environment variables) is selected correctly to compile the source. But when consuming the packages with conan install suddenly that mechanism is thrown out of the window and the developer (or CMake) has to figure out by itself compiler to use?

That doesn't make much sense to me. I already showed above that it's possible to tell CMake the correct compiler via a toolchain file or via presets.

fschoenm avatar Aug 11 '22 19:08 fschoenm

There are also #9962 and #10877 discussion on this feature.

b1ackviking avatar Sep 02 '22 06:09 b1ackviking

Quick question, why the above Windows example doesn't define the env-vars too in the profile, as the Linux profile does?

Also a 2.0 tip: use [buildenv] instead of [env] together with VirtualBuildEnv generator in the consumer side to be 2.0 ready.

Maybe we want to consider a conf, similar to the recent tools.build:cxxflags confs, that defines the compiler directly to the toolchain, for those cases where env-var definition (Windows...) might not work?

memsharded avatar Sep 02 '22 09:09 memsharded

Quick question, why the above Windows example doesn't define the env-vars too in the profile, as the Linux profile does?

No specific reason. We mainly develop on Linux and support Windows with less effort going into it.

fschoenm avatar Sep 06 '22 12:09 fschoenm

Hi @fschoenm

We have added in https://github.com/conan-io/conan/pull/12556, for 1.55 the possibility to explicitly tell the compilers to CMake (not only CMake, but also other build systems as well), via a new tools.build:compiler_executables configuration.

I think this PR will solve this request, could you please have a look and confirm? Thanks!

memsharded avatar Nov 24 '22 11:11 memsharded

Looks fine to me. Thanks for spending the effort!

fschoenm avatar Nov 24 '22 13:11 fschoenm