electrodyssey.net

Odyssey of Electronics and Computers

Qt5 cross-compilation environment for Raspberry Pi

July 26, 2020 — Nazim

This post is a brief extract of a wonderfully detailed video made by Ulas Dikme. Many thanks to Ulas for sharing his experiences, it saved me several days of work setting up the cross-compilation environment.

Ulas was using an Ubuntu 20 Virtual Box machine for building a sysroot and qt base. While it's not the best solution performance-wise, it's certainly very convenient in terms of being portable across the host machines. My Qt5 build system resides on a USB hard drive.


VM installation

The first part of the video covers a Virtual Box ubuntu installation and set up. Please don't forget to allocate a sufficient amount of RAM and VCPU resources. 4 to 6 VCPU might be adequate for make -j 6

I would refer to ubuntu VM as to a host system. Once the host system is up and running, we need to install some prerequisite development packages.

    apt-get install gawk wget git-core diffstat unzip \
    texinfo gcc-multilib  build-essential chrpath socat \
    libsdl1.2-dev xterm

    apt-get install build-essential make  gawk curl git \
    git-lfs diffstat unzip texinfo build-essential \
    chrpath libsdl1.2-dev xterm gperf bison gcc-multilib \
    g++-multilib

Target (Raspbery Pi) system setup

Download the official Raspberry Pi OS and flash the image.

download rpi

    wget --content-disposition --retry-connrefused \
    --waitretry=2 https://downloads.raspberrypi.org/raspios_armhf_latest

flash the image

    unzip 2020-05-27-raspios-buster-armhf.zip

lsblk will show your block devices, choose a correct one and rewrite the entire device with an image. Some sources advise to reduce the write block size (bs) down to 1M, which makes it slower. I've been using bs=4M with no issues.

    dd if=2020-05-27-raspios-buster-armhf.img of=/dev/mmcblk0  bs=4M conv=fsync

Once the image is copied to a micro sd card, insert it into the slot and power up the board.

Please login into the target system and update /etc/apt/sources.list

Line below must be uncommented:

deb-src http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi

Update the packages:

    apt-get update
    apt-get upgrade

run firmware update and accept changes

    rpi-update


     *** Updating firmware
     *** Updating kernel modules
     *** depmod 5.4.51+
     *** depmod 5.4.51-v7l+
     *** depmod 5.4.51-v8+
     *** depmod 5.4.51-v7+
     *** Updaating VideoCore libraries
     *** Using HardFP libraries
     *** Updating SDK
     *** Running ldconfig
     *** Storing current firmware revision
     *** Deleting downloaded files
     *** Syncing changes to disk
     *** If no errors appeared, your firmware was successfully updated to **70598414a73afab7f8e521c358a7cfd5ffb65d3e**
     *** A reboot is needed to activate the new firmware

In his video Ulas urges us to note the firmware revision for later. Current revision is accessible via /boot/.firmware_revision

    root@raspberrypi:/home/pi# cat /boot/.firmware_revision
    70598414a73afab7f8e521c358a7cfd5ffb65d3e

It would allow us to reproduce the working environment and keep track of the updates.

To install a specific firmware version use rpi-update:

    rpi-update <revision number here>

Please be warned that Raspberry Pi may not boot after the firmware update. Mine was not booting up until I've disconnected the 5V jumper line between a touch screen and raspberry pi GPIO header and powered the screen with a separate USB PSU.

it's a good idea to enable ssh before the Raspberry Pi reboot and check if it starts.

Enable ssh server on a target

    systemctl enable ssh
    systemctl daemon-reload
    systemctl start ssh

    check the status
    systemctl status ssh

Installation of qt & dependencies on a target system

Login as root and install all of the prerequisites.

I was logging in via ssh from the host machine for convenience.

    apt-get build-dep qt5-qmake
    apt-get build-dep libqt5webengine-data
    apt-get install libboost1.58-all-dev libudev-dev libinput-dev \
    libts-dev libmtdev-dev libjpeg-dev libfontconfig1-dev

    apt-get install libssl-dev libdbus-1-dev libglib2.0-dev libxkbcommon-dev \
    libegl1-mesa-dev libgbm-dev libgles2-mesa-dev mesa-common-dev

    apt-get install libasound2-dev libpulse-dev gstreamer1.0-omx \
    libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-alsa

    apt-get install libvpx-dev libsrtp0-dev libsnappy-dev libnss3-dev

    apt-get install "^libxcb.*"


    apt-get install libfreetype6-dev libicu-dev libsqlite3-dev libxslt1-dev \
    libavcodec-dev libavformat-dev libswscale-dev

    apt-get install libgstreamer0.10-dev gstreamer-tools libraspberrypi-dev \
    libx11-dev libglib2.0-dev

    apt-get install freetds-dev libsqlite0-dev libpq-dev libiodbc2-dev firebird \
    -dev libjpeg9-dev libgst-dev libxext-dev libxcb1 libxcb1-dev libx11-xcb1

    apt-get install libxcb-sync1 libxcb-sync-dev libxcb-render-util0 \
    libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0 libxcb-randr0-dev

    apt-get install libxcb-glx0-dev libxi-dev libdrm-dev libssl-dev \
    libxcb-xinerama0 libxcb-xinerama0-dev

    apt-get install libatspi-dev libssl-dev libxcursor-dev libxcomposite-dev \
    libxdamage-dev libfontconfig1-dev

    apt-get install libxss-dev libxtst-dev libpci-dev libcap-dev libsrtp0-dev \
    libxrandr-dev libnss3-dev libdirectfb-dev libaudio-dev

Create directory for qt5

    mkdir /usr/local/qt5pi
    chown pi:pi /usr/local/qt5pi

