Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[question] Can CMakeToolchain tell CMake the correct compilers? #11842

Closed
1 task done
fschoenm opened this issue Aug 11, 2022 · 11 comments
Closed
1 task done

[question] Can CMakeToolchain tell CMake the correct compilers? #11842

fschoenm opened this issue Aug 11, 2022 · 11 comments

Comments

@fschoenm
Copy link

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!
@franramirez688
Copy link
Contributor

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.

@fschoenm
Copy link
Author

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.

@memsharded
Copy link
Member

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.

@fschoenm
Copy link
Author

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

@jcar87
Copy link
Contributor

jcar87 commented Aug 11, 2022

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.

@fschoenm
Copy link
Author

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.

@b1ackviking
Copy link
Contributor

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

@memsharded
Copy link
Member

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 memsharded added this to the 1.53 milestone Sep 2, 2022
@fschoenm
Copy link
Author

fschoenm commented Sep 6, 2022

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.

@czoido czoido modified the milestones: 1.53, 1.54 Oct 4, 2022
@memsharded memsharded modified the milestones: 1.54, 1.55 Nov 2, 2022
@memsharded
Copy link
Member

memsharded commented Nov 24, 2022

Hi @fschoenm

We have added in #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!

@fschoenm
Copy link
Author

Looks fine to me. Thanks for spending the effort!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants