CMake: use a custom linker

I want to setup a custom toolchain with cmake. I've set the compiler but I don't know how to set the linker. This error is reported because cmake try to use the compiler to link:

The C compiler "xgcc.exe" is not able to compile a simple test program.

Here there is a snippet of my toolchain file

# specify the cross compiler
INCLUDE(CMakeForceCompiler)
SET(CMAKE_C_COMPILER   xgcc.exe)
SET(CMAKE_CXX_COMPILER xgcc.exe)
#CMAKE_FORCE_C_COMPILER(xgcc.exe GNU)
#CMAKE_FORCE_CXX_COMPILER(xgcc.exe GNU)

I've tried to force the compiler but the linker problem will not be solved.


The link command line is set in Modules/CMake{C,CXX,Fortran}Information.cmake and defaults to using the compiler, not CMAKE_LINKER (see source code). This can be changed by replacing the rule that builds the link command line, which lives in variables CMAKE_CXX_LINK_EXECUTABLE (and friends). NB that variable does not indicate the path to the linker executable; it says how to link an executable!

One approach is to set that rule to use the linker, e.g.

cmake -DCMAKE_LINKER=/path/to/linker -DCMAKE_CXX_LINK_EXECUTABLE="<CMAKE_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>"

See also this post from CMake mailing list and this one - this also makes a natural place to prepend a linker modifier to another linker.


As Mabraham points out, CMake calls the compiler to do the linking. So, by far the simplest solution to this is to LET IT, and instead tell the compiler to run a different linker when called.

Which, as noted in this other answer — but now it's even a documented option in gcc --help=common — is as easy as:

cmake -DCMAKE_CXX_FLAGS="-fuse-ld=lld"

g++ or clang++ will get passed the -fuse-ld=lld1 flag on every call, and when they do any linking they'll use the specified command instead of the built-in default. Easy-peasy, and CMake need not concern itself with such things at all.

(BTW, the option is parsed (-f) (use-ld) (=) (lld), there's no "fuse" option to gcc.)

Notes
  1. When using Clang, lld can be replaced with whatever other linker command you want to use, like ld.exe, ld.gold, mingw32/bin/ld.exe, etc.

    GCC isn't as flexible, its -fuse-ld only accepts one of three possible arguments: lld, bfd, or gold. It will invoke the first matching ld.foo executable it finds on the PATH. (Thanks to bviktor for pointing out GCC's limitations for alternate linker selection.)


Set the variable ${CMAKE_LINKER} either in CMakeCache.txt or after ccmake . under advanced options.