Raspberry Pi Tutorials

Raspberry Pi Tutorials

This is a collection of various tutorials and articles related to the Raspberry Pi platform.

root

Setup a Raspberry Pi for headless use with USB serial console

Setup a Raspberry Pi for headless use with USB serial console root

This tutorial will describe how to configure a serial console over USB on Raspberry Pi Zero, Zero W, A and A+ models (Also Compute Module 3). Note that these are the only models where it is possible to do so as they don't have a USB hub and therefore OTG mode can be used. For serial console on other models you need to use a USB TTL or RS-232 adapter unfortunately.

The Raspberry Pi Zero, Zero W, A and Raspberry Pi A+ are great cheap little devices, but connecting to them without any screen and keyboard can be a bit of a pain. You can always use a TTL RS-232 adapter but using just one simple USB cable is much more easier and convenient. And as the Zero & Zero W comes without any pin headers you have the additional hasle of needing to solder one.

Thankfully it is possible to configure them to use USB gadget mode to provide a serial console over the USB connector (or even a USB ethernet connection if needed).
Unfortunately it won't work as system console as the gadget driver is loaded as a module, but we can use it for serial console.

This tutorial will show how to do that on plain SD card under Linux. You can also modify the SD card image directly in case you need to make the modification for multiple SD cards.

Prepare a Raspbian SD card

First, prepare a SD card of raspbian as your normally would, I will not go into the details here as there are plenty of sources for that. You can use full or lite version depending on your needs, both will work.

Mount the SD card partitions

When done preparing the SD card, remove the card and re-insert so the system will re-read the new partition scheme of the SD card.

Then mount the filesystems, this depend a bit on your environment, on Ubuntu and derivates like Linux Mint the root and boot partitions will be mounted automatically.

If they are not, check in the dmesg the devices nodes that the SD card shows up as.

For example if the card is available as a mmc device nodes the partitions will show up as something looking like this:

mmcblk0: mmc0:59b4 USDU1 15.0 GiB
  mmcblk0: p1 p2

brw-rw---- 1 root disk 179, 0 Nov 16 11:17 /dev/mmcblk0
brw-rw---- 1 root disk 179, 1 Nov 16 11:17 /dev/mmcblk0p1
brw-rw---- 1 root disk 179, 2 Nov 16 11:17 /dev/mmcblk0p2

p1 is the /boot partition. We will use BOOT to point to the mount point of this partition below.
p2 is the / partition. We will use ROOTFS to point to the mount point of this partition below.

If you are using a SD to USB adapter they will most likey show up as /dev/sdb1 and /dev/sdb2 (or sdc, sde, etc. Depending on amount of drives in your system)

Mount these as you normally would in case your system didn't auto mount them. Location is up to you.

Optional, modify Raspbian SD image in place

You can also modify the image directly, before writing it to a SD card. For example if you need this feature on multiple Pies. In this case, we need to configure a loopback device and mount the image partitions.

First, configure a loopback device with losetup for the Raspbian image you are using:

sudo losetup -f --show -P 2017-09-07-raspbian-stretch-lite.img

Note the loopback device node the losetup command will print out, it is usually something close to /dev/loop0. Next, mount the SD image loopback device partitions, /dev/loop0p1 (BOOT) and /dev/loop0p2 (ROOTFS).

Now make the below modifications inside these moutpoints, unmount, detach the image from the loopback device (sudo losetup -d /dev/loop0) and then write the image to your SD card.

Configure Raspbian image

Next we need to adjust the configuration of the image, enable USB OTG driver, enable USB serial gadget driver and last enable a console on the USB serial device so we can login.

USB Driver setting

We need to use the dwc2 USB controller driver, luckily on the Pi Zero dwc2 is the default driver so we don't need to change anything for that. Should be default according to documentation, but it didn't work for me, so:

Enable dwc2 driver in BOOT/config.txt, add the line at the end. At the same time you can enable/disable anything extra you might need like SPI or I2C.

dtoverlay=dwc2

Modify default cmdline.txt to enable serial gadget driver

We need to enable loading of the serial USB gadget driver.

In BOOT/cmdline.txt

Add "modules-load=dwc2,g_serial" to the kernel command line file, cmdline.txt in /boot and remove the "init=/usr/lib/raspi-config/init_resize.sh" part as otherwise the first boot will resize the root partition and the USB drivers won't engage until the next boot and it will first look like the configuration failed. Note the root=PARTUUID=xxxxxxxx-yy part, don't modify that.

The resulting command line in cmdline.txt should look something close to this :

dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=72d5f72a-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait modules-load=dwc2,g_serial

Optionally, if you need networking over USB, use g_cdc instead of g_serial

Enable serial console login on USB gadget serial node

If we where on a live running system it would be a matter of running the systemd command:

sudo systemctl enable getty@ttyGS0.service

But as we are modifying the filesystem on another computer we need to manually enable getty on ttyGS0

Go to (ROOT)/etc/systemd/system/getty.target.wants and create a symlink

ln -s /lib/systemd/system/getty@.service getty@ttyGS0.service

Boot with serial console

We are now done, umount the partitions and insert the SD card into your Raspberry PI and connect a USB cable to the USB port (not the one marked POWER!). Your Pi should now boot and a USB serial device should pop up on the host device after a short while, start your terminal software (minicom, picocom) and point it to the new device node, probably /dev/ttyACM0. Check dmesg.

Press ENTER and you should be presented with a login prompt.

Problems ?

  • Raspbian is quite slow to boot on the Pi Zero, it might take a while before the serial device appers as it will be loaded quite late in the boot stage.
  • Check that you did everything right
  • If possible, connect a monitor and see what happens.
  • If a message, "udc-core: couldn't find an available UDC - added [g_serial] to list of pending drivers." is printed, then you didn't enable the dwc2 driver properly.

 

Build 64-bit kernel for Raspberry Pi, using native tools

Build 64-bit kernel for Raspberry Pi, using native tools root

How to build a custom 64-bit ARM aarch64 kernel for the Raspberry Pi 3, 3+ and 4 boards, on device, using native cross-compilation tools binutils and gcc.

 

Note: For a long time the Raspberry Pi foundation didn't provide 64-bit kernel or userland even if they are advertising the Pi 3 and 4 as 64-bit platforms. This has now changed, as they provide both a 64-bit kernel and userland combination (beta 64-bit Raspberry OS), and also a 64-bit kernel combined with a 32-bit userland option, so you don't need to build a 64-bit kernel yourself anymore unless you really want to.

There are 3 ways to get a 64-bit kernel compiled:

  1. Native build on another 64-bit ARM platform
  2. Cross-compilation on another platform
  3. Cross-compilation on the Pi itself

This tutorial will explain how to do option number 3. (And will actually work just fine for option number 2 as they are pretty much the same).

Note: You will need plenty of space when building as the sources and build results for both the tools and kernel takes quite a lot of space. Also a heat sink is highly recommended if building in parallel.

Time: Speed is relative. The Raspberry Pi is fast or slow, depending on what you compare it to. Even so, it will take a while to build everything, for example C-compiler only gcc will take about 85 minutes to build using non-parallel make on a Pi 3.

Install essential build tools and development packages

As we need to build the tools we need, that is aarch64 binutils and gcc, we need to install the required build tools first. Start by first installing required dependencies for compilation of these tools:

sudo apt-get install build-essential libgmp-dev libmpfr-dev libmpc-dev libisl-dev libncurses5-dev bc git-core bison flex

Build the cross compilation tools

To be able to cross-compile we need to build a couple of tools ourselves as they are not provided. These are aarch64 versions of binutils (assembler, linker) and gcc (C compiler). We will install these tools in their own prefix or path,

