RaspberryPiWithQt6WebEngine: Difference between revisions
m make 16G instead of 2G |
m typo |
||
| (10 intermediate revisions by the same user not shown) | |||
| Line 19: | Line 19: | ||
One Qt6 host build, which is later used to cross-compile the arm64 Qt build. | One Qt6 host build, which is later used to cross-compile the arm64 Qt build. | ||
In this guide we are going to cross compile Qt 6. | In this guide we are going to cross compile Qt 6.12 with QtWebEngine [https://www.qt.io/blog/qt-webengine-will-release-separate 6.140]. | ||
{{note | As shown [[Cross-Compile_Qt_6_for_Raspberry_Pi | here]], we could do a 'top level build' of Qt6, but we are going to do 'prefix module build' just to show an alternative way of building Qt6.}} | {{note | As shown [[Cross-Compile_Qt_6_for_Raspberry_Pi | here]], we could do a 'top level build' of Qt6, but we are going to do 'prefix module build' just to show an alternative way of building Qt6.}} | ||
| Line 33: | Line 33: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Let's checkout the main qt6 repository, select 6. | * Let's checkout the main qt6 repository, select 6.12 branch and fetch source code of minimal subset of qt modules to be able to compile QtWebEngine:<syntaxhighlight lang="bash"> | ||
cd ~/workspaces/rpi/toolchain/qt | cd ~/workspaces/rpi/toolchain/qt | ||
git clone git://code.qt.io/qt/qt5.git qt6 | git clone git://code.qt.io/qt/qt5.git qt6 | ||
cd qt6 | cd qt6 | ||
git checkout origin/6. | git checkout origin/6.12 | ||
./init-repository --module-subset=qtbase,qtshadertools,qtdeclarative | ./init-repository --module-subset=qtbase,qtshadertools,qtdeclarative --no-resolve-deps | ||
</syntaxhighlight> | </syntaxhighlight> | ||
{{note|Re-selecting other branches requires rerun of init-repository script with option '-f'.}} | {{note|Re-selecting other branches requires rerun of init-repository script with option '-f'.}} | ||
* Let's now clone qtwebenigne repository and switch to 6.140 branch :<syntaxhighlight lang="bash"> | |||
cd ~/workspaces/rpi/toolchain/qt | |||
git clone git://code.qt.io/qt/qtwebengine.git qtwebengine | |||
git checkout origin/6.140 | |||
git submodule update --init | |||
</syntaxhighlight> | |||
==Sysroot== | ==Sysroot== | ||
| Line 104: | Line 111: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* rsync the parts that we need:<syntaxhighlight lang="bash"> | * exit and rsync the parts that we need:<syntaxhighlight lang="bash"> | ||
exit | |||
cd ~/workspaces/rpi/toolchain | cd ~/workspaces/rpi/toolchain | ||
rsync -av ~/workspaces/rpi/target/lib sysroot | rsync -av ~/workspaces/rpi/target/lib sysroot/lib | ||
rsync -av ~/workspaces/rpi/target/usr/include sysroot/usr | rsync -av ~/workspaces/rpi/target/usr/include sysroot/usr | ||
rsync -av ~/workspaces/rpi/target/usr/lib sysroot/usr | rsync -av ~/workspaces/rpi/target/usr/lib sysroot/usr | ||
| Line 125: | Line 133: | ||
To cross-compile Qt, we need a cross-compiler toolchain. There are many excellent tools to compile a toolchain, such as [https://crosstool-ng.github.io crosstool-ng]. We could also simply download ready 3dparty toolchain form the internet. However, this guide will use the official gcc cross compiler, which is shipped with Debian distribution, same as the one shipped with Raspberry Pi OS. | To cross-compile Qt, we need a cross-compiler toolchain. There are many excellent tools to compile a toolchain, such as [https://crosstool-ng.github.io crosstool-ng]. We could also simply download ready 3dparty toolchain form the internet. However, this guide will use the official gcc cross compiler, which is shipped with Debian distribution, same as the one shipped with Raspberry Pi OS. | ||
In time of writing this quide latest Raspberry Pi OS is called ' | In time of writing this quide latest Raspberry Pi OS is called 'Trixie' and it is shipped with gcc 14.2 and Qt 6.8. Therefore we will use the gnu gcc cross compiler from Trixie release. | ||
To setup the cross-compiler toolchain will use 'debootstrap' which is a very convenient tool to install Debian base system into a subdirectory | To setup the cross-compiler toolchain will use 'debootstrap' which is a very convenient tool to install Debian base system into a subdirectory | ||
of any other running Linux system. Most of distributions ship this tool therefore it was selected as most generic approach. | of any other running Linux system. Most of distributions ship this tool therefore it was selected as most generic approach. | ||
| Line 131: | Line 139: | ||
{{note | The other approach could be for example installing Debian distribution on VM.}} | {{note | The other approach could be for example installing Debian distribution on VM.}} | ||
* To setup | * To setup Trixie Debian release on your machine execute:<syntaxhighlight lang="bash"> | ||
debootstrap --arch amd64 | debootstrap --arch amd64 trixie ~/workspaces/rpi/toolchain http://ftp.uk.debian.org/debian | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 144: | Line 152: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Let's install host, cross compiler and | * Let's install host, cross compiler and mold linker:<syntaxhighlight lang="bash"> | ||
apt update | apt update | ||
apt install build-essential crossbuild-essential-arm64 | apt install build-essential crossbuild-essential-arm64 mold | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 158: | Line 166: | ||
* Add source packages repository for 'apt' by following line to '/etc/apt/sources.list' file:<syntaxhighlight lang="bash"> | * Add source packages repository for 'apt' by following line to '/etc/apt/sources.list' file:<syntaxhighlight lang="bash"> | ||
deb-src http://deb.debian.org/debian | deb-src http://deb.debian.org/debian trixie main | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Let's install dependencies for Qt host build using know dependencies for Qt 6. | * Let's install dependencies for Qt host build using know dependencies for Qt 6.8:<syntaxhighlight lang="bash"> | ||
apt update | apt update | ||
apt build-dep | apt build-dep libqt6webenginecore6 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Let's configure host build for Qt6, build it and install into ~/workspaces/rpi/toolchain/opt/qt/host:<syntaxhighlight lang="bash"> | |||
* Let's configure host build for Qt6 | |||
cd /qt/build/host | cd /qt/build/host | ||
mkdir qtbase | mkdir qtbase | ||
cd qtbase | cd qtbase | ||
/qt/qt6 | /qt/qt6/configure -release -nomake tests -nomake examples -linker mold -prefix /opt/qt/host | ||
cmake --build . --parallel | cmake --build . --parallel | ||
cmake --install . | cmake --install . | ||
| Line 180: | Line 185: | ||
{{note | The path /qt/qt6/qtbase in chroot is really ~/workspaces/rpi/toolchain/qt/qt6/qtbase on the build machine.}} | {{note | The path /qt/qt6/qtbase in chroot is really ~/workspaces/rpi/toolchain/qt/qt6/qtbase on the build machine.}} | ||
* | * To be able to cross compile QtWebEngine module we also need gn, therfreo let's configure and build one from qtwebengine:<syntaxhighlight lang="bash"> | ||
cd /qt/build/host | cd /qt/build/host | ||
mkdir | mkdir qtwebengine | ||
cd qtwebengine | cd qtwebengine | ||
/opt/qt/host/bin/qt-configure-module ../../../qt6/qtwebengine | /opt/qt/host/bin/qt-configure-module ../../../qt6/qtwebengine -- -DBUILD_ONLY_GN=ON | ||
cmake --build . --parallel | cmake --build . --parallel | ||
cmake --install . | cmake --install . | ||
cd .. | cd .. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
{{note | We could build the whole module, but we just need gn binary, therfore we use BUILD_ONLY_GN define.}} | |||
==Qt6 Target Cross Build== | ==Qt6 Target Cross Build== | ||
| Line 225: | Line 214: | ||
set(CMAKE_SYSROOT /sysroot) | set(CMAKE_SYSROOT /sysroot) | ||
set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc- | set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc-14) | ||
set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++- | set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++-14) | ||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | ||
| Line 271: | Line 260: | ||
mkdir qtbase | mkdir qtbase | ||
cd qtbase | cd qtbase | ||
/qt/qt6/configure -release -opengl es2 -nomake examples -nomake tests -qt-host-path /opt/qt/host -extprefix /opt/qt/target -prefix /usr/local/qt6 -- -DCMAKE_TOOLCHAIN_FILE=/qt/rpi.toolchain.cmake | |||
cmake --build . --parallel | cmake --build . --parallel | ||
cmake --install . | cmake --install . | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Let's configure and build | * Let's configure and build QtWebEngine module:<syntaxhighlight lang="bash"> | ||
cd /qt/build/target | cd /qt/build/target | ||
mkdir | mkdir qtwebengine | ||
cd qtwebengine | cd qtwebengine | ||
| Line 318: | Line 289: | ||
cd simplebrowser | cd simplebrowser | ||
/opt/qt/target/bin/qt-cmake ../../../qt6/qtwebengine/examples/webenginewidgets/simplebrowser | /opt/qt/target/bin/qt-cmake ../../../qt6/qtwebengine/examples/webenginewidgets/simplebrowser -DCMAKE_INSTALL_PREFIX=/opt/qt/target/ -G Ninja | ||
cmake --build . | cmake --build . | ||
cmake --install .</syntaxhighlight> | cmake --install .</syntaxhighlight> | ||
| Line 350: | Line 321: | ||
It is time to copy the image to the SD card (replace sdX with the device on your machine):<syntaxhighlight lang="bash"> | It is time to copy the image to the SD card (replace sdX with the device on your machine):<syntaxhighlight lang="bash"> | ||
cd ~/workspaces/rpi/image | cd ~/workspaces/rpi/image | ||
dd if= | dd if=2026-09-15-raspios-trixie-arm64.img of=/dev/sdX bs=4M | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Latest revision as of 15:02, 9 October 2026
Introduction
This page describes how to set up self-compiled Qt6 with WebEngine on Raspberry Pi 4 running Raspberry Pi OS.
To see other guides visit:
- Qt5 WebEngine cross compilation guide for Raspbian
- Qt6 general cross compilation guide for Raspberry Pi OS
- Qt6 WebEngine general compilation quide for all platforms
Setup
To be able to cross compile Qt6 for Raspberry Pi OS, we need three things:
Qt6 uses cmake therefore to cross-compile we need to have actually two builds of Qt. One Qt6 host build, which is later used to cross-compile the arm64 Qt build.
In this guide we are going to cross compile Qt 6.12 with QtWebEngine 6.140.
Note: As shown here, we could do a 'top level build' of Qt6, but we are going to do 'prefix module build' just to show an alternative way of building Qt6.
As latest Raspberry Pi runs on wayland we need five repositories to have Qt 6WebEngine up and running: qtbase, shadertools, qtdeclarative, qtwebengine and qtwayland.
- Let's create our workspace:
mkdir -p ~/workspaces/rpi/toolchain/sysroot mkdir -p ~/workspaces/rpi/toolchain/qt/build/host mkdir -p ~/workspaces/rpi/toolchain/qt/build/target mkdir -p ~/workspaces/rpi/target mkdir -p ~/workspaces/rpi/image
- Let's checkout the main qt6 repository, select 6.12 branch and fetch source code of minimal subset of qt modules to be able to compile QtWebEngine:
cd ~/workspaces/rpi/toolchain/qt git clone git://code.qt.io/qt/qt5.git qt6 cd qt6 git checkout origin/6.12 ./init-repository --module-subset=qtbase,qtshadertools,qtdeclarative --no-resolve-deps
Note: Re-selecting other branches requires rerun of init-repository script with option '-f'.
- Let's now clone qtwebenigne repository and switch to 6.140 branch :
cd ~/workspaces/rpi/toolchain/qt git clone git://code.qt.io/qt/qtwebengine.git qtwebengine git checkout origin/6.140 git submodule update --init
Sysroot
To be able to cross-compile, we need a part of arm64 target sysroot to be present on our build machine. As shown here, you could simply start your Rasberry Pi OS on the board and then rsync the required libs and includes to the host machine with SSH connection. However, in this guide we will mount the Raspberry Pi OS image via a loop device, use qemu to install build dependencies and than make a local copy.
Note: We do need a local copy of 'libs' and 'headers' from the image, as we want to adjust the symlinks.
- Let's now download Raspberry Pi OS:
cd ~/workspaces/rpi/image wget https://downloads.raspberrypi.com/raspios_arm64/images/raspios_arm64-2026-09-15/2026-09-15-raspios-trixie-arm64.img.xz
- Let's extract the image:
unxz --keep 2026-09-15-raspios-trixie-arm64.img.xz
- We need add at least 16G space to the image to be able to fit qt build with debug info (see here instructions)
- Make loop devices for the image:
losetup -fP 2026-09-15-raspios-trixie-arm64.img losetup -a /dev/loop0: [64769]:10797192 (~/workspaces/rpi/image/2026-09-15-raspios-trixie-arm64.img)
- Mount the root partition:
mount /dev/loop0p2 -t ext4 ~/workspaces/rpi/target mount -t proc /proc ~/workspaces/rpi/target/proc mount -t sysfs /sys ~/workspaces/rpi/target/sys mount --bind /dev ~/workspaces/rpi/target/dev mount --bind /dev/pts ~/workspaces/rpi/target/dev/pts
- Make sure you have working setup of qemu arm64 static interpreter.
Note: Setup of qemu static interpreter is distribution specific. Please refer to your Linux distribution documentation.
Note: Also registering bin formats is distribution specific. Check 'systemctl status binfmt' if you distribution uses systemd.
- We need qemu on the image to able to execute command, therefore copy static qemu binary to image.
cp /usr/bin/qemu-aarch64-static ~/workspaces/rpi/target/usr/bin/
- Chroot to arm64 target:
cd ~/workspaces/rpi/target chroot .
- Go to the apt sources file, look for the line that says 'Types: deb' and change it to include 'deb-src':
vi /etc/apt/sources.list.d/debian.sources Types: deb deb-src URIs: http://deb.debian.org/debian/ Suites: trixie trixie-updates Components: main contrib non-free non-free-firmware ...
- Let's upgrade the image (optional) and install Qt6 build dependencies:
apt update apt upgrade apt build-dep libqt6webenginecore6
- exit and rsync the parts that we need:
exit cd ~/workspaces/rpi/toolchain rsync -av ~/workspaces/rpi/target/lib sysroot/lib rsync -av ~/workspaces/rpi/target/usr/include sysroot/usr rsync -av ~/workspaces/rpi/target/usr/lib sysroot/usr rsync -av ~/workspaces/rpi/target/usr/share/pkgconfig sysroot/usr/share
- Adjust symlinks to be relative:
wget https://raw.githubusercontent.com/Kukkimonsuta/rpi-buildqt/master/scripts/utils/sysroot-relativelinks.py chmod +x sysroot-relativelinks.py ./sysroot-relativelinks.py sysroot
Note: Command-line tool called symlinks should not be used instead as it creates dangling links.
Note: We umount the image and detach loop device in Cleanup section
Toolchain
To cross-compile Qt, we need a cross-compiler toolchain. There are many excellent tools to compile a toolchain, such as crosstool-ng. We could also simply download ready 3dparty toolchain form the internet. However, this guide will use the official gcc cross compiler, which is shipped with Debian distribution, same as the one shipped with Raspberry Pi OS. In time of writing this quide latest Raspberry Pi OS is called 'Trixie' and it is shipped with gcc 14.2 and Qt 6.8. Therefore we will use the gnu gcc cross compiler from Trixie release. To setup the cross-compiler toolchain will use 'debootstrap' which is a very convenient tool to install Debian base system into a subdirectory of any other running Linux system. Most of distributions ship this tool therefore it was selected as most generic approach.
Note: The other approach could be for example installing Debian distribution on VM.
- To setup Trixie Debian release on your machine execute:
debootstrap --arch amd64 trixie ~/workspaces/rpi/toolchain http://ftp.uk.debian.org/debian
- Let's mount and chroot into newly created installation:
mount -t proc /proc ~/workspaces/rpi/toolchain/proc mount -t sysfs /sys ~/workspaces/rpi/toolchain/sys mount --bind /dev ~/workspaces/rpi/toolchain/dev mount --bind /dev/pts ~/workspaces/rpi/toolchain/dev/pts chroot ~/workspaces/rpi/toolchain /bin/bash
- Let's install host, cross compiler and mold linker:
apt update apt install build-essential crossbuild-essential-arm64 mold
Qt6 Host Build
We need Qt6 host build as cross-compilation requires all host compiled tools like for example 'moc'. We will do here qt 'module' build in separate build directory.
Note: For more information about build options see here.
Note: After toolchain setup, we should be still chrooted into our host Debian root (~/workspaces/rpi/toolchain).
- Add source packages repository for 'apt' by following line to '/etc/apt/sources.list' file:
deb-src http://deb.debian.org/debian trixie main
- Let's install dependencies for Qt host build using know dependencies for Qt 6.8:
apt update apt build-dep libqt6webenginecore6
- Let's configure host build for Qt6, build it and install into ~/workspaces/rpi/toolchain/opt/qt/host:
cd /qt/build/host mkdir qtbase cd qtbase /qt/qt6/configure -release -nomake tests -nomake examples -linker mold -prefix /opt/qt/host cmake --build . --parallel cmake --install .
Note: The path /qt/qt6/qtbase in chroot is really ~/workspaces/rpi/toolchain/qt/qt6/qtbase on the build machine.
- To be able to cross compile QtWebEngine module we also need gn, therfreo let's configure and build one from qtwebengine:
cd /qt/build/host mkdir qtwebengine cd qtwebengine /opt/qt/host/bin/qt-configure-module ../../../qt6/qtwebengine -- -DBUILD_ONLY_GN=ON cmake --build . --parallel cmake --install . cd ..
Note: We could build the whole module, but we just need gn binary, therfore we use BUILD_ONLY_GN define.
Qt6 Target Cross Build
We should have by now Qt6 host build, target arm64 sysroot and cross compilation toolchain. To setup now cmake build we still need to create cmake toolchain file 'rpi.toolchain.cmake', which will provide information to cmake about our toolchian and sysroot setup.
Note: After toolchain setup, we should be still chrooted into our host Debian root (~/workspaces/rpi/toolchain).
- Let's create toolchain file:
vi /qt/rpi.toolchain.cmake cmake_minimum_required(VERSION 3.18) include_guard(GLOBAL) set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_SYSROOT /sysroot) set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc-14) set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++-14) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(QT_COMPILER_FLAGS "-march=armv8-a") set(QT_COMPILER_FLAGS_RELEASE "-O2 -pipe") set(QT_LINKER_FLAGS "-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed") include(CMakeInitializeConfigs) function(cmake_initialize_per_config_variable _PREFIX _DOCSTRING) if (_PREFIX MATCHES "CMAKE_(C|CXX|ASM)_FLAGS") set(CMAKE_${CMAKE_MATCH_1}_FLAGS_INIT "${QT_COMPILER_FLAGS}") foreach(config DEBUG RELEASE MINSIZEREL RELWITHDEBINFO) if (DEFINED QT_COMPILER_FLAGS_${config}) set(CMAKE_${CMAKE_MATCH_1}_FLAGS_${config}_INIT "${QT_COMPILER_FLAGS_${config}}") endif() endforeach() endif() if (_PREFIX MATCHES "CMAKE_(SHARED|MODULE|EXE)_LINKER_FLAGS") foreach (config SHARED MODULE EXE) set(CMAKE_${config}_LINKER_FLAGS_INIT "${QT_LINKER_FLAGS}") endforeach() endif() _cmake_initialize_per_config_variable(${ARGV}) endfunction() # See output of 'pkg-config --variable pc_path pkg-config' command. set(ENV{PKG_CONFIG_PATH} "") set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_SYSROOT}/usr/lib/aarch64-linux-gnu/pkgconfig:${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig) set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})
Note: If you wonder why we overload 'cmake_initialize_per_config_variable' see this blog post.
Note: The pkg-config exports could be set in build shell instead of toolchain.
- Let's configure target build for Qt6 qtbase, build it and install into ~/workspaces/rpi/toolchain/opt/qt/target:
cd /qt/build/target mkdir qtbase cd qtbase /qt/qt6/configure -release -opengl es2 -nomake examples -nomake tests -qt-host-path /opt/qt/host -extprefix /opt/qt/target -prefix /usr/local/qt6 -- -DCMAKE_TOOLCHAIN_FILE=/qt/rpi.toolchain.cmake cmake --build . --parallel cmake --install .
- Let's configure and build QtWebEngine module:
cd /qt/build/target mkdir qtwebengine cd qtwebengine /opt/qt/target/bin/qt-configure-module ../../../qt6/qtwebengine cmake --build . --parallel cmake --install . cd ..
Simplebrowser
To be able to test QtWebengine we can build 'simplebrowser' example.
- first to able to run the example on the device we need a proper RPATH set for our target application, therefore edit example's 'CMakeLists.txt' and add the correct setting for our setup:
vi /qt/qt6/qtwebengine/examples/webenginewidgets/simplebrowser/CMakeLists.txt set(CMAKE_INSTALL_RPATH "\$ORIGIN/../../../lib")
Note: You do not have to st RPATH, instead use can export LD_LIBRARY_PATH to point to Qt installed libs on the device.
- now let's configure and build the example:
cd /qt/build/target
mkdir simplebrowser
cd simplebrowser
/opt/qt/target/bin/qt-cmake ../../../qt6/qtwebengine/examples/webenginewidgets/simplebrowser -DCMAKE_INSTALL_PREFIX=/opt/qt/target/ -G Ninja
cmake --build .
cmake --install .
Deploy
We need to deploy compiled sources to sdcard. We can use RasberryPi OS image from sysroot step, mount it and rsync the content.
Note: We are not any longer in the chrooted enviroment, however target image is still mounted.
- Deploy with rsync:
rsync -av ~/workspaces/rpi/toolchain/opt/qt/target/ ~/workspaces/rpi/target/usr/local/qt6/
Note: If you wnat to rsync sysroot over the network, just replace the rsync steps below with the equivalent network location of your Rasberry Pi board.
Cleanup
During our toolchain preparastion we have left few mounts behind, therfore it is time to umount evetyhing
- Umount no longer needed mounts:
umount ~/workspaces/rpi/target/sys ~/workspaces/rpi/target/proc umount ~/workspaces/rpi/target/dev/pts ~/workspaces/rpi/target/dev umount ~/workspaces/rpi/target
- Detach loop device:
losetup -d /dev/loop0
Write image
It is time to copy the image to the SD card (replace sdX with the device on your machine):
cd ~/workspaces/rpi/image
dd if=2026-09-15-raspios-trixie-arm64.img of=/dev/sdX bs=4M