How is TOOLCHAIN_LD used?

I am using the GNU ARM toolchain to cross-compile an ARM Cortex-M4 application on Windows.

In my toolchain file I have:

get_filename_component(TOOLCHAIN ${CROSS_GCC_PATH} PATH)
set(CMAKE_C_COMPILER ${TOOLCHAIN}/arm-none-eabi-gcc${SUFFIX})
set(CMAKE_Cxx_COMPILER ${TOOLCHAIN}/arm-none-eabi-g++${SUFFIX})
set(TOOLCHAIN_as ${TOOLCHAIN}/arm-none-eabi-as${SUFFIX} CACHE STRING "arm-none-eabi-as")
set(TOOLCHAIN_LD ${TOOLCHAIN}/arm-none-eabi-ld${SUFFIX} CACHE STRING "arm-none-eabi-ld")
set(TOOLCHAIN_SIZE ${TOOLCHAIN}/arm-none-eabi-size${SUFFIX} CACHE STRING "arm-none-eabi-size")

The resulting compiler command correctly uses arm-none-eabi-gcc but I find that the linker command also uses arm-none-eabi-gcc whereas I need it to call arm-none-eabi-ld.

Any ideas why please?

TOOLCHAIN_* are not variables used by CMake - they have no special meaning. See here: https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html for a list of recognised variables.

Additionally CMAKE_Cxx_COMPILER is misspelled - should be all upper case or you’re in for a surprise.

Thanks for your reply. I reworked my toolchain file to have:

set(CMAKE_C_COMPILER ${TOOLCHAIN}/arm-none-eabi-gcc${SUFFIX})
set(CMAKE_CXX_COMPILER ${TOOLCHAIN}/arm-none-eabi-g++${SUFFIX})
set(CMAKE_LINKER ${TOOLCHAIN}/arm-none-eabi-ld${SUFFIX} CACHE STRING "arm-none-eabi-ld")

but the linker command is still calling arm-none-eabi-gcc instead of arm-none-eabi-ld.

Any further thoughts please?

Well, typically you just don’t and gcc will forward everything just right to the ld.
If you really have to, I think you must adjust CMAKE_LINKER and CMAKE_CXX_LINK_EXECUTABLE as described here: gcc - CMake: use a custom linker - Stack Overflow

The makefile that I am replacing explicitly calls arm-none-eabi-ld to do the linking so I think it best to do that.

I tried the suggestion from the Stack Overflow post:

cmake -S .. -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain-gnu-arm.cmake -DCMAKE_LINKER=/home/asic/lib/ARM/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-ld -DCMAKE_CXX_LINK_EXECUTABLE="<CMAKE_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>"

but CMake is still calling arm-none-eabi-gcc to do the link.

CMake uses the compiler to drive the linker since it adds things like the standard library and other such things on its own. If CMake always used the linker, it would have to reverse engineer whatever flags get passed through the compiler driver.

Does using the compiler work? If so, just go with it. CMake does not offer fine-grained control over the linker because it is not well-abstracted at CMake level (between languages or generators).