Remote Qt development
Let´s take a look how you can develop and cross compile Qt applications for your Raspberry Pi.
If you want to develop a graphical user interface for the Raspberry Pi, in most cases you end up with a solution that is realized with Qt. This is a universal C ++ library for creating graphical interfaces for various operating systems, such as B. Windows, Linux or Android.
Unfortunately, a Raspberry Pi does not offer a lot of computing power, which is why the development of graphical interfaces on the Raspberry Pi is rather unattractive. A much more elegant way would be if the program was developed on a host PC and then copied and executed on the Raspberry Pi via remote connection.
And that's exactly what this guide should be about. I will show how the Raspberry Pi and an Ubuntu host system can be used to develop Qt applications for the Raspberry Pi on the host system, which are then run remotely on the Raspberry Pi.
Prepare the Raspberry Pi
For a smooth process, the operating system (here Raspbian) on the Raspberry Pi must be updated. To do this, the file /etc/apt/sources.list
must first be adjusted and Debian source packages must be permitted. Add this to the file:
deb-src http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
Then the package list, the packages and the operating system of the Raspberry Pi are updated:
$ sudo apt-get update
$ sudo apt-get dist-upgrade
$ sudo reboot
$ sudo rpi-update
$ sudo reboot
Then the missing packages are installed:
$ sudo apt-get build-dep qt5-qmake
$ sudo apt-get build-dep libqt5gui5
$ sudo apt-get build-dep libqt5webengine-data
$ sudo apt-get build-dep libqt5webkit5
$ sudo apt-get install libudev-dev libinput-dev libts-dev libxcb-xinerama0-dev libxcb-xinerama0 gdbserver
And finally, a folder for the Qt installation and some additional symlinks are created:
$ sudo mkdir /usr/local/RaspberryQt
$ sudo chown -R pi:pi /usr/local/RaspberryQt
$ ln -s /opt/RaspberryQt/sysroot/opt/vc/lib/libEGL.so /opt/RaspberryQt/sysroot/usr/lib/arm-linux-gnueabihf/libEGL.so.1.0.0
$ ln -s /opt/RaspberryQt/sysroot/opt/vc/lib/libGLESv2.so /opt/RaspberryQt/sysroot/usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0
$ ln -s /opt/RaspberryQt/sysroot/opt/vc/lib/libEGL.so /opt/RaspberryQt/sysroot/opt/vc/lib/libEGL.so.1
$ ln -s /opt/RaspberryQt/sysroot/opt/vc/lib/libGLESv2.so /opt/RaspberryQt/sysroot/opt/vc/lib/libGLESv2.so.2
The configuration of the Raspberry Pi is now complete. It continues with the host ...
Compile Qt for the Raspberry Pi
For the host system I used an Ubuntu 18.04 LTS in a virtual machine.
Here, too, the package sources and packages must first be updated and a few additional packages installed.
$ sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
$ sudo apt update
$ sudo apt install libjasper-dev
$ sudo apt-get install -y git cmake build-essential pkg-config libjpeg-dev libtiff5-dev libpng-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev libatlas-base-dev gfortran wget unzip libz-dev zlib1g-dev gcc g++ git bison python gperf gdb-multiarch qt5-default texinfo make python3-dev
Then the working directories are created and the rights configured accordingly:
$ sudo mkdir /opt/RaspberryQt
$ sudo mkdir /opt/RaspberryQt/build
$ sudo mkdir /opt/RaspberryQt/sysroot /opt/RaspberryQt/sysroot/usr /opt/RaspberryQt/sysroot/opt
$ sudo chown -R 1000:1000 /opt/RaspberryQt
An SSH key for the Raspberry Pi is then created for easier work, which avoids annoying password entries when copying the data.
$ ssh-keygen -t rsa -C root@<IP Raspberry Pi> -P "" -f ~/.ssh/rpi_root_id_rsa
$ ssh-keygen -t rsa -C pi@<IP Raspberry Pi> -P "" -f ~/.ssh/rpi_pi_id_rsa
$ cat ~/.ssh/rpi_root_id_rsa.pub | ssh root@<IP Raspberry Pi> 'cat >> .ssh/authorized_keys && chmod 640 .ssh/authorized_keys'
$ cat ~/.ssh/rpi_pi_id_rsa.pub | ssh pi@<IP Raspberry Pi> 'cat >> .ssh/authorized_keys && chmod 640 .ssh/authorized_keys'
The necessary files can then be downloaded.
$ cd /opt/RaspberryQt
$ git clone https://github.com/raspberrypi/tools
$ wget https://download.qt.io/archive/qt/5.12/5.12.8/single/qt-everywhere-src-5.12.8.tar.xz
$ wget https://raw.githubusercontent.com/riscv/riscv-poky/master/scripts/sysroot-relativelinks.py
The files are a cross compiler for the Raspberry Pi, the Qt version used (here 5.12.8) and a Python script to replace symbolic links of files with relative links (will be needed later).
Then the Qt version is unpacked and the name of the compiler used (here arm-linux-gnueabihf
) is adjusted in the Qt configuration file.
$ tar xf qt-everywhere-src-5.12.8.tar.xz
$ cp -R qt-everywhere-src-5.12.8/qtbase/mkspecs/linux-arm-gnueabi-g++ qt-everywhere-src-5.10.1/qtbase/mkspecs/linux-arm-gnueabihf-g++
$ sed -i -e 's/arm-linux-gnueabi-/arm-linux-gnueabihf-/g' qt-everywhere-src-5.12.8/qtbase/mkspecs/linux-arm-gnueabihf-g++/qmake.conf
Now the libraries used by the target (here the Raspberry Pi) Pi are still required. These can be downloaded from the Raspberry Pi using rsync
.
$ rsync -avz root@<IP vom Raspberry Pi>:/lib sysroot
$ rsync -avz root@<IP vom Raspberry Pi>:/usr/include sysroot/usr
$ rsync -avz root@<IP vom Raspberry Pi>:/usr/lib sysroot/usr
$ rsync -avz root@<IP vom Raspberry Pi>:/opt/vc sysroot/opt
It may take a few minutes to download. These files will later be required for the Qt build process, since Qt requires some standard libraries from the target system (here the Raspberry Pi).
Before the files can be used, the symbolic links that still point to the file system of the Raspberry Pi must be replaced by relative links from the new sysroot
directory.
/opt/RaspberryQt/sysroot-relativelinks.py /opt/RaspberryQt/sysroot
Finally, Qt is configured.
$ cd /opt/RaspberryQt/build
$ ../qt-everywhere-src-5.12.8/configure -opengl es2 -device linux-rasp-pi3-g++ -device-option CROSS_COMPILE=/opt/RaspberryQt/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- -sysroot /opt/RaspberryQt/sysroot -prefix /usr/local/RaspberryQt -opensource -confirm-license -no-gbm -skip qtscript -nomake tests -nomake examples -make libs -pkg-config -no-use-gold-linker -v
During configuration, the type of the target must be specified via the parameter of the argument -device
. The following table applies to the parameters.
Target
Option
Raspberry Pi 1 (+ Zero and Zero W)
linux-rasp-pi-g++
Raspberry Pi 2
linux-rasp-pi2-g++
Raspberry Pi 3
linux-rasp-pi3-g++
Raspberry Pi 3 with VC4 driver
linux-rasp-pi3-vc4-g++
Once the configuration is complete, Qt can be compiled and installed.
$ make -j4
$ make install
The number of cores used is specified via parameter -j4
, which can speed up the process. With a core, the entire process takes a good 3-4 hours (depending on the system). The fully compiled Qt libraries are then copied to the Raspberry Pi using rsync
.
$ cd /opt/RaspberryQt
$ rsync -avz sysroot/usr/local/RaspberryQt root@<IP des Raspberry Pi>:/usr/local
The Qt libraries and the Raspberry Pi are now ready for use. Qt applications can now be created, compiled and executed on the Raspberry Pi. The next step is to create a new GDB, because the GDB from the Raspberry Pi Toolchain does not have any support for the Python programming language and therefore cannot be used in the Qt Creator.
Compiling GDB
Before GDB can be compiled, a few additional packages must be installed:
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install texinfo gcc gcc-c++ make python3-devel wget
The sources for GDB can be downloaded directly from the FTP server of the GNU project by using the wget
command:
$ wget https://ftp.gnu.org/gnu/gdb/gdb-9.1.tar.xz
$ tar xf gdb-9.1.tar.xz
$ mkdir gdb-9.1/build
The installed Python version and the corresponding Python libraries are required to create GDB:
$ export PYTHON=python3
$ export PYTHON_LIBDIR=$("${PYTHON}" -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
GDB can now be configured and created:
$ cd gdb-9.1/build
$ ../configure --prefix=/home/kampi/GDB/bin --target=arm-linux-gnueabihf --with-python=${PYTHON} LDFLAGS="-L${PYTHON_LIBDIR}"
$ make -j4
$ make -C gdb install
The GDB version created is saved in the bin/
directory at the end of the compilation process.
This would complete the tools. I'll show you in the next step how you can set up the Qt Creator.
Configure Qt Creator for the host system
The Qt Creator is best suited for the development of Qt applications. Since the installation via the official Ubuntu package sources didn't work for me and the Qt Creator always throw some errors me, I downloaded and ran the Qt installer directly from the website.
$ cd ~/Downloads
$ sudo chmod +x qt-unified-linux-x64-3.0.6-online.run
$ ./qt-unified-linux-x64-3.0.6-online.run
After installation, the Qt Creator must still be configured for the Raspberry Pi. To do this, the Creator is started and the menu Tools → Settings is opened. Then the Devices submenu is opened and click on Add... to add a new Generic Linux device.
The Start Wizard button confirms the selection and creates a new device. The key file already created can be used for the SSH connection. The setup of the new device is completed with Next → Complete. The Qt Creator then tests the settings and tries to connect to the device.

If the test was successful, the window can be closed. The new device is now listed in the device list.

The kit, i.e. the compiler, debugger and source collection, is then created. The Settings menu is opened again via Tools and the Kits item is selected. In the Compiler tab, the Add button adds an entry for a C and a C ++ compiler (both can be found under GCC).

Compiler
Path
C
/home/kampi/Toolchain/Raspberry Pi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc/opt/RaspberryQt/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc
C++
/home/kampi/Toolchain/Raspberry Pi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-g++/opt/RaspberryQt/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-g++
The entries are then confirmed by clicking Apply.
Next, the Qt version for the Raspberry Pi is created. To do this, the Qt Versions tab is opened and the Add button is used to create a new entry. A file browser opens with which the path of the created qmake
is selected.

The entry is confirmed by clicking the Apply
button.
In the last step, a new debugger is created. To do this, the Debugger tab is opened and a new entry is created using the Add button and filled in with the path of the debugger created.

Now the kit can be created. The Kits tab is opened and a new kit is created using the Add button. The mask is now filled in according to the screenshot.

Here too, the entry is confirmed by clicking on Apply. The window can then be closed with OK.
Create the first application
Now that all tools are together, a sample project should be developed on the Ubuntu host system and executed remotely on the Raspberry Pi. Via File → New... a new Qt-Widgets project is created. The individual entries are confirmed with Next. When selecting the kit, the Raspberry Pi Kit that has just been created is selected as the kit.

All other entries can be confirmed directly with Next and the wizard can then be closed with Close.
Next, the deployment rule must be adjusted in the project file, since the user pi is not allowed to access the default directory /opt
by default. Therefore the path in /home/pi
is changed.
target.path = /home/pi/$${TARGET}/bin
INSTALLS += target
In the created project, two environment variables must then be set for the target, i.e. the Raspberry Pi. To do this, the Projects tab is opened and the item Execute the current kit is selected. The variables DISPLAY =: 0
and XAUTHORITY = /home/pi/.Xauthority
are created and set in the submenu Execution Environment.

In addition, the command line parameters must be set to -platform xcb
.

This means that the setup is ready for use and nothing stands in the way of developing graphic applications on the PC for the Raspberry Pi. With a click on the green arrow in the side bar or with the key combination Ctrl + R the project is created and the application is started a few seconds later on the Raspberry Pi.

Add additional modules
The installation carried out is a minimal installation, in which not all modules are present (e.g. the Qt charts are missing). These modules can be installed later by downloading the sources of the respective module from the submodules directory of the respective Qt version (hereinafter carried out for Qt charts):
$ wget http://download.qt.io/official_releases/qt/5.12/5.12.8/submodules/qtcharts-everywhere-src-5.12.8.tar.xz
$ tar xf qtcharts-everywhere-src-5.12.8.tar.xz
After unpacking, you change to the directory and start the installation. The path of the created qmake
is required for this:
$ cd qtcharts-everywhere-src-5.12.8
$ /opt/RaspberryQt/sysroot/usr/local/RaspberryQt/bin/qmake
$ make
$ make install
The created libraries must then be copied to the Raspberry Pi using rsync
.
$ rsync -avz /opt/RaspberryQt/sysroot/usr/local/RaspberryQt root@$<IP des Raspberry Pi>:/usr/local
And the additional module is ready for use.
I have created some bash scripts that contain the complete installation procedure (both for the Raspberry Pi and for the host system). You can download both scripts and the sample project can be found in my GitLab repository.
Last updated
Was this helpful?