RPI aarch64 cross compilation : unable to link

I’m trying to cross compile for the raspberry pi 4 (64 bits) using cmake from Ubuntu 20.04.
I’m using the latest bullseye image with desktop and recommended software from the official raspberry website.

For the toolchain, I’m using this one : https://sourceforge.net/projects/raspberry-pi-cross-compilers/files/Bonus%20Raspberry%20Pi%20GCC%2064-Bit%20Toolchains/Raspberry%20Pi%20GCC%2064-Bit%20Cross-Compiler%20Toolchains/Bullseye/GCC%2010.2.0/

When I try to build any program, I’m having this error message (even for the preliminary checks performed by cmake to be sure the env is able to build for the target):

/home/user/RPI_BUILD_ENV/toolchain/cross-pi-gcc-10.2.0-64/bin/../lib/gcc/aarch64-linux-gnu/10.2.0/../../../../aarch64-linux-gnu/bin/ld: cannot find crt1.o: No such file or directory
/home/user/RPI_BUILD_ENV/toolchain/cross-pi-gcc-10.2.0-64/bin/../lib/gcc/aarch64-linux-gnu/10.2.0/../../../../aarch64-linux-gnu/bin/ld: cannot find crti.o: No such file or directory
    collect2: error: ld returned 1 exit status

The command line used to link is the following:

/home/user/RPI_BUILD_ENV/toolchain/cross-pi-gcc-10.2.0-64/bin/aarch64-linux-gnu-gcc   --sysroot=/home/user/RPI_BUILD_ENV/sysroot/   CMakeFiles/cmTC_50c5a.dir/testCCompiler.c.o -o cmTC_50c5a -Wl,-rpath-link,/home/user/RPI_BUILD_ENV/sysroot/lib   -L/home/user/RPI_BUILD_ENV/sysroot/usr/lib  -L/home/user/RPI_BUILD_ENV/sysroot/usr/lib/aarch64-linux-gnu

I’ve checked /home/user/RPI_BUILD_ENV/sysroot/usr/lib/aarch64-linux-gnu/crt1.o and /home/user/RPI_BUILD_ENV/sysroot/usr/lib/aarch64-linux-gnu/crti.o both exists.

I have checked that the toolchain is aligned with the sysroot in terms of architecture (aarch64) and version of glibc (2.31) and everything is correct.

Here is the content of my cmake toolchain file:

#
# CMake Toolchain file for crosscompiling on ARM.
#
# Target operating system name.
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_CROSSCOMPILING TRUE)

set(CMAKE_SYSROOT $ENV{RPI_SYSROOT})

# Name of C compiler.
set(CMAKE_C_COMPILER $ENV{RPI_TOOLCHAIN}$ENV{CC})
set(CMAKE_CXX_COMPILER $ENV{RPI_TOOLCHAIN}$ENV{CXX})

set(CMAKE_AR $ENV{RPI_TOOLCHAIN}$ENV{AR})
set(CMAKE_ASM_COMPILER $ENV{RPI_TOOLCHAIN}$ENV{AS})
set(CMAKE_OBJCOPY $ENV{RPI_TOOLCHAIN}$ENV{OBJCOPY})
set(CMAKE_RANLIB $ENV{RPI_TOOLCHAIN}$ENV{RANLIB})

# Target architecture
set(CMAKE_LIBRARY_ARCHITECTURE aarch64-linux-gnu)
set(CMAKE_C_COMPILER_TARGET aarch64-linux-gnu)
set(CMAKE_CXX_COMPILER_TARGET aarch64-linux-gnu)

# Name of linker and its args
set(CMAKE_LINKER $ENV{CXX})
set(CMAKE_CXX_LINK_FLAGS "<FLAGS> --sysroot=$ENV{RPI_SYSROOT} <LINK_FLAGS> <OBJECTS> -o <TARGET> -Wl,-rpath-link,$ENV{RPI_SYSROOT}lib <LINK_LIBRARIES>")
set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_LINKER} ${CMAKE_CXX_LINK_FLAGS}")

set(CMAKE_C_LINK_FLAGS "<FLAGS> --sysroot=$ENV{RPI_SYSROOT} <LINK_FLAGS> <OBJECTS> -o <TARGET> -Wl,-rpath-link,$ENV{RPI_SYSROOT}lib <LINK_LIBRARIES>")
set(CMAKE_C_LINK_EXECUTABLE "$ENV{CC} ${CMAKE_C_LINK_FLAGS}")

add_compile_options(-pthread)

# Where to look for the target environment. (More paths can be added here)
set(CMAKE_FIND_ROOT_PATH $ENV{RPI_SYSROOT})

# Where to find header files for target
include_directories(SYSTEM ${CMAKE_FIND_ROOT_PATH}usr/include
                           ${CMAKE_FIND_ROOT_PATH}usr/include/${CMAKE_CXX_COMPILER_TARGET})

# Where to find libraries for target
link_directories(${CMAKE_FIND_ROOT_PATH}/usr/lib/
                 ${CMAKE_FIND_ROOT_PATH}/usr/lib/${CMAKE_CXX_COMPILER_TARGET}/)

# Adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment only.
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# Search headers and libraries in the target environment only.
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

And here is the content of the shell script I’m using to configure the environment variables:

#!/bin/bash
export RPI_SYSROOT="${HOME}/RPI_BUILD_ENV/sysroot/"
export RPI_TOOLCHAIN="${HOME}/RPI_BUILD_ENV/toolchain/cross-pi-gcc-10.2.0-64/bin/"
export PATH="${RPI_TOOLCHAIN}:${PATH}"
export CC="aarch64-linux-gnu-gcc"
export CXX="aarch64-linux-gnu-g++"
export CPP="aarch64-linux-gnu-gcc"
export LD="aarch64-linux-gnu-ld"
export AR="aarch64-linux-gnu-ar"
export AS="aarch64-linux-gnu-as"
export RANLIB="aarch64-linux-gnu-ranlib"
export STRIP="aarch64-linux-gnu-strip"
export OBJCOPY="aarch64-linux-gnu-objcopy"
export OBJDUMP="aarch64-linux-gnu-objdump"
export NM="aarch64-linux-gnu-nm"
export GDB="aarch64-linux-gnu-gdb"

I don’t understand what’s happening and why I cannot link any binary using this environment.

Can somebody help me on this topic.

Thanks for your help.

  • Have you tried to build simple C program in the command line (without CMake)? It would help to separate toolchain issues from CMake ones. If building simple C program in command line returns the same error message, then something wrong with your toolchain, and CMake is unrelated to that problems. If building simple C program succeed in command line, the compare the successful command with the one generated by CMake.

    – 

  • Hi, Thanks for your quick reply. I created a simple Makefile to cross compile a hello world with this toolchain and it works (at least, it build and link). I didn’t check if it run on the RPI, but ….

    – 




  • Looks like -L does not influence where ld is looking for .o files. Actually, ld does not find crti.o, crt1.o, crtn.o because they are located into <sysroot>/usr/lib/aarch64-linux-gnu. If I put a symlink for each of these files into <sysroot>/usr/lib pointing to <sysroot>/usr/lib/aarch64-linux-gnu, then ld succeed to find them. Any hints on how to tell ld where to look for .o files (any parameters to be passed to gcc / g++ as I’m not calling ld directly) ?

    – 

  • I didn’t work with the toolchain you use, so I cannot suggest anything about its usage. According to their README, creating symlinks to system object files is a normal way to go.

    – 




Leave a Comment