Compilation of Qt in ubuntu vm

when the vm is ready, apt-get update, upgrade & install dependencies:

    apt-get install gcc git bison python gperf pkg-config
    apt-get install libclang-dev

    mkdir /opt/qt5pi
    chown dev:dev /opt/qt5pi

Latest qt versions are reliably cross-compiled with a linaro toolchain, so let's get linaro.

Download Linaro cross-compiler

    cd /opt/qt5pi
    wget https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz

untar it:

    tar xf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz

add the tool chain path to a .bashrc

    export PATH=$PATH:/opt/qt5pi/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin

and export it in a current session

Download the latest qt (an original version in video was 5.14.x)

    http://download.qt.io/official_releases/qt/5.15/5.15.0/single/qt-everywhere-src-5.15.0.tar.xz

and untar it under /opt/qt5pi/

Create sysroot on a host machine

Create sysroot on a host device

Rsync target files into a host for cross compilation

    rsync -avz root@10.0.0.7:/lib sysroot

    rsync -avz root@10.0.0.7:/usr/include sysroot/usr

    rsync -avz root@10.0.0.7:/usr/lib sysroot/usr

    rsync -avz root@10.0.0.7:/opt/vc sysroot/opt

make a backup of libEGL

    mv sysroot/usr/lib/arm-linux-gnueabihf/libEGL.so.1.1.0 \
    sysroot/usr/lib/arm-linux-gnueabihf/bak_orig_libEGL.so.1.1.0
    mv sysroot/usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.1.0 \
    sysroot/usr/lib/arm-linux-gnueabihf/backup_orig_libGLESv2.so.2.1.0

create symlinks

    ln -s sysroot/opt/vc/lib/libEGL.so \
    sysroot/usr/lib/arm-linux-gnueabihf/libEGL.so.1.1.0

    ln -s sysroot/opt/vc/lib/libGLESv2.so \
    sysroot/usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.1.0

    ln -s sysroot/opt/vc/lib/libEGL.so \
    sysroot/opt/vc/lib/libEGL.so.1

    ln -s sysroot/opt/vc/lib/libGLESv2.so \
    sysroot/opt/vc/lib/libGLESv2.so.2

fix absolute link names in sysroot

Download ./sysroot-relativelinks.py script and run it on a sysroot. This python script will process all of the symlinks in sysyroot and make them relative.

    wget https://raw.githubusercontent.com/riscv/riscv-poky/master/scripts/sysroot-relativelinks.py

    root@ubuntu-qt:/opt/qt5pi# chmod 755 sysroot-relativelinks.py
    root@ubuntu-qt:/opt/qt5pi# ./sysroot-relativelinks.py sysroot

create a build directory, configure the build and start it:

    root@ubuntu-qt:/opt/qt5pi# mkdir qt5build

    root@ubuntu-qt:/opt/qt5pi# cd qt5build/

    root@ubuntu-qt:/opt/qt5pi/qt5build#

Run configure script

    ../qt-everywhere-src-5.15.0/configure -opengl es2 -device linux-rasp-pi4-v3d-g++ \
    -device-option CROSS_COMPILE=arm-linux-gnueabihf- -sysroot /opt/qt5pi/sysroot -gcc-sysroot \
    -prefix /usr/local/qt5pi -opensource -confirm-license -skip qtscript -skip qtwayland \
    -skip qtdatavis3d -nomake examples -make libs -pkg-config -no-use-gold-linker -v

Once everything is built, you must run 'make install'. Qt will be installed into '/opt/qt5pi/sysroot/usr/local/qt5pi'.

This will take a while to complete:

    make -j 6
    make install

Copy cross compiled qt into a target (10.0.0.7 is my Raspberry Pi):

    cd /opt/qt5pi/
    dev@ubuntu-qt:/opt/qt5pi$ rsync -avz sysroot/usr/local/qt5pi root@10.0.0.7:/usr/local

Install and configure Qt creator

    dev@ubuntu-qt:/opt/qt5pi$ apt-cache showpkg qtcreator
    Package: qtcreator
    Versions:
    4.11.0

    dev@ubuntu-qt:/opt/qt5pi$ sudo apt-get install qtcreator

Configure Qt Creator embedded device kit

Navitage to QT Creator's "Options" -> "Kits"

Add new kit as a generic linux device

Alt

Navigate to "Qt Versions" tab and select the manual, then add "/opt/qt5pi/sysroot/usr/local/qt5pi/bin/qmake"

Go to "Compilers" tab

click "Add" -> "GCC" -> "C", add the linaro cross compiler's path there : /opt/qt5pi/gcc-linaro-7.5.0-2019.12-x8664arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc and name it

change "ABI" to custom, it will change to arm linux generic elf 32bit

click "Apply" / "Ok"

Alt

click "Add" -> "GCC" -> "C++", add the linaro cross compiler's path there : /opt/qt5pi/gcc-linaro-7.5.0-2019.12-x8664arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ and name it

change "ABI" to custom, it will change to arm linux generic elf 32bit

click "Apply" / "Ok"

Alt

now go back to the "kits" tab, select your kit and change the C / C++ compilers to the ones you've just added.

change the qt version as well to qt5pi and apply changes

Alt

Click on "devices" entry in a navigation list Click "Add" and select a generic linux device, then supply an ip address, login and a private key to log in

Alt

Add ssh key to allow an automated deployment into a target system.

Alt

Go back to kits, your new device shall be selecteds under devices

Alt

Your cross-compilation environment is now ready. Create a new project with a qt5-rpi4 environment, build it and copy to the target device. You should be able to run the cross-compiled executable.

Tags: embedded, qt, linux, raspberry-pi