I love Qt for any project that needs a UI and I love Raspberry Pi’s, so why not use the two together? There are a number of tutorials around showing how to do that but most of them are old and out of date. I’ve written-up the method I have used to do this below to get Qt 5.12.2 running on a Raspberry Pi 3 Model B+ running Raspbian Stretch (November 2018). No doubt you will be using something different, so here’s some good background reading to understand the process and what you may need to do to update the following for your environment.
https://doc.qt.io/qt-5/supported-platforms.html - work out which version of GCC you need
https://wiki.qt.io/Building_Qt_5_from_Git
http://doc.qt.io/qt-5/build-sources.html
https://wiki.qt.io/Building_a_static_Qt_for_Windows_using_MinGW
https://wiki.qt.io/MinGW
https://wiki.qt.io/Mingw-64-bit
http://doc.qt.io/qt-5/windows-requirements.html#gcc-mingw-builds
http://doc.qt.io/qt-5/supported-platforms-and-configurations.html
http://doc.qt.io/qt-5/windows-building.html
https://wiki.qt.io/Building_Qt_Desktop_for_Windows_with_MinGW
I want to run the Qt apps on Pi to write directly to the screen rather than a desktop-style windowed Qt app running under X11. That means cross-compiling to use hardware accelerated OpenGL with eglfs.
I’m assuming that the Pi is up and running with Stretch. In overview the things we need to do from here are to :
- Setup the RPI with all the required libraries and development files and then sync those to the PC.
- Cross-compile the chosen version of Qt on the PC to run on the RPi.
- Set-up Qt on the PC to cross-compile applications for the RPi.
*Simple! OK lets get started.
[The following includes material copied from other recipes on the web, mostly from https://wiki.qt.io/RaspberryPi2EGLFS and https://visualgdb.com/tutorials/raspberry/qt/embedded/. If any of the authors of those object, let me know and I will change it].
First we need to do some work on the RPi to get it ready.
- [on RPi] Make sure that your distribution is up to date:
sudo rpi-update sudo reboot
sudo apt-get update
sudo apt-get upgrade
sudo reboot - [on RPi] Install a bunch of development files (for simplicity we use build-dep, not everything is really needed, but it is easier this way).
Edit sources list in /etc/apt/sources.list with use of your favorite editor (nano / vi) and uncomment the deb-src line:sudo nano /etc/apt/sources.list
Update your system and install required libraries:
sudo apt-get update
sudo apt-get build-dep qt4-x11
sudo apt-get build-dep libqt5gui5
sudo apt-get install libudev-dev libinput-dev libts-dev libxcb-xinerama0-dev libxcb-xinerama0
Now move over to the PC and do the following steps there.
- Download and install a cross compile toolchain appropriate for your level of Raspbian from here : http://gnutoolchains.com/raspberry/. For Raspbian Stretch I used raspberry-gcc6.3.0-r4.exe (534 MB), however this appears to include some older levels of some of the header files, which screws up the build. These can be removed from the search path by renaming the two offending folders:
CD to C:\SysGCC\Raspberry\arm-linux-gnueabihf\include
Rename the “bits” and “sys” folders to something else. I used “bits.old” and “sys.old” respectively. - Download and install a MinGW64 toolchain from here : https://sourceforge.net/projects/mingw-w64/. You’ll need to pick the right level for your version of Qt. For Qt 5.12.2 I used version 7.3.0
- Download and install Python 2.7 for Windows .
- Download and install Perl for Windows.
- Download the latest version of Qt from here : https://www.qt.io/download. You will need the source code, so tick the “Sources” box if using the Qt Online Installer for Windows.
- Before we can build the Qt for Raspberry Pi, we need to resynchronize the sysroot with the toolchain to ensure that the toolchain has all the headers and libraries from your Raspberry Pi. Start the UpdateSysroot.bat file from the c:\SysGCC\Raspberry\TOOLS folder:You need to synchronize at least the /opt folder, as it contains OpenGL headers that are not included in the toolchain. If you have installed additional packages on your Raspberry Pi, resynchronize other suggested directories as well. Do not resynchronize the /etc folder. Otherwise it will overwrite the /etc/ld.so.conf file with a version from the device that contains “include” statements unsupported by the Windows compiler. If you did overwrite it, expand the statements manually or revert to the ld.so.conf file shipped with the original toolchain.
TIP: use <ctrl> <Return> to add a new line to the list of directories to synchronise
TIP2: this process can take a long time, so time to make a cup of tea.
TIP3: this crashed halfway through for me (at the end of the /usr/lib section). So I ran it again without the folders that had already been synced. - Create a folder to contain your Qt build. I used c:/temp/qt-build, referred to as <qt-build> in the following.
- We are going to use a Windows command shell to run the compilations. To do that, it is easiest to use a script to setup the environment.
CD to <qt-build> and create the file qt5vars.cmd, containing the following:@echo off
REM Edit this location to point to the source code of Qt
SET _ROOT=C:\Qt\5.12.2\Src
SET PATH=%_ROOT%\qtbase\bin;%_ROOT%\gnuwin32\bin;%PATH%
REM Uncomment the below line when using a git checkout of the source repository
REM SET PATH=%_ROOT%\qtrepotools\bin;%PATH%
REM Uncomment the below line when building with OpenSSL enabled. If so, make sure the directory points
REM to the correct location (binaries for OpenSSL).
REM SET PATH=C:\OpenSSL-Win32\bin;%PATH%
REM When compiling with ICU, uncomment the lines below and change <icupath> appropriately:
REM Note that -I <icupath>\include and -L <icupath>\lib need to be passed to
REM configure separately (that works for MSVC as well).
REM SET PATH=<icupath>\lib;%PATH%
REM Contrary to earlier recommendations, do NOT set QMAKESPEC.
SET _ROOT=
REM Keeps the command line open when this script is run.
REM cmd /k - Run qt5vars to create a command shell and use that for the following steps.
- Check that Python and Perl are installed on the path correctly.
- Typing “python” should take you into the python shell (ctrl-Z, return to exit). Check that it is V2.7.x.
- Typing “perl -v” should tell you what version of Perl is installed. I’m not sure it matters what level you have. I had v5.22.2.
- Ensure that we are running the correct versions of the MinGW gcc compiler and the Raspberry Pi cross-compiler.
- “where gcc” should return C:\SysGCC\mingw64\bin\gcc.exe
- “where arm-linux-gnueabihf-gcc” should return C:\SysGCC\raspberry\bin\arm-linux-gnueabihf-gcc.exe
- Open the C:\Qt\5.12.2\Src\qtbase\mkspecs\linux-arm-gnueabi-g++\qmake.conf file and replace all occurences of arm-linux-gnueabi- with arm-linux-gnueabihf- [Not sure if this step is still needed]
- The Raspberry Pi 3 qmake.conf file needs to be fixed up. The shipped version uses “=” in the paths to indicate sysroot, but that seems to screw up “configure”. The fix is to change the “=” if there is one at the start of any path to $$[QT_SYSROOT]. In C:\Qt\5.12.2\Src\qtbase\mkspecs\devices\linux-rasp-pi3-g++\gmake.conf, change:
VC_LIBRARY_PATH = /opt/vc/lib
VC_INCLUDE_PATH = =/opt/vc/include
VC_LINK_LINE = -L=${VC_LIBRARY_PATH}
QMAKE_LIBDIR_OPENGL_ES2 = =${VC_LIBRARY_PATH}To:
VC_LIBRARY_PATH = $[QT_SYSROOT]/opt/vc/lib
VC_INCLUDE_PATH = $[QT_SYSROOT]/opt/vc/include
VC_LINK_LINE = -L${VC_LIBRARY_PATH}
QMAKE_LIBDIR_OPENGL_ES2 = ${VC_LIBRARY_PATH} - Now we are ready to build Qt. Due to a bug in the Qmake build script, we will need to build it in 2 steps: first we will build a Qmake for Windows and then we’ll build the actual Qt binaries.
- First to build the Windows tools, make sure that you are in the <qt-build> directory and run the following configuration script from there (all one line) (note the “-opengl es2” option that configures Qt to use the Raspberry Pi framebuffer directly instead of the X11 system):
c:\Qt\5.12.2\Src\configure -platform win32-g++ -xplatform linux-arm-gnueabi-g++ -release -opengl es2 -sysroot C:/SysGCC/Raspberry/arm-linux-gnueabihf/sysroot -prefix /usr/local/qt5 -nomake examples
- This build may fail eventually, but as long as it has got past building qmake.exe we are OK. Check this by making sure that you can run “qtbase\bin\qmake -v”.
- Now we can build the rest of the Qt framework. First of all open the c:\Qt\5.12.2\Src\configure file and insert the condition before the “Creating qmake line” with this one and add a matching fi at the end of the block:
if [ '!' -f "$outpath/bin/qmake.exe" ]; then
- We now need to run the configure script again with a few more parameters. Configure has loads of parameters (try configure -h to see them all) and you may need to try different combinations to get the results you want. To make that easier, you may want to put the command inside a command file (I use “qt5unix.cmd”) to make it easier to tweak. The combination that worked for me is (again, all one line):
c:\Qt\5.12.2\Src\configure -platform win32-g++ -device linux-rasp-pi3-g++ -release -opengl es2 -sysroot C:/SysGCC/Raspberry/arm-linux-gnueabihf/sysroot -prefix /usr/local/qt5 -nomake examples -device-option CROSS_COMPILE=C:/SysGCC/Raspberry/bin/arm-linux-gnueabihf- -qt-xcb -opensource -confirm-license
- The -device-option is required when using the device specification, however if you specify it while building Qmake, the Qt build system will try to use the cross-compiler to build the Windows Qmake executable that will obviously fail.
If you get errors while configuring Qt, please check that:
- Your <toolchain>\sysroot\etc\ld.so.conf file contains the following lines:
12345/opt/vc/lib/lib/arm–linux–gnueabihf/usr/lib/arm–linux–gnueabihf/usr/lib/arm–linux–gnueabihf/libfakeroot/usr/local/lib
- Your toolchain sysroot directory contains the /opt/vc directory
If nothing helps, run the configure script with the -verbose argument and direct its output to a file by appending “>log.txt 2>&1” to the command line. This should provide more information on what exactly is causing the problem.
- Your <toolchain>\sysroot\etc\ld.so.conf file contains the following lines:
- Once the configure script reports that the configuration is complete, run the “mingw32-make && mingw32-make install” command to build the entire Qt framework and install it into the cross-compiler directory. The framework is huge, so the build process might take several hours to complete, even on a fast machine.Warning: do not run “make install” before “make” succeeds as it would fail leaving the build directory in a partially built state failing further builds until the entire directory is deleted and re-created.
- Open SmarTTY (a portable version can be found in <SysGCC>\Raspberry\TOOLS\PortableSmartty) and connect to your Raspberry Pi. Then run the following commands to create the /usr/local/qt5 folder and make it writable to the current user:
123cd /usr/localsudo mkdir qt5sudo chown pi qt5
Then select SCP->Upload directory:
- Select the <sysroot>\usr\local\qt5 directory and upload it to /usr/local/qt5:
- Wait for the upload to complete. The built Qt framework is relatively large and would take several minutes to upload:
- Once the upload is complete, you can test out the framework. Go to the /usr/local/qt5/examples/opengl/qopenglwidget directory and launch ./qopenglwidget:
- To get this working I had to fix-up a few things :
To get fonts working I did:export QT_QPA_FONTDIR=/usr/share/fonts/truetype/dejavu
I also needed to set the following environment variables
export QT_QPA_PLATFORM=eglfs export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/local/qt5/plugins/platforms export LD_LIBRARY_PATH=/usr/local/qt5/lib
- Look at the screen connected to the HDMI port of the Raspberry Pi. You will see a rotating Qt logo animation:If the screen does not show anything, shut down your Raspberry Pi and re-plug the power connector. As long as the screen is connected when the device is powered on, Raspberry Pi should recognize it.