Tuesday, February 6, 2024

[SOLVED] In CMake why is it okay to set the compiler without also setting the linker?

Issue

I'm newly learning CMake. In the course of my various readings, I sometimes encounter instruction to explicitly set the C/C++ compiler, e.g. by passing a -D CMAKE_CXX_COMPILER "/path/to/compiler" argument to cmake, or a set(CMAKE_CXX_COMPILER "/path/to/compiler") statement in your CMakeLists.txt or a "cacheVariables": {"CMAKE_CXX_COMPILER": "/path/to/compiler"} line in your CMakePresets.json. (One example is this post, but there are obviously many similar Q&A/tutorials with similar guidance). One use-case that comes to mind is on Windows, where I believe Visual Studio installs cl.exe by default and gives you the option to additionally install clang-cl.exe.

But doesn't your choice of compiler also drive your choice of other toolchain utilities, e.g. the linker, maybe the archiver, etc.? Why is it sufficient to only set CMAKE_CXX_COMPILER but not some corresponding variable that controls the linker, e.g. CMAKE_LINKER?

What I mean is: I'm aware that there are CMake cache variables to control both the choice of compiler and linker, but broadly speaking, online tutorials, articles, Stack Overflow posts, etc., that discuss setting CMAKE_CXX_COMPILER do not also hand-in-hand discuss setting CMAKE_LINKER. E.g. if I explicitly do set(CMAKE_CXX_COMPILER "gcc"), why don't I need to also explicitly do set(CMAKE_LINKER "ld")?

Can someone please explain the relationship between the compiler and linker (and other related toolchain utilities) in the context of CMake? Why is it sufficient to only set CMAKE_CXX_COMPILER but not some corresponding variable that controls the linker, e.g. CMAKE_LINKER?


(I have a not-fully-formed notion in my head that "compilers" like gcc and presumably cl.exe are actually "compiler drivers" which means that they actually wrap/encapsulate other executables that actually do the compiling and linking (and archiving?) -- is this correct, and related to the question?)


Solution

By knowing a compiler, in most cases CMake is able to guess about location of other utilities needed for compile, link and some other processes.

The guessing is performed according to the compiler's path and information, which compiler is able to report about itself (see e.g. description of variable CMAKE_<LANG>_COMPILER_ID). As for the link process, by default CMake uses the compiler itself for drive the linking: https://stackoverflow.com/a/25274328/3440745.

In rare cases, when CMake fails to guess about other parts of the toolchain, one need to additionally set other variables (which is normally done in a toolchain file).



Answered By - Tsyvarev
Answer Checked By - Terry (WPSolving Volunteer)