Search code examples
cmakecross-compilingarm64raspberry-pi4

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.


Solution

  • Finally, I discovered that the toolchain I was using was not properly configured for multiarch and then was not searching for those files in /usr/lib/aarch64-linux-gnu. Looks like there is no way to add parameters into the gcc or g++ command line to add some locations for searching this kind of files. I switched to the toolchain provided in Ubuntu (sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu) and everything was running smoother. Hope this will help someone.