/opt/aarch64

We will also use out-of-source build directories to keep the sources clean. This is handy if you need to re-configure, re-build or start over without needing to clean the source tree.

Build and install Binutils

We will start with building the low-level tool, binutils. Binutils is basically an assembler and linker.

Download the latest binutils, (Tested with 2.34 at time of writing, feel free to try any later versions when available)

wget https://ftp.gnu.org/gnu/binutils/binutils-2.34.tar.bz2

Untar the binutils archive

tar xf binutils-2.34.tar.bz2

Configure build and install

mkdir binutils-obj
cd binutils-obj
../binutils-2.34/configure --prefix=/opt/aarch64 --target=aarch64-linux-gnu --disable-nls
make -j4
sudo make install

Binutils is now installed, to be able to use it directly, add "/opt/aarch64/bin/" to your path:

export PATH=$PATH:/opt/aarch64/bin/

Build and install GCC

Next up is gcc, the C compiler. We will build a minimal compiler for C only and no userland support. This is enough to get a aarch64 kernel compiled.

Download latest stable gcc (Tested with 8.4.0 at time of writing, feel free to try any later version when available):

wget https://ftp.gnu.org/gnu/gcc/gcc-8.4.0/gcc-8.4.0.tar.xz

Untar the gcc archive

tar xf gcc-8.4.0.tar.xz

Next configure gcc and build gcc. We will configure the build for only a minimal C compiler, that is enough for building a kernel.

mkdir gcc-out
cd gcc-out
../gcc-8.4.0/configure --prefix=/opt/aarch64 --target=aarch64-linux-gnu --with-newlib --without-headers \
 --disable-nls --disable-shared --disable-threads --disable-libssp --disable-decimal-float \
 --disable-libquadmath --disable-libvtv --disable-libgomp --disable-libatomic \
 --enable-languages=c
make all-gcc -j4
sudo make install-gcc

Test that the cross gcc runs ok, run:

/opt/aarch64/bin/aarch64-linux-gnu-gcc -v

It should report something close to this is everything is ok:

Using built-in specs.
COLLECT_GCC=./aarch64-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/opt/aarch64/libexec/gcc/aarch64-linux-gnu/8.3.0/lto-wrapper
Target: aarch64-linux-gnu
Configured with: ../gcc-8.3.0/configure --prefix=/opt/aarch64 --target=aarch64-linux-gnu --with-newlib 
--without-headers --disable-nls --disable-shared --disable-threads --disable-libssp --disable-decimal-float 
--disable-libquadmath --disable-libvtv --disable-libgomp --disable-libatomic --enable-languages=c --enable-lto
Thread model: single
gcc version 8.3.0 (GCC)

If all is well, then you can continue to building the kernel itself!

Optional: libgcc

The C-only compiler we built above is enough for building a Linux kernel and is enough for this guide. But, if you would like to for example build and use u-boot, then you will need to build libgcc, a static library that contains shared code and various helper functions. Building and installing libgcc is fortunately very easy, just make the libgcc target and install using the following commands after building gcc:

make all-target-libgcc
make install-target-libgcc

Build the Linux kernel

Now you have a toolchain that is able to build 64-bit ARM kernels. So the next step is to download the Raspberry Pi kernel sources, configure them and build a 64-bit kernel and modules.

Download Linux kernel sources

You have a couple of choices depending on what you like to do. If you just wanna get the latest Raspberry Pi kernel release, download a release archive. If you would like to keep up with any changes fast, then clone the repository.

Release archive

The fastest way to get the kernel sources are by downloading a release archive from the Raspberry Pi GitHub repository. Just pick the latest release, 1.20200212-1 at time of writing, and use that.

Extract the archive with

tar xf raspberrypi-kernel_1.20200212-1.tar.gz
From git repository

Get the most up to date stable branch kernel sources (4.19 branch at time of writing) directly from the Raspberry Pi GitHub repository with

git clone --depth=1 -b rpi-4.19.y https://github.com/raspberrypi/linux.git
Keeping sources fresh

The Linux kernel is a moving target and evolves almost daily. To keep updated with latest changes, run the following command in the directory you checked out above:

git pull

Configure Linux kernel for 64-bit Raspberry Pi

We use output directory for kernel build so we can use the same source tree for other configuration (32-bit for example)

mkdir kernel-out
cd linux
For Raspberry Pi 3, use bcmrpi3_defconfig
make O=../kernel-out/ ARCH=arm64 CROSS_COMPILE=/opt/aarch64/bin/aarch64-linux-gnu- bcmrpi3_defconfig
For Raspberry Pi 4, use bcm2711_defconfig
make O=../kernel-out/ ARCH=arm64 CROSS_COMPILE=/opt/aarch64/bin/aarch64-linux-gnu- bcm2711_defconfig

The kernel build is now configured with a default configuration for a 64-bit Raspberry Pi kernel.

In case you need to customize the configuration (Add support for some specific hardware, trim out things you don't need or otherwise mess around with the configuration) run

make O=../kernel-out/ ARCH=arm64 CROSS_COMPILE=/opt/aarch64/bin/aarch64-linux-gnu- menuconfig

and adjust the configuration for your needs.

Build the kernel and modules

Next build the kernel and modules with:

make -j4 O=../kernel-out/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-

If all goes well, as it should, you should now have a 64-bit kernel, modules and device tree built.

Keep up with kernel development

The Linux kernel evolves and so does the Raspberry Pi kernel too. If you used the repositroy clone then to keep up with development changes you can pull changes with git to download changes to your kernel source tree. To do that run the following command in the kernel source locations:

git pull

This will download any changes made to the kernel source.

Update kernel configuration

After pulling in changes I personally like to always run, just in case:

make -j4 O=../kernel-out/ ARCH=arm64 CROSS_COMPILE=/opt/aarch64/bin/aarch64-linux-gnu- oldconfig

Booting 64-bit kernel on Raspberry Pi 3

Booting 64-bit kernel on Raspberry Pi 3 root

So now you should have a shiny 64-bit kernel if you followed the 64-bit kernel build tutorial, and if not, do it first.

Now that you have the kernel and modules built, the next step is to install configure your Raspberry Pi 3 to boot it. All commands must be run as root, so either login as root or prefix commands with sudo.

Kernel, device overlays and kernel modules

Install kernel, DTBs, device overlays and kernel modules

First, install the kernel modules and DTBs

make O=../kernel-out/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- modules_install dtbs_install

Then copy the kernel image to /boot

cp ../kernel-out/arch/arm64/boot/Image /boot/kernel8.img

Setup kernel image and DTB in config.txt

Edit /boot/config.txt and add/modify the the following configuration options. The paths are kernel version specific so adjust as needed. Also point the device_tree to the correct model, bcm2710-rpi-3-b.dtb or bcm2710-rpi-3-b-plus.dtb:

device_tree=dtbs/4.14.33-v8+/broadcom/bcm2710-rpi-3-b.dtb
overlay_prefix=dtbs/4.14.33-v8+/overlays/
kernel=kernel8.img

Reboot your device

Reboot your Pi. If all goes well and you did the above steps correctly you should now be running a 64-bit kernel on your Pi 3.

To confirm that you are on a 64-bit kernel, you can check with arch or uname, they should respond with aarch64, like this:

pi@raspberrypi:~ $ arch
aarch64

Or uname -a

pi@raspberrypi:~ $ uname -a
Linux raspberrypi 4.9.51-v8+ #1 SMP PREEMPT Mon Oct 2 15:25:25 UTC 2017 aarch64 GNU/Linux

Going back to a 32-bit kernel

If you would like to go back to using a default 32-bit kernel, just remove or comment out (with #) the lines added to config.txt, like so:

#device_tree=dtbs/4.14.33-v8+/broadcom/bcm2710-rpi-3-b.dtb
#overlay_prefix=dtbs/4.14.33-v8+/overlays/
#kernel=kernel8.img

And either set

kernel=kernel7.img

or rename/remove the kernel8.img to something else, as otherwise it will still be used as default. Then reboot your Pi and you should be running the stock 32-bit kernel again.

Problems and issues with 64-bit

The 64-bit Raspberry Pi kernel is not yet complete. There are still some issues with device support.

Silence kernel warnings about deprecated instructions

(This seems to have been fixed in 4.14!)

The 64-bit ARM ABI deprecates some instructions that are still used in the 32-bit userland binaries. The kernel log will be flooded with messages about this, to silence them run:

echo 2 >/proc/sys/abi/setend
echo 2 >/proc/sys/abi/cp15_barrier

These settings can be put in /etc/sysctl.conf like so:

abi.cp15_barrier = 2
abi.setend = 2

Unfortunately there seems to be race condition or timing issue in the kernel with disabling emulation and enabling instructon support as booting will stall so right now this is not a good option.

Setup PHP 8 with Apache on a Raspberry Pi

Setup PHP 8 with Apache on a Raspberry Pi root

How to install and configure PHP 8.2 or later/earlier with Apache on Raspberry Pi running Raspberry Pi OS (Buster, Bullseye or Bookworm).

PHP 8.1.2 phpinfo()

Raspberry Pi OS release track stable Debian release, the current being Bookworm, previous version Bullseye.

Note: Debian 12 Bookworm now comes with PHP 8.2 and if you are happy with the version that Debian provides, you can skip pretty much everything here and just install the require packages listed below (TL;DR apt install php-fpm). On the other hand, you you would like to keep more updated that what the default distribution packages offer, then please read along!

PHP is included in Bullseye, but unfortunately it is from the PHP 7 series that is no longer supported upstream and therefore not recommended to be used anymore. Upstream PHP support is time limited, PHP 7 is no longer supported and you should use 8.1, 8.2 or 8.3. As there can be major or minor incompatibilities you might need to run a specific version depending on the PHP based application that you are using. For example, if you are running Drupal 9 or 10 site the supported version is 8.0/8.1 and recommended version is 8.2

Supported PHP versions
BranchInitial ReleaseActive Support UntilSecurity Support Until
7.428 Nov 201928 Nov 202128 Nov 2022
8.026 Nov 202026 Nov 202226 Nov 2023
8.125 Nov 202125 Nov 202325 Nov 2024
8.28 Dec 20228 Dec 20248 Dec 2025
8.323 Nov 202323 Nov 202523 Nov 2026
  • Debian Buster comes with version 7.2.9 that is already EOL:ed upstream and 7.3 is now unsupported too.
  • Debian Bullseye comes with version 7.4.30 that is EOL
  • Debian Bullseye does NOT come with PHP 8
  • Debian Bookworm comes with 8.2

Note: The packages from the repository we will use are unfortunately not compatible with the ARMv6 (armhf) based Raspberry Pis, you need to be using a ARMv7 or ARMv8 based Raspberry Pi 2, 3 or 4.

This tutorial will show installation instructions for PHP 8.1 but in case you need to use something else like 8.2 or still 7.4, just adjust the versions in the packages and commands. And there is also the issues of the recommended way to run PHP these days. It is not as a Apache module, libapache2-mod-php, anymore!

What we need to do is:

  1. Add apt source repository for up to date PHP packages
  2. Install Apache with required modules
  3. Install PHP 8.1 with optional extras. In this guide we will start with installation of version 8.1
  4. Optional: Parallel install other PHP versions

Add the PHP repository

So how to get a fresh version of PHP then ? Luckily the Debian PHP maintainer hosts a repository with fresh version of PHP and it includes armhf (Note: armv7 or above only!) versions too. Lets start by adding the repository PGP key:

 wget -q https://packages.sury.org/php/apt.gpg -O- | sudo tee /etc/apt/trusted.gpg.d/php.gpg

And add the PHP repository to your apt sources (adjust for the Raspberry OS version you are running, stretch/buster or bullseye)

 echo "deb https://packages.sury.org/php/ bullseye main" | sudo tee /etc/apt/sources.list.d/php.list

Update repository pacakge index

 sudo apt update

In case apt complains about "The method driver /usr/lib/apt/methods/https could not be found", install the following optional packages:

 sudo apt install ca-certificates apt-transport-https

Install Apache and FastCGI module

Next we will install Apache and the required extra module for FastCGI support:

 sudo apt install apache2 libapache2-mod-fcgid

Verify that apache work by going to http://YOUR-RPI-IP with your browser. If all is well and you get a response, continue with installation of PHP.

Install PHP 8.1 and common modules

Next we will install PHP 8.1 with some common modules, but not the Apache module version! Instead we will use php-fpm, the FastCGI version.

If you need some other version, just adjust the version in the package names and commands. Later we will show how you can have multiple PHP version running in parallel.

 sudo apt install php8.1-cli php8.1-fpm \
 php8.1-opcache php8.1-curl php8.1-mbstring \
 php8.1-pgsql php8.1-zip php8.1-xml php8.1-gd

The above list is some of the most common PHP modules that you might need, for example for running Drupal. If you need something else, just use: apt search php8 to find them.

Enable apache fpm proxy module and enable php-fpm configuration with (make sure you installed both apache2 and libapache2-mod-fcgid first!)

 sudo a2enmod proxy_fcgi
 sudo a2enconf php8.1-fpm

And reload Apache

 sudo systemctl reload apache2

Test the installation

Test PHP cli

php8.1 -v

It should response with something close to:

PHP 8.1.12 (cli) (built: Oct 28 2022 18:35:51) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.12, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.12, Copyright (c), by Zend Technologies

Test serving a PHP page

Create a "test.php" file in /var/www/html with your favorite editor, use the contents:

 <?php phpinfo(); ?>

And the point your browser to http://YOUR-RPI-IP/test.php

Your browser should now show the PHP information page with all kinds of details.

Configure PHP & PHP-FPM

The default FPM configuration are quite suitable for a small to medium site and the power of a Pi. But in case you need to adjust them see the php-fpm configuration file:

/etc/php/8.1/fpm/php-fpm.conf

And for PHP specific configuration see:

/etc/php/8.1/fpm/php.ini

Parallel install other PHP versions

With php-fpm it is possible to have multiple version of PHP installed and served by Apache. You have one version configured as the default and then Virtual hosts can run some other version.

This might be needed in case your PHP based software required some specific version or is not yet compatible with the latest version. The following example will show how to run multiple versions at the same time.

Install other PHP versions

Installing other versions of php-fpm is straightforward, just install the phpVersion-fpm packages you need. For example, to run both 8.1 and 7.4, install both fpm packages with:

sudo apt-get install php7.4-fpm php8.1-fpm

Example parallel configuration

We will create two virtual hosts, running on custom ports. Edit Apache configuration file /etc/apache2/ports.conf and add the following lines after "Listen 80":

Listen 8080
Listen 8081

Then edit the default VirtualHost configuration in /etc/apache2/sites-available/000-default.conf and add two more VirtualHost settings:

<VirtualHost *:8080>
    <FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost"
    </FilesMatch>
</VirtualHost>

<VirtualHost *:8081>
    <FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost"
    </FilesMatch>
</VirtualHost>

Then restart apache. Now when visiting the test page with http://YOUR-RPI-IP:8080/test.php or http://YOUR-RPI-IP:8081/test.php will give you different PHP versions. You can of course run them on different IP addresses or paths instead of ports.

Enjoy PHP 8 on your Pi!

Building Qt 5.12 LTS for Raspberry Pi on Raspberry Pi OS

Building Qt 5.12 LTS for Raspberry Pi on Raspberry Pi OS root

Raspberry Pi OS (aka Raspbian), based on Debian Buster, comes with an old version of Qt 5.11 that is already outdated. Afaik there are no up-to-date backports so the only way to get an up to date version of Qt with board specific features enabled for running on your Raspberry Pi is to build it yourself.

Even if this tutorial concentrates on the Qt 5.12.10 LTS, the Long Time Support release, the guide is tested to work on 5.14 and 5.15 too.

Note: A Qt 5.15.7 specific tutorial is available here and is highly recommended using Qt 5.15 if you still need to use Qt 5. A tutorial for Qt 6.2 LTS on Buster & Bullseye is also available.

These instructions will build version of Qt that uses the eglfs interface by default and therefore runs applications fullscreen. You can optionally add X11 and/or Wayland support by installing the required development packages, they are described in the Optional features table below.

Building Qt on the Raspberry Pi is pretty straightforward, there is one Pi specific configuration that needs to be made. In short it consist of the following steps:

  1. Downloading sources of Qt
  2. Checking the Qt source package integrity
  3. Preparing the sources for building
  4. Setup Qt mkspecs configuration for Raspberry Pi
  5. Installing required dependencies
  6. Installing optional dependencies
  7. Fix for EGL library detection (Not needed for Pi 4)
  8. Configuring the Qt build
  9. Compiling Qt
  10. Installing the Qt build

This tutorial is written for the full source of version 5.12.10, it is fully possible to build only parts using the split up Qt submodule sources packages, but this tutorial will not go into that at this time. Anyway, it is also very easy to skip building of modules that you don't need.

Tutorial changelog

As this tutorial evolves over time, changes are logged here.

  • 10.12.2018 - Initial (beta) version for Qt 5.12 published
  • 29.01.2019 - Removed old fake cross compiled way. Added example Pi model specific CFLAGS & CXXFLAGS. Fixed download link URL.
  • 22.02.2019 - Reference to update version 5.12.1.
  • 23.04.2019 - Reference to update version 5.12.3.
  • 26.04.2019 - Use Qt mkspecs for configuration as configure overrides, even if it should work, does not work as documented
  • 25.09.2019 - Reference to update version 5.12.5
  • 06.02.2020 - Reference to update version 5.12.7
  • 11.02.2020 - Fix wrong version leftovers, add Pi 4 platform option.
  • 25.05.2020 - Reference to update version 5.12.8, use apt, add section about building webengine
  • 01.03.2021 - Reference to update version 5.12.10, use /opt/Qt/5.12.10 prefix
  • 06.03.2021 - Add missing required XCB/X11 packages

Storage space and memory requirements

Make sure you have enough disk space free on your on your Pi as building Qt requires a lot of disk space. The unpacked full Qt sources itself takes around 2.8GB, the build result around 625MB and the installation 155MB. A minimum of 8GB SD card is highly recommended. USB3 attached HDD or SDD is highly recommended on Pi 4 as it speeds up compiling. Running out of disk space after hours of compiling can be extremely annoying, trust me.

Qt build storage space requirements
Item Size Note
Qt source archive 486MB qt-everywhere-src-5.12.10.tar.xz
Unpacked Qt Sources 2.8GB qt-everywhere-src-5.12.10
Build result 745MB Depends on configuration options and enabled features
Install size 155MB - 300MB Depends on configuration options and enabled features

Enable swap and adjust CPU/GPU memory split

Compiling Qt takes quite a lot of memory, especially if trying to do a parallel build. Some parts take even too much memory and we need to disable building of them. It is highly recommened to enable at least 200MB of swap and also consider adjusting the Raspberry Pi CPU/GPU memory-split for the time of compilation, especially if parallel building or if you are using a model with limited amount of memory. On the new Raspberry Pi 4 models with 2GB or 4GB of memory, swap is not required. USB3 attached HDD or SSD is also highly recommended.

Build Qt for Raspberry Pi

Download the Qt 5.12.10 source archive

Download the single source tar file from download.qt.io, version 5.12.10. The package is relatively large, 486MB, so depending on your bandwidth it might take some time to download, grab a coffe or continue with the dependecies while the Qt source archive is downloading.

wget http://download.qt.io/official_releases/qt/5.12/5.12.10/single/qt-everywhere-src-5.12.10.tar.xz

Check archive MD5 hash

Just to make sure the download was succesfull and is what it should be, check the MD5 hash of the archive with:

md5sum qt-everywhere-src-5.12.10.tar.xz

It should be:

a781a0e247400e764c0730b8fb54226f   qt-everywhere-src-5.12.10.tar.xz

Un-tar the source archive

Un-tar the source archive in a suitable location, with enough free space (~2.8GB). This will take around 7-13 minutes on a Raspberry Pi 3+, depending on SD card speed, and even more on an older model, so go grab of coffe again. If you are on a Pi 4, then we highly recommend using fast USB 3 storage (HDD or SSD) for both sources and building. You can of course start installation of the build dependecies while you wait.

tar xf qt-everywhere-src-5.12.10.tar.xz

Setup Qt mkspecs configuration files

Qt build is configured trough the configure script, but platform and device specifc settings are set in mkspecs configuration files. Qt includes mkspecs for the Raspberry Pi but they are unfortunately setup for cross-compilation environments only and can not be used for native building without editing or the need for faking a cross compilation environment and that has its own issues.

Fortunately suitable mkspecs files for the various Pi versions are available in our github, so the next step is to clone that repository and install the mkspecs files into the Qt source tree so that they can be used.

Clone the configuration repository:

git clone https://github.com/oniongarlic/qt-raspberrypi-configuration.git

change into the cloned repository and run (adjust DESTDIR in case your Qt sources are extracted somewhere else):

cd qt-raspberrypi-configuration && make install DESTDIR=../qt-everywhere-src-5.12.10

Install required build dependencies

You will need to install plenty of packages to be able to build Qt 5. Some of the Qt 5 are optional and can be either left our or included, depending on your particular needs. For example support for various databases (PostgreSQL, MySQL/MariaDB) and if you don't need a specific feature you can skip building the support (or build the from separate packages later). Or the other way around, if you need a specific feature you might need to install more packages.

Some features are not strictly required but might still be nice to have, for example support for the webp image format is optional, but these days it is already widely used so might be good to include.

See the table below for a list of some optional features and the required development packages you need to install. But first, start by updating your apt package cache so everything is fresh:

apt update

Then continue with required package installation below.

Install the bare minimum required development packages for building Qt 5 with apt:

apt install build-essential libfontconfig1-dev libdbus-1-dev libfreetype6-dev libicu-dev libinput-dev libxkbcommon-dev libsqlite3-dev libssl-dev libpng-dev libjpeg-dev libglib2.0-dev libraspberrypi-dev

Install optional Qt 5 feature development packages

Qt consist of many modules, depending on your needs you might like to install additional development packages to be able to enable support for these features in Qt 5. Check the table below for any optional features you might need and the required development packages that you need to install to support them. Also make sure that the optional feature you need is found and enabled by the configure script by checking the output of configure run (see config.summary).

Optional features
Optional feature Packages to install Configure option
Bluetooth

bluez libbluetooth-dev

 
gstreamer multimedia framework support

libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-plugins-bad libgstreamer-plugins-bad1.0-dev gstreamer1.0-pulseaudio gstreamer1.0-tools gstreamer1.0-alsa

 
Linux ALSA Audio support

libasound2-dev

 
Pulseaudio support

pulseaudio libpulse-dev

 
Support for various databases (PostgreSQL, MariaDB/MySQL)

libpq-dev libmariadbclient-dev

 

Printing support using CUPS

libcups2-dev

 
Wayland support

libwayland-dev

 
X11 support

libx11-dev libxcb1-dev  libxext-dev libxi-dev libxcomposite-dev libxcursor-dev libxtst-dev libxrandr-dev libfontconfig1-dev libfreetype6-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-util0-dev  libxcb-xinerama0-dev  libxcb-xkb-dev libxkbcommon-dev libxkbcommon-x11-dev

 
WebEngine

Required: flex bison gperf libre2-dev libnss3-dev libdrm-dev

Optional: libxml2-dev libxslt1-dev libminizip-dev libjsoncpp-dev liblcms2-dev libevent-dev libprotobuf-dev protobuf-compiler

Optional but unusable versions in raspbian: libopus-dev libvpx-dev

 
Accessibility

libatspi-dev

 
SCTP [1][2]

libsctp-dev

-sctp

Use VC4 driver instead of Broadcom EGL binary-blobs.

Mandatory on Raspberry Pi 4.

libgles2-mesa-dev libgbm-dev Use -platform linux-rpi-vc4-g++

Install any package from the above table with apt install.

Broadcom EGL library filename fix

Note: This is NOT needed when building a Raspberry Pi 4 configuration.

On Raspbian Stretch/Buster the OpenGL library files have been renamed (1, 2)so that they wouldn't conflict with Mesa installed ones. Unfortunately Qt configure script is still looking for the old names. See QTBUG-62216 for details.

If you use the mkspecs configuration files provided in this tutorial you don't need to worry about this as they are setup to reference the libbrcm*.so library names.

Create a shadow build directory outside of the Qt source tree

We will build Qt 5 outside of the source tree, this way you can easily have different build version and easily also start over in case of any issues with configuration or the build itself. Your build location can be anywhere where there is enough space, for example an HDD, SDD or USB stick in case you are running out of spaec on your SD card. Remember to adjust any paths in the example commands.

mkdir build
cd build

Configure the Qt build environment

We configure Qt 5 for a native build and set device specific settings, like libraries, default QPA plugin to use, etc directly on the configure command line. Note that the below configuration is just an example, you might need to adjust it for your particular needs, for example if you do need wayland the remove the "-skip wayland" option. This makes it also easy to optimize for any specific Raspberry Pi board type, see the table for used CFLAGS & CXXFLAGS for your target board. Configure run takes ~10 minutes as it will first compile the Qt build tool qmake and then run various tests and feature checks.

PKG_CONFIG_LIBDIR=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/share/pkgconfig \
../qt-everywhere-src-5.12.10/configure -platform linux-rpi-g++ \
-v \
-opengl es2 -eglfs \
-no-gtk \
-opensource -confirm-license -release \
-reduce-exports \
-force-pkg-config \
-nomake examples -no-compile-examples \
-skip qtwayland \
-skip qtwebengine \
-no-feature-geoservices_mapboxgl \
-qt-pcre \
-no-pch \
-ssl \
-evdev \
-system-freetype \
-fontconfig \
-glib \
-prefix /opt/Qt/5.12.10 \
-qpa eglfs

Building QtWebEngine support

Building the qtwebengine module takes a lot of time and space, the default configure example above disables it with -skip qtwebengine. The reason being that on older Pi versions with a tiny amount of memory it is pretty much impossible to build. Now with the 4GB or 8GB Raspberry Pi 4 it is fully possible to build, but you might still need to enable swap and also limit the amount of parallel builds the ninja build tool (that qtwebengine uses internally for building) is allowed to use. You can either build qtwebengine at the same time as the rest of Qt, but in case it fails (and it probably will) your whole build has failed, so the recommended way is to first build the base Qt 5 separately, install it and then build qtwebengine separately. But if you so choose, you can enable building of qtwebengine by removing the -skip qtwebengine configure option. Make sure that when you invoke make for building, that you add NINJAJOBS=-j1 to the command line. (make -j4 NINJAJOBS=-j1)

Building QtWebEngine separately

Read the separate guide on how to build qtwebengine.

Raspberry Pi platform options

Select platform according to the Pi model you are going to run Qt on. You can build on a fast Pi 4/3+ and the move the files over to a slower version if needed, just make sure you build for the correct ARM architecture in that case.

Note: For a Qt 5 that will be run on a Raspberry Pi 4 you must use KMS, Broadcom EGL is not supported on that model and never will. Make sure you have installed the packages: libgles2-mesa-dev libgbm-dev

Model specific optimization
Raspberry Pi model ARM architecture version Platform option Compiler FLAGS that will be used
Raspberry Pi 4 ARMv8 -platform linux-rpi4-v3d-g++
-march=armv8-a -mtune=cortex-a72 -mfpu=crypto-neon-fp-armv8

Note: Will use VC4 DRM Mesa GL driver, not Broadcom EGL as it is not supported on the Pi 4.

Note: You must install libgles2-mesa-dev libgbm-dev

Raspberry Pi 3, models:
3+, A+, Compute Module 3, Compute Module 3+

Raspberry Pi 2, model:
B v1.2

ARMv8
-platform linux-rpi3-g++
 
-march=armv8-a -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8

Note: QtScript won't build with these flags. If you need QtScript, then build with ARMv7 options.
And remove -skip qtscript from configure options.

Note: If you will build Qt Creator you will need QtScript!

Raspberry Pi 2, model:
B
ARMv7
-platform linux-rpi2-g++
 
-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4
Raspberry Pi 1, models:
Original, Zero, Zero W, A, A+, B+, Compute Module 1
ARMv6
-platform linux-rpi-g++
 
-march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp
       

Check the configure result

When the Qt configuration scripts has finnished succesfully it will print out a configuration summary and store the result in the config.summary file, also all the raw checks will be in the config.log file. Check that all options and features you needed are found and enabled in the summary output. If not, check the config.log file for a reason.

Broadcom EGLFS

Make sure that the configure script detects Raspberry Pi EGLFS when building for Raspberry Pi 1,2 or 3. Look for the following output or check the log file config.summary:

  EGLFS .................................. yes
  EGLFS details:
...
    EGLFS Rasberry Pi .................... yes

Note: If it says "no", check the configuration run output for reasons. Make sure that you have all required build dependencies installed and fixed the EGLFS library references!

MesaGL

When building for Raspberry Pi 4, check for

  EGLFS .................................. yes
  EGLFS details:
...
    EGLFS EGLDevice ...................... yes
...
    EGLFS Raspberry Pi ................... no

 

Compile Qt

Now Qt should be configured properly with all features enabled that we need. If you need some of the optional features, make sure to check the configure result that they where properly detected.

To compile Qt run:

make

or if you are using any of the quad-core Pis, append the -j4 parameter to build in parallel. Make sure you have proper cooling in this case, the 3+ this should run fine without getting throttled too much.

Build time

The compilation time depends on the Qt features being built, speed of your SD card, etc. Build time on a Raspberry Pi 3 with two parallel jobs (make -j2) takes roughly 8 hours.

Note: It might happen that parallel build needs too much memory and the compiler will crash. In this case try run with just one process or try -j3 or just -j2. Enabling swap will also help.

Optional: Speed up building with distcc

If you have many Raspberry Pi you can speed up the compilation by using distcc. In that case setup distcc on your machines and invoke make with:

make CC=distcc CXX=distcc -j[Machines in distcc cluster]

Install the build

The compilation should finnish without any errors, if it does not, double check that you have all the dependecies installed and run configure correctly.

If all is well, install Qt by running

make install

You should now have Qt 5.12.10 installed in /opt/Qt/5.12.10 ready for use. To configure your Qt project(s) to build with this version run qmake from the installation directory:

/opt/Qt/5.12.10/bin/qmake

You can of course also add it to your PATH, edit your users ".profile" or system wide in "/etc/profile" .

Choosing platform

As explained in the introduction, this build will default to using the eglfs platform, meaning that no windowing environment is required to run GUI applications. You can choose the platform binaries will run against by suppling the "-platform" paramter when running them.

Qt Platform option examples
Platform Parameter
X11 -platform xcb
VNC -platform vnc
WebGL -platform webgl

Enjoy Qt 5.12 on your Pi, Happy coding!

 

Building Qt 5.15 LTS for Raspberry Pi on Raspberry Pi OS

Building Qt 5.15 LTS for Raspberry Pi on Raspberry Pi OS root

This tutorial provides you a step-by-step guide on how to build an up-to-date Qt 5.15 LTS release from source with proper hardware acceleration support for Raspberry Pi on Raspberry Pi OS, both 32-bit and 64-bit, Buster and Bullseye. Qt is a popular cross-platform application framework that enables developers to create user interfaces and applications that can run on various platforms, including the Raspberry Pi.

Current for version 5.15.12, released 20.12.2023.

Raspberry Pi closeup

Raspberry Pi OS (aka Raspbian), based on Debian Buster, comes with a very old version of Qt 5.11 that is already outdated. Afaik there are no up-to-date backports so the only way to get an up to date version of Qt with board specific features enabled for running on your Raspberry Pi is to build it yourself.

Note: These instructions are mostly written for the older Debian Buster based Raspberry Pi OS version. The Bullseye release of Raspberry Pi OS comes with Qt 5.15 in the repositories and will work fine under X11 but does not support running without it like for example plain eglfs. In case you would like to use plain eglfs you might still like to build your own customized version of Qt 5.15.

This tutorial concentrates on the Qt 5.15 LTS, the Long Time Support releases of 5.15, the last in the Qt 5 series. Unfortunately latest releases of Qt 5.15 are not available as Open Source immediately anymore but with a 1 year delay from commercial release. The latest open source release at this time is 5.15.12, released in 20.12.2023. KDE provides patches for the Qt 5.15 branch.

Note: Qt 5.15, and therefore Qt 5 branch, is going to be End-of-Life pretty soon, you should consider using Qt 6, especially for any new projects, there is a tutorial available for just that.

These instructions will build version of Qt that uses the eglfs interface by default and therefore runs applications fullscreen. You can optionally add X11 and/or Wayland support by installing the required development packages, they are described in the Optional features table below.

You can also choose what graphics drivers you will be using for eglfs, depending on what version of the Raspberry Pi you are using, either the proprietary Broadcom EGL or open source Mesa.

Building Qt for and on the Raspberry Pi is pretty straightforward, there are some Pi specific configurations that needs to be made, but in short it consist of the following steps:

  1. Downloading sources of Qt
  2. Checking the Qt source package integrity
  3. Preparing the sources for building
  4. Setup Qt mkspecs configuration for Raspberry Pi
  5. Installing required dependencies
  6. Installing optional dependencies
  7. Fix for EGL library detection (Not needed for Pi 4)
  8. Configuring the Qt build
  9. Compiling Qt
  10. Installing the Qt build

This tutorial is written for the full source of version 5.15.12, it is fully possible to build only parts using the split up Qt sub-module source packages, but this tutorial will not go into that at this time. Anyway, it is also very easy to skip building of modules that you don't need with the no-make options.

Note: These example builds have been verified to work on both 32-bit and 64-bit Raspberry Pi OS. Just make sure you choose the correct platform!

Tutorial changelog

As this tutorial evolves over time, changes are logged here.

  • 04.04.2021 - 5.15.2 Specific guide, copied from latest 5.12.10 version
  • 28.04.2021 - VC4 needs libdrm-drm, separete table for graphics options, preliminary 64-bit build option
  • 07.05.2022 - Add mention of using no-feature-eglfs_brcm when building under 64-bit Bullseye
  • 11.05.2022 - Bump version to 5.15.3
  • 15.05.2022 - Bump version to 5.15.4
  • 16.05.2022 - Looks like they renamed the source archive name, fixed download & tar examples.
  • 28.06.2022 - Bump version to 5.15.5
  • 26.10.2022 - Bump version to 5.15.6
  • 05.11.2022 - Bump version to 5.15.7
  • 07.01.2023 - Bump version to 5.15.8
  • 02.05.2023 - Bump version to 5.15.9
  • 03.08.2023 - Bump version to 5.15.10
  • 17.10.2023 - Bump version to 5.15.11
  • 31.12.2023 - Bump version to 5.15.12

Storage space and memory requirements

Make sure you have enough disk space free on your on your Pi as building Qt requires a lot of storage space. The unpacked full Qt sources itself takes around 3.7GB, the build result around 830MB and the installation from 232MB or more. A minimum of 8GB SD card is highly recommended. USB3 attached HDD or SDD is highly recommended on the Pi 4 as it speeds up compiling. Running out of disk space after hours of compiling can be extremely annoying, trust me.

Qt build storage space requirements
Item Size Note
Qt source archive 630MB qt-everywhere-opensource-src-5.15.12.tar.xz
Unpacked Qt Sources 3.9GB qt-everywhere-src-5.15.12
Build result ~959MB Typical, depends on configuration options and enabled features
Install size ~250MB Typical, depends on configuration options and enabled features

Enable swap and adjust CPU/GPU memory split

Compiling Qt takes quite a lot of memory, especially if trying to do a parallel build. Some parts take even too much memory and we need to disable building of them. It is highly recommended to enable at least 200MB of swap and also consider adjusting the Raspberry Pi CPU/GPU memory-split for the time of compilation, especially if parallel building or if you are using a model with limited amount of memory. On the new Raspberry Pi 4 models with 2GB,  4GB or 8GB of memory, swap is not required. If using swap, a USB3 attached HDD or SSD is also highly recommended as the swap device.

Build Qt for Raspberry Pi

Download the Qt 5.15.12 source archive

Download the single source tar file from download.qt.io, version 5.15.12, the package is relatively large, 630MB, so depending on your bandwidth it might take some time to download, grab a coffee or continue with the dependencies while the Qt source archive is downloading.

wget https://download.qt.io/official_releases/qt/5.15/5.15.12/single/qt-everywhere-opensource-src-5.15.12.tar.xz

Check archive MD5 hash

Just to make sure the download was successful and is what it should be, check the MD5 hash of the archive against the one in the official file with:

md5sum qt-everywhere-opensource-src-5.15.12.tar.xz

Un-tar the source archive

Un-tar the source archive in a suitable location, with enough free space (~4GB). This will take around 7-13 minutes on a Raspberry Pi 3+, depending on SD card speed, and even more on an older model, so go grab of coffee again. If you are on a Pi 4, then we highly recommend using fast USB 3 storage (HDD or SSD) for both sources and building. You can of course start installation of the build dependencies while you wait.

tar xf qt-everywhere-opensource-src-5.15.12.tar.xz

Setup Qt mkspecs configuration files

Qt build is configured trough the configure script, but platform and device specific settings are set in Qt specific mkspecs configuration files. Qt includes mkspecs for the Raspberry Pi but they are unfortunately setup for cross-compilation environments only and can not be used directly for native building without editing or the need for faking a cross compilation environment and that has its own issues.

Fortunately suitable mkspecs files for the various Pi versions are available in our Qt raspberrypi-configuration github repository, so the next step is to clone that repository and install the mkspecs files into the Qt source tree so that they can be used for the build.

Clone the configuration repository:

git clone https://github.com/oniongarlic/qt-raspberrypi-configuration.git

change into the cloned repository and run (adjust DESTDIR in case your Qt sources are extracted somewhere else), make sure QTVERSION match like in the example as the repository might not default to the latest version:

cd qt-raspberrypi-configuration && make install DESTDIR=../qt-everywhere-src-5.15.12 QTVERSION=5.15.12

Install required build dependencies

You will need to install plenty of packages to be able to build Qt 5.15. Some of the Qt 5.15 features are optional and can be either left our or included, depending on your particular needs. For example support for various databases (PostgreSQL, MySQL/MariaDB) and if you don't need a specific feature you can skip building the support (or build the from separate packages later). Or the other way around, if you need a specific feature you might need to install more development packages.

Some features are not strictly required but might still be nice to have, for example support for the webp image format is optional, but these days it is already widely used so might be good to include.

See the table below for a list of some optional features and the required development packages you need to install. But first, start by updating your apt package cache so everything is fresh:

apt update

Then continue with required package installation below.

Install the bare minimum required development packages for building Qt 5.15 with apt:

apt install build-essential libfontconfig1-dev libdbus-1-dev libfreetype6-dev libicu-dev libinput-dev libxkbcommon-dev libsqlite3-dev libssl-dev libpng-dev libjpeg-dev libglib2.0-dev

Graphics driver options

It is possible to use either the proprietary EGL blobs from Broadcom or the Mesa open source drivers. Broadcom drivers can be used on all older Pi variants, but not on any Pi 4 variants (Pi4, 400, Compute Module 4). For those you need to use Mesa.

Graphics driver options
Graphics driver Required package(s) Information

Broadcom EGL

For vintage Pi, Zero, Pi 2, Pi 3, CM 1, CM3

32-bit only

libraspberrypi-dev

Required for all pre-Pi 4 boards if not using open source GL drivers.

EGLFS Rasberry Pi .................... yes
 

VC4 driver

Mandatory on Raspberry Pi 4

Mandatory on 64-bit

libgles2-mesa-dev libgbm-dev libdrm-dev

Use -platform linux-rpi-vc4-g++

Under 64-bit Bullseye, make sure to use/add the option:
-no-feature-eglfs_brcm

to disable any usage of the old brcm libraries.

Note: If you build with gstreamer support you must also install libwayland-dev

Install optional Qt 5 feature development packages

Qt consist of many modules, depending on your needs you might like to install additional development packages to be able to enable support for these features in Qt 5. Check the table below for any optional features you might need and the required development packages that you need to install to support them. Also make sure that the optional feature you need is found and enabled by the configure script by checking the output of configure run (see config.summary).

Optional features
Optional feature Packages to install Configure option
Bluetooth

bluez libbluetooth-dev

 

gstreamer multimedia framework support

Wayland development packages is required as it is required by a gstreamer header that is used by Qt.

libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-plugins-bad libgstreamer-plugins-bad1.0-dev gstreamer1.0-pulseaudio gstreamer1.0-tools gstreamer1.0-alsa

libwayland-dev

Automatic, force with

-gstreamer

Optionally disable with

-no-gstreamer

Linux ALSA Audio support

libasound2-dev

Automatic, force with

-alsa

Pulseaudio support

pulseaudio libpulse-dev

Automatic, force with

-pulseaudio

Flite speech synthesis flite1-dev -flite -flite-alsa
Support for various databases (PostgreSQL, MariaDB/MySQL)

libpq-dev libmariadbclient-dev

Automatic, force with

-sql-psql

-sql-mysql

Printing support using CUPS

libcups2-dev

 
Wayland support

libwayland-dev

 
X11 support

libx11-dev libxcb1-dev  libxext-dev libxi-dev libxcomposite-dev libxcursor-dev libxtst-dev libxrandr-dev libfontconfig1-dev libfreetype6-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-util0-dev  libxcb-xinerama0-dev  libxcb-xkb-dev libxkbcommon-dev libxkbcommon-x11-dev

 
QtWebEngine

Required: flex bison gperf libre2-dev libnss3-dev libdrm-dev

Optional: libxml2-dev libxslt1-dev libminizip-dev libjsoncpp-dev liblcms2-dev libevent-dev libprotobuf-dev protobuf-compiler

Optional but unusable versions in raspbian: libopus-dev libvpx-dev

Note: We highly recommend to build QtWebEngine separately from base Qt.

 
libzstd libzstd-dev  
Accessibility

libatspi-dev

 
SCTP [1][2]

libsctp-dev

-sctp

Install any package from the above table with apt install.

Broadcom EGL library filename fix

Note: This is NOT needed when building a Raspberry Pi 4 configuration.

On Raspbian Stretch/Buster the OpenGL library files have been renamed (1, 2) so that they wouldn't conflict with Mesa installed ones. Unfortunately Qt configure script is still looking for the old names. See QTBUG-62216 for details.

If you use the mkspecs configuration files provided in this tutorial you don't need to worry about this as they are setup to reference the libbrcm*.so library names.

Create a shadow build directory outside of the Qt source tree

We will build Qt 5 outside of the source tree, this way you can easily have different build version and easily also start over in case of any issues with configuration or the build itself. Your build location can be anywhere where there is enough space, for example an HDD, SDD or USB stick in case you are running out of spaec on your SD card. Remember to adjust any paths in the example commands.

mkdir build
cd build

Configure the Qt 5 build environment

We configure Qt 5 for a native build and set device specific settings, like libraries, default QPA plugin to use, etc directly on the configure command line. Note that the below configuration is just an example, you might need to adjust it for your particular needs, for example if you do need wayland the remove the "-skip wayland" option. This makes it also easy to optimize for any specific Raspberry Pi board type, see the table for used CFLAGS & CXXFLAGS for your target board. Configure run takes ~10 minutes as it will first compile the Qt build tool qmake and then run various tests and feature checks.

PKG_CONFIG_LIBDIR=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/share/pkgconfig \
../qt-everywhere-src-5.15.12/configure -platform linux-rpi-g++ \
-v \
-opengl es2 -eglfs \
-no-gtk \
-opensource -confirm-license -release \
-reduce-exports \
-force-pkg-config \
-nomake examples -no-compile-examples -nomake tests \
-skip qtwayland \
-skip qtwebengine \
-no-feature-geoservices_mapboxgl \
-qt-pcre \
-no-pch \
-ssl \
-evdev \
-system-freetype \
-fontconfig \
-glib \
-prefix /opt/Qt/5.15 \
-qpa eglfs

Configuration options explained

Wondering what the options do, let the below table explain:

Qt build configuration options explained
Option Description Why is this option used
-v Verbose configuration output To see what is going on
-opengl es2 -eglfs Use OpenGL ES and use Qt EGLFS platform plugin So we don't need to run X11
-no-gtk Don't use GTK theme support No need for GTK development libraries
-opensource -confirm-license Select open source license build, don't prompt for license License needs to be set
-release Use release build options (optimized libraries and binaries) For speed

-nomake examples -no-compile-examples
-nomake tests

Skip building of example applications and tests. Takes time and space
-qt-pcre Use Qt provided pcre library  
-no-pch Don't use pre-compiled C++ headers Takes a lot of space
-ssl Use OpenSSL, required for crypot and for example https support in Qt networking code Crypto is the new black
-evdev Use Linux generic input subsystem  
-system-freetype Use system provided version of freetype library instead of bundled version Speed up compliation
-fontconfig Use fontconfig for font discovery Fonts are nice to have
-glib Use glib compatible event loop Integrates with glib based event loop users, for example gstreamer
-prefix /opt/Qt/5.15

Installation prefix for the Qt framework. Running make install will install Qt at this location.

If you like to have different versions installed then you can use the full version string.

Note: Binaries will have hardcoded paths to the Qt libraries

Qt needs to be installed somewhere where you can find it
-qpa eglfs

Default platform abstraction plugin to use for applications.
Change this if you prefer using something else, for example xcb.

Selects the default platform plugin, on Pi EGLS is nice so you don't need to run X11

About QtWebEngine

Building the qtwebengine module takes a lot of time and space, the default configure example above disables it with -skip qtwebengine. The reason being that on older Raspberry Pi models with a relatively tiny amount of memory it is pretty much impossible to build succesfully.

Building and adding QtWebEngine support

Now with the 4GB or 8GB Raspberry Pi 4 it is fully possible to build, but you might still need to enable swap and also limit the amount of parallel builds the ninja build tool (that qtwebengine uses internally for building) is allowed to use. You can either build qtwebengine at the same time as the rest of Qt, but in case it fails (and it probably will) your whole build has failed, so the recommended way is to first build the base Qt 5 separately, install it and then build qtwebengine separately. But if you so choose, you can enable building of qtwebengine by removing the -skip qtwebengine configure option. Make sure that when you invoke make for building, that you add NINJAJOBS=-j1 to the command line. (make -j4 NINJAJOBS=-j1)

Building QtWebEngine separately

It is highly recommended to build QtWebEngine separately,read the separate guide on how to build qtwebengine.

Raspberry Pi platform options

Select platform according to the Pi model you are going to run Qt on. You can build on a fast Pi 4/3+ and the move the files over to a slower version if needed, just make sure you build for the correct ARM architecture in that case.

Note: For a Qt 5.15 that will be run on a Raspberry Pi 4 you must use KMS as Broadcom EGL is not supported on that model and never will. Make sure you have installed the packages: libgles2-mesa-dev libgbm-dev

Model specific optimization
Raspberry Pi model ARM architecture version Platform option Compiler FLAGS that will be used

Raspberry Pi 4

32-bit

ARMv8 -platform linux-rpi4-v3d-g++
-march=armv8-a -mtune=cortex-a72 -mfpu=crypto-neon-fp-armv8

Note: Will use VC4 DRM Mesa GL driver, not Broadcom EGL as it is not supported on the Pi 4.

Note: Under Bullseye, make sure to add the option: -no-feature-eglfs_brcm so that brcm libraries are not used

Note: You must install libgles2-mesa-dev libgbm-dev libdrm-dev

Raspberry Pi 4

64-bit
ARMv8 -platform linux-rpi64-vc4-g++

Note: Preliminary, not tested properly yet but should work

Note: Under Bullseye, make sure to add the option: -no-feature-eglfs_brcm so that brcm libraries are not used

Note: You must install libgles2-mesa-dev libgbm-dev libdrm-dev

Raspberry Pi 3, models:
3+, A+, Compute Module 3, Compute Module 3+

Raspberry Pi 2, model:
B v1.2

ARMv8
-platform linux-rpi3-g++
 
-march=armv8-a -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8

Note: QtScript won't build with these flags. If you need QtScript, then build with ARMv7 options.
And remove -skip qtscript from configure options.

Note: If you will build Qt Creator you will need QtScript!

Raspberry Pi 2, model:
B
ARMv7
-platform linux-rpi2-g++
 
-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4
Raspberry Pi 1, models:
Original, Zero, Zero W, A, A+, B+, Compute Module 1
ARMv6
-platform linux-rpi-g++
 
-march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp

Check the configure result

When the Qt configuration scripts has finnished succesfully it will print out a configuration summary and store the result in the config.summary file, also all the raw checks will be in the config.log file. Check that all options and features you needed are found and enabled in the summary output. If not, check the config.log file for a reason.

Example configuration summaries for

Broadcom EGLFS

Make sure that the configure script detects Raspberry Pi EGLFS when building for Raspberry Pi 1,2 or 3. Look for the following output or check the log file config.summary:

  EGLFS .................................. yes
  EGLFS details:
...
    EGLFS Rasberry Pi .................... yes

Note: If it says "no", check the configuration run output for reasons. Make sure that you have all required build dependencies installed (check the above table) and fixed the EGLFS library references!

MesaGL

When building for Raspberry Pi 4, check for

  EGLFS .................................. yes
  EGLFS details:
...
    EGLFS EGLDevice ...................... yes
...
    EGLFS Raspberry Pi ................... no

Note: If it says "no" for EGLDevice, check the configuration run output for reasons. Make sure that you have all required build dependencies installed (check the above table), especially the note about Pi 4 packages.

Compile Qt

Now Qt should be configured properly with all features enabled that we need. If you need some of the optional features, make sure to check the configure result that they where properly detected.

To compile Qt run:

make

or if you are using any of the quad-core Pis, append the -j4 parameter to build in parallel. Make sure you have proper cooling in this case, the 3+ this should run fine without getting throttled too much.

Build time

The compilation time depends on the Qt features being built, speed of your SD card, etc. Build time on a Raspberry Pi 3 with two parallel jobs (make -j2) takes roughly 8 hours.

Build times on various platforms
System Time
Raspberry Pi 400 (Bullseye, aarch64, -j4, SD) ~274 minutes
Raspberry Pi 3 (-j2,SD) ~540 minutes

Note: It might happen that parallel build needs too much memory and the compiler will crash. In this case try run with just one process or try -j3 or just -j2. Enabling swap will also help.

Optional: Speed up building with distcc

If you have many Raspberry Pi you can speed up the compilation by using distcc. In that case setup distcc on your machines and invoke make with:

make CC=distcc CXX=distcc -j[Machines in distcc cluster]

Install the build

The compilation should finnish without any errors, if it does not, double check that you have all the dependecies installed and run configure correctly.

If all is well, install Qt by running

make install

You should now have Qt 5.15.12 installed in /opt/Qt/5.15 ready for use. To configure your Qt project(s) to build with this version run qmake from the installation directory:

/opt/Qt/5.15/bin/qmake

You can of course also add it to your PATH, edit your users ".profile" or system wide in "/etc/profile" .

Common build issues

We have collected some common issues that might come up while building in the table below.

Common Qt build issues
Problem Solution

In function ‘EGLNativeWindowType createDispmanxLayer(const QPoint&, const QSize&, int, DISPMANX_FLAGS_ALPHA_T)’:
error: ‘EGL_DISPMANX_WINDOW_T’ was not declared in this scope

You are trying to build with Broadcom BRCM libraries in a 64-bit environment. That will not work.

Solution: Configure with -no-feature-eglfs_brcm

   

Choosing platform

As explained in the introduction, this build will default to using the eglfs platform, meaning that no windowing environment is required to run GUI applications. You can choose the platform binaries will run against by suppling the "-platform" paramter when running them.

Qt Platform option examples
Platform Parameter Information
EGLFS -platform eglfs The default if example options are used (qpa eglfs)
 
X11 -platform xcb  
VNC -platform vnc  
WebGL -platform webgl  

Enjoy Qt 5.15 on your Pi, Happy coding!