RaspberryPiWithQt6WebEngine: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
m (add lld linker)
m (add cleanup setup and write image)
 
(7 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.5 with WebEngine coming from Qt 6.7
In this guide we are going to cross compile Qt 6.9.


{{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.}}


We need fours repositories to have Qt 6WebEngine up and running: qtbase, shadertools, qtdeclarative and qtwebengine.
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:<syntaxhighlight lang="bash">
* Let's create our workspace:<syntaxhighlight lang="bash">
Line 33: Line 33:
</syntaxhighlight>
</syntaxhighlight>


* Let's checkout qt source code and select branches:<syntaxhighlight lang="bash">
* Let's checkout the main qt6 repository, select 6.9 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/qtbase.git
git clone git://code.qt.io/qt/qt5.git qt6
cd qtbase
cd qt6
git checkout origin/6.5.3
git checkout origin/6.9
cd ..
./init-repository --module-subset=qtbase,qtshadertools,qtdeclarative,qtwayland,qtwebengine --no-resolve-deps
 
git clone git://code.qt.io/qt/qtshadertools.git
cd qtshadertools
git checkout origin/6.5.3
cd ..
 
git clone git://code.qt.io/qt/qtdeclarative.git
cd qtdeclarative
git checkout origin/6.5.3
cd ..
 
git clone git://code.qt.io/qt/qtwebengine.git
cd qtwebengine
git checkout origin/6.7
git submodule init
git submodule update
cd ..
</syntaxhighlight>
</syntaxhighlight>


{{note|QtWebEngine needs initialization of the submodule.}}
{{note|Re-selecting other branches requires rerun of init-repository script with option '-f'.}}


==Sysroot==
==Sysroot==
Line 69: Line 52:
* Let's now download Raspberry Pi OS:<syntaxhighlight lang="bash">
* Let's now download Raspberry Pi OS:<syntaxhighlight lang="bash">
cd ~/workspaces/rpi/image
cd ~/workspaces/rpi/image
wget https://downloads.raspberrypi.com/raspios_arm64/images/raspios_arm64-2023-12-06/2023-12-05-raspios-bookworm-arm64.img.xz
wget https://downloads.raspberrypi.com/raspios_arm64/images/raspios_arm64-2024-11-19/2024-11-19-raspios-bookworm-arm64.img.xz
</syntaxhighlight>
</syntaxhighlight>


* Let's extract the image:<syntaxhighlight lang="bash">
* Let's extract the image:<syntaxhighlight lang="bash">
unxz --keep 2023-12-05-raspios-bookworm-arm64.img.xz
unxz --keep 2024-11-19-raspios-bookworm-arm64.img.xz
</syntaxhighlight>
</syntaxhighlight>


* We need add at least 2G space to the image to be able to fit qt build with debug info [[ResizeRaspberryPiImage| (see here instructions) ]]
* We need add at least 2G space to the image to be able to fit qt build with debug info [[ResizeRaspberryPiImage| (see here instructions) ]]
* Make loop devices for the image:<syntaxhighlight lang="bash">
* Make loop devices for the image:<syntaxhighlight lang="bash">
losetup -fP 2023-12-05-raspios-bookworm-arm64.img
losetup -fP 2024-11-19-raspios-bookworm-arm64.img
losetup -a
losetup -a
/dev/loop0: [66306]:2363198 (~/workspaces/rpi/image/2023-12-05-raspios-bookworm-arm64.img)
/dev/loop0: [64769]:10797192 (~/workspaces/rpi/image/2024-11-19-raspios-bookworm-arm64.img)
</syntaxhighlight>
</syntaxhighlight>


Line 90: Line 73:
mount --bind /dev/pts ~/workspaces/rpi/target/dev/pts
mount --bind /dev/pts ~/workspaces/rpi/target/dev/pts
</syntaxhighlight>
</syntaxhighlight>
* Make sure you have working setup of qemu arm64 static interpeter.
{{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.<syntaxhighlight lang="bash">
* We need qemu on the image to able to execute command, therefore copy static qemu binary to image.<syntaxhighlight lang="bash">
cp /usr/bin/qemu-aarch64-static ~/workspaces/rpi/target/usr/bin/
cp /usr/bin/qemu-aarch64-static ~/workspaces/rpi/target/usr/bin/
</syntaxhighlight>
</syntaxhighlight>
{{note| Setup of qemu static interpreter is distribution specific. Please refer to your Linux distribution documentation.}}


* Chroot to arm64 target:<syntaxhighlight lang="bash">
* Chroot to arm64 target:<syntaxhighlight lang="bash">
Line 130: Line 117:
{{note| Command-line tool called [https://linux.die.net/man/8/symlinks symlinks] should not be used instead as it creates dangling links.}}
{{note| Command-line tool called [https://linux.die.net/man/8/symlinks symlinks] should not be used instead as it creates dangling links.}}


* Umount no longer needed mounts:<syntaxhighlight lang="bash">
{{note| We umount the image and detach loop device in [[RaspberryPiWithQt6WebEngine#Cleanup|Cleanup section]]}}
umount ~/workspaces/rpi/target/sys ~/workspaces/rpi/target/proc
umount ~/workspaces/rpi/target/dev/pts ~/workspaces/rpi/target/dev
umount ~/workspaces/rpi/target
</syntaxhighlight>
 
* Detach loop device:<syntaxhighlight lang="bash">
losetup -d /dev/loop0
</syntaxhighlight>


==Toolchain==
==Toolchain==
Line 191: Line 170:
mkdir qtbase
mkdir qtbase
cd qtbase  
cd qtbase  
/qt/qtbase/configure -release -nomake tests -nomake examples -linker lld -prefix /opt/qt/host
/qt/qt6/qtbase/configure -release -nomake tests -nomake examples -linker lld -prefix /opt/qt/host
cmake --build . --parallel
cmake --build . --parallel
cmake --install .
cmake --install .
</syntaxhighlight>
</syntaxhighlight>


{{note | The path /qt/qtbase in chroot is really ~/workspaces/rpi/toolchain/qt/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.}}


* Let's configure and build remaining modules:<syntaxhighlight lang="bash">
* Let's configure and build remaining modules:<syntaxhighlight lang="bash">
cd /qt/build/host
cd /qt/build/host
mkdir qtshadertools qtdeclarative qtwebengine
mkdir qtshadertools qtdeclarative qtwebengine qtwayland


cd qtshadertools
cd qtshadertools
/opt/qt/host/bin/qt-configure-module ../../../qtshadertools
/opt/qt/host/bin/qt-configure-module ../../../qt6/qtshadertools
cmake --build . --parallel
cmake --build . --parallel
cmake --install .
cmake --install .
Line 209: Line 188:


cd qtdeclarative
cd qtdeclarative
/opt/qt/host/bin/qt-configure-module ../../../qtdeclarative
/opt/qt/host/bin/qt-configure-module ../../../qt6/qtdeclarative
cmake --build . --parallel
cmake --install .
cd ..
 
cd qtwayland
/opt/qt/host/bin/qt-configure-module ../../../qt6/qtwayland
cmake --build . --parallel
cmake --build . --parallel
cmake --install .
cmake --install .
Line 215: Line 200:


cd qtwebengine
cd qtwebengine
/opt/qt/host/bin/qt-configure-module ../../../qtwebengine
/opt/qt/host/bin/qt-configure-module ../../../qt6/qtwebengine
cmake --build . --parallel
cmake --build . --parallel
cmake --install .
cmake --install .
Line 283: Line 268:
mkdir qtbase
mkdir qtbase
cd qtbase  
cd qtbase  
../../../qtbase/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
../../../qt6/qtbase/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 .
Line 289: Line 274:
* Let's configure and build remaining modules:<syntaxhighlight lang="bash">
* Let's configure and build remaining modules:<syntaxhighlight lang="bash">
cd /qt/build/target
cd /qt/build/target
mkdir qtshadertools qtdeclarative qtwebengine
mkdir qtshadertools qtdeclarative qtwebengine qtwayland


cd qtshadertools
cd qtshadertools
/opt/qt/target/bin/qt-configure-module ../../../qtshadertools
/opt/qt/target/bin/qt-configure-module ../../../qt6/qtshadertools
cmake --build . --parallel
cmake --build . --parallel
cmake --install .
cmake --install .
Line 298: Line 283:


cd qtdeclarative
cd qtdeclarative
/opt/qt/target/bin/qt-configure-module ../../../qtdeclarative
/opt/qt/target/bin/qt-configure-module ../../../qt6/qtdeclarative
cmake --build . --parallel
cmake --install .
cd ..
 
cd qtwayland
/opt/qt/host/bin/qt-configure-module ../../../qt6/qtwayland
cmake --build . --parallel
cmake --build . --parallel
cmake --install .
cmake --install .
Line 304: Line 295:


cd qtwebengine
cd qtwebengine
/opt/qt/target/bin/qt-configure-module ../../../qtwebengine
/opt/qt/target/bin/qt-configure-module ../../../qt6/qtwebengine
cmake --build . --parallel
cmake --build . --parallel
cmake --install .
cmake --install .
cd ..
cd ..
</syntaxhighlight>
</syntaxhighlight>
==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:<syntaxhighlight lang="bash">
vi /qt/qt6/qtwebengine/examples/webenginewidgets/simplebrowser/CMakeLists.txt
set(CMAKE_INSTALL_RPATH "\$ORIGIN/../../../lib")
</syntaxhighlight>
{{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:
<syntaxhighlight lang="bash">
cd /qt/build/target
mkdir simplebrowser
cd simplebrowser
/opt/qt/target/bin/qt-cmake ../../../qt6/qtwebengine/examples/webenginewidgets/simplebrowser/CMakeLists.txt -DCMAKE_INSTALL_PREFIX=/opt/qt/target/ -G Ninja
cmake --build .
cmake --install .</syntaxhighlight>


==Deploy==
==Deploy==
Line 322: Line 331:
{{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.}}
{{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.}}


* Umount the image and detach loop device:<syntaxhighlight lang="bash">
==Cleanup==
During our toolchain preparastion we have left few mounts behind, therfore it is time to umount evetyhing
 
* Umount no longer needed mounts:<syntaxhighlight lang="bash">
umount ~/workspaces/rpi/target/sys ~/workspaces/rpi/target/proc
umount ~/workspaces/rpi/target/dev/pts ~/workspaces/rpi/target/dev
umount ~/workspaces/rpi/target/dev/pts ~/workspaces/rpi/target/dev
umount ~/workspaces/rpi/target/proc ~/workspaces/rpi/target/sys
umount ~/workspaces/rpi/target
umount ~/workspaces/rpi/target
</syntaxhighlight>
* Detach loop device:<syntaxhighlight lang="bash">
losetup -d /dev/loop0
losetup -d /dev/loop0
</syntaxhighlight>
</syntaxhighlight>


* Copy the image to the SD card (replace sdX with the device on your machine):<syntaxhighlight lang="bash">
==Write image==
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=2023-12-05-raspios-bookworm-arm64.img of=/dev/sdX bs=4M
dd if=2024-11-19-raspios-bookworm-arm64.img of=/dev/sdX bs=4M
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 12:15, 26 February 2025

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:

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.9.

  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.9 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.9
    ./init-repository --module-subset=qtbase,qtshadertools,qtdeclarative,qtwayland,qtwebengine  --no-resolve-deps
    

  Note: Re-selecting other branches requires rerun of init-repository script with option '-f'.

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-2024-11-19/2024-11-19-raspios-bookworm-arm64.img.xz
    
  • Let's extract the image:
    unxz --keep 2024-11-19-raspios-bookworm-arm64.img.xz
    
  • We need add at least 2G 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 2024-11-19-raspios-bookworm-arm64.img
    losetup -a
    /dev/loop0: [64769]:10797192 (~/workspaces/rpi/image/2024-11-19-raspios-bookworm-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 interpeter.

  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 .
    
  • Let's upgrade the image (optional) and install Qt6 build dependencies:
    vi /etc/apt/sources.list
    # uncomment the deb-src lines
    apt update
    apt upgrade
    apt build-dep libqt6gui6
    
  • Let's install build dependencies for QtWebEngine:
    apt install libnss3-dev
    exit
    
  • rsync the parts that we need:
    cd ~/workspaces/rpi/toolchain
    rsync -av ~/workspaces/rpi/target/lib sysroot
    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 'Bookworm' and it is shipped with gcc 12.2 and Qt 6.4. Therefore we will use the gnu gcc cross compiler from Bookworm 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 Bookworm Debian release on your machine execute:
    debootstrap --arch amd64 bookworm ~/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 lld linker:
    apt update
    apt install build-essential crossbuild-essential-arm64 lld
    

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 bookworm main
    
  • Let's install dependencies for Qt host build using know dependencies for Qt 6.4:
    apt update
    apt build-dep libqt6gui6
    
  • Let's install build dependencies for QtWebEngine:
    apt install nodejs gperf bison flex python3-html5lib libnss3-dev
    
  • Let's configure host build for Qt6 qtbase, build it and install into ~/workspaces/rpi/toolchain/opt/qt/host:
    cd /qt/build/host
    mkdir qtbase
    cd qtbase 
    /qt/qt6/qtbase/configure -release -nomake tests -nomake examples -linker lld -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.

  • Let's configure and build remaining modules:
    cd /qt/build/host
    mkdir qtshadertools qtdeclarative qtwebengine qtwayland
    
    cd qtshadertools
    /opt/qt/host/bin/qt-configure-module ../../../qt6/qtshadertools
    cmake --build . --parallel
    cmake --install .
    cd ..
    
    cd qtdeclarative
    /opt/qt/host/bin/qt-configure-module ../../../qt6/qtdeclarative
    cmake --build . --parallel
    cmake --install .
    cd ..
    
    cd qtwayland
    /opt/qt/host/bin/qt-configure-module ../../../qt6/qtwayland
    cmake --build . --parallel
    cmake --install .
    cd ..
    
    cd qtwebengine
    /opt/qt/host/bin/qt-configure-module ../../../qt6/qtwebengine
    cmake --build . --parallel
    cmake --install .
    cd ..
    

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-12)
    set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++-12)
    
    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 
    ../../../qt6/qtbase/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 remaining modules:
    cd /qt/build/target
    mkdir qtshadertools qtdeclarative qtwebengine qtwayland
    
    cd qtshadertools
    /opt/qt/target/bin/qt-configure-module ../../../qt6/qtshadertools
    cmake --build . --parallel
    cmake --install .
    cd ..
    
    cd qtdeclarative
    /opt/qt/target/bin/qt-configure-module ../../../qt6/qtdeclarative
    cmake --build . --parallel
    cmake --install .
    cd ..
    
    cd qtwayland
    /opt/qt/host/bin/qt-configure-module ../../../qt6/qtwayland
    cmake --build . --parallel
    cmake --install .
    cd ..
    
    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/CMakeLists.txt -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=2024-11-19-raspios-bookworm-arm64.img of=/dev/sdX bs=4M