User:Jimis

From Qt Wiki
Jump to navigation Jump to search

Notes on cross-compiling Qt 6.5 (including all submodules with examples) for both armhf and aarch64 architectures for Raspberry Pi OS

  • We'll be using Clang-13 as the compiler and lld-13 as the linker. This is mostly to avoid building a toolchain, which would be required with GCC and binutils.
  • We are copying the sysroot from a 64-bit installation of Raspberry Pi OS. However it will contain both 32-bit and 64-bit libraries, installed according to the Debian Multiarch HOWTO.

Host build

Cross-compiling Qt-6 requires that we perform a host build first in order to have tools like

moc

and

lupdate

available for the cross-build.

  • Install the packages for the compiler and the linker, depending on the system. For OpenSUSE-Tumbleweed I needed to install
 llvm13-libclang13 clang13-devel lld13

NOTE: Avoid having multiple versions of Clang installed (it caused linkage problems obscure enough to be detected only when the

lupdate

binaries were segfaulting!)

  • Configure the host build. I use developer-build to not need installation.
cd $HOME/qt6-host-developer-build
$SRC_DIR/configure -developer-build -linker lld -nomake tests -nomake examples \
    --  -DCMAKE_C_COMPILER=clang-13 -DCMAKE_CXX_COMPILER=clang++-13

Preparing the sysroot on Raspberry Pi OS with both 32-bit and 64-bit libraries

To cross-compile for a system, you need to have all the system libraries and header files of the target copied into the host. This is called a sysroot.

To prepare that, the best way is to try compiling on the target itself. You don't need to actually complete the compilation, but at least the configuration step should be successful.

After lots of trial and errors, these are the packages that I installed on Raspberry Pi OS:

LIBDEPS="libfontconfig1-dev libfreetype6-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libxcb-glx0-dev libxcb-keysyms1-dev\
    libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-util-dev\
    libxcb-xinerama0-dev libxcb-xkb-dev libxkbcommon-dev libxkbcommon-x11-dev\
    libdrm-dev libdrm-etnaviv1 libdrm-freedreno1 libdrm-tegra0 libgl-dev libglx-dev mesa-common-dev\
    libegl-dev libegl1-mesa-dev libgbm-dev libgles-dev libgles2-mesa-dev libglvnd-dev libopengl-dev libopengl0 libvulkan-dev mesa-vulkan-drivers\
    libxcb-cursor-dev libxcursor-dev\
    libssl-dev libjpeg-dev"

sudo apt update
sudo dpkg --add-architecture armhf

# Install 64-bit libraries
sudo apt install  $LIBDEPS

# Install 32-bit libraries
sudo apt install crossbuild-essential-armhf
echo $LIBDEPS | sed -E -e 's/ +|$/:armhf /g' | xargs sudo apt install

WARNING: do not install

clang-*-dev

on the target, it causes linking problems on tools like

lupdate

and is not required for a successful build.

Copy the sysroot to the host

On the x86_64 host:

SYSROOT=$HOME/sysroot-RPiOS/
rsync --info=progress2 -ar --copy-unsafe-links --delete -z --zc lz4 pi@rasbperry-pi:usr $SYSROOT/

This will copy all of

/usr

into the $SYSROOT directory, using fast compression for quicker transfer over the network.

It will also replace symlinks that escape the directory, with the actual file contents.

A workaround is needed for clang and ninja to avoid rebuilding everything on every rebuild attempt:

ln -s usr/lib     $SYSROOT/lib
ln -s usr/include $SYSROOT/include
ln -s usr/arm-linux-gnueabihf $SYSROOT/arm-linux-gnueabihf

CROSS-COMPILING

For targeting 64-bit Raspberry Pi OS, set:

ARCH=aarch64
TRIPLET=aarch64-linux-gnu

For targeting 32-bit Raspberry Pi OS, retaining compatibility all the way back to the original Raspberry Pi, set:

ARCH=armhf
TRIPLET=arm-linux-gnueabihf

And then configure the actual cross-compilation:

SYSROOT=$HOME/sysroot-RPiOS
QT_HOST_PATH="$HOME/qt6-host-developer-build/qtbase"

CC=clang-13
CXX=clang++-13
CFLAGS="-O1 -target $TRIPLET --sysroot $SYSROOT"
LDFLAGS="-Wl,-rpath-link,$SYSROOT/usr/lib/$TRIPLET"
CXXFLAGS="$CFLAGS"
ASMFLAGS="$CFLAGS"
PREFIX=$HOME/qt-$ARCH

PKG_CONFIG_PATH=  \
PKG_CONFIG_SYSROOT_DIR="$SYSROOT" \
PKG_CONFIG_LIBDIR="$SYSROOT/usr/lib/$TRIPLET/pkgconfig:$SYSROOT/usr/share/pkgconfig" \
    $SRC_DIR/configure \
    -make examples -xcb -opengl es2 -debug -linker lld \
    -sysroot "$SYSROOT" -prefix "$PREFIX" \
    -qt-host-path "$QT_HOST_PATH" \
    --  -DCMAKE_C_COMPILER="$CC" -DCMAKE_CXX_COMPILER="$CXX" \
        -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DCMAKE_ASM_FLAGS="$ASMFLAGS" \
        -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS" -DCMAKE_EXE_LINKER_FLAGS="$LDFLAGS" -DCMAKE_MODULE_LINKER_FLAGS="$LDFLAGS" \
        -DCMAKE_SYSROOT="$SYSROOT" -DCMAKE_SYSTEM_NAME=Linux \
        -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
        -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY