RaspberryPiWithQt5WebEngine: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
(fix deploy instructions)
m (fix formatting)
 
(35 intermediate revisions by 3 users not shown)
Line 1: Line 1:
This is simple and basic guide to how setup self compiled qtwebengine on raspberry pi3 running Raspbian Stretch with webgl support using VC4 open source drivers.
 
This page describes how to set up self-compiled '''Qt5 WebEngine on Raspberry Pi 3 running Raspbian Stretch with WebGL support using VC4 open source drivers'''.
 
To see other guides visit:
* [[RaspberryPi2EGLFS|Qt5 general cross compilation guide for Raspbian with closed source drivers and the toolchain from Broadcom]]
* [[RaspberryPiWithQt6WebEngine|Qt6 WebEngine cross compilation guide for Raspberry Pi OS]]
* [[Cross-Compile_Qt_6_for_Raspberry_Pi|Qt6 general cross compilation guide for Raspberry Pi OS]]


==Setup==
==Setup==


The setup is tested on Rasberry3 model B, and qt version we are going to compile is 5.13.1. We are going to use newest open source VC4 Gallium3D driver instead of old close source binaries from Broadcom.
The setup is tested on Rasberry Pi 3 model B. We'll use the latest open source VC4 Gallium3D driver instead of the old closed source binaries from Broadcom. We cannot use the Broadcom toolchain to compile Qt 5.13.2. and Qt WebEngine, because it uses the GCC compiler version 4.8, and we'll need at least version 5.0.  
We are not going to use Bradcom toolchain since it has old 4.8 gcc compiler and to compile qtwebengine we need at least gcc 5.0. Raspbian Stretch ships with Binutils 2.28, GCC 6.3.0 and Glibc 2.24. Since
we would like to use same Glibc version and try to avoid getting a lot of issues when trying to compiler older Glibc 2.24 with some more modern GCC, we are going to simply mirror rasbian setup and reuse the same versions
as Raspbian ships. Therefore we start with downloading sources and raspbian image.


* let's create our workspace
Raspbian Stretch ships with Binutils 2.28, GCC 6.3.0 and GlibC 2.24. Since we would like to use the same GlibC version and try to avoid running into a lot of issues when trying to compiler older GlibC 2.24 with newer GCC, we are going to simply mirror the Raspbian setup and reuse the same versions as Raspbian ships. Therefore we'll start with downloading the sources and Raspbian image.


<code lang="bash">
* Let's create our workspace:<syntaxhighlight>
mkdir -p ~/workspaces/raspberrypi-raspbian/image
mkdir -p ~/workspaces/raspberrypi-raspbian/image
mkdir -p ~/workspaces/raspberrypi-raspbian/toolchain/sources
mkdir -p ~/workspaces/raspberrypi-raspbian/toolchain/sources
mkdir -p ~/workspaces/raspberrypi-raspbian/qt/qt5
mkdir -p ~/workspaces/raspberrypi-raspbian/qt/qt5
</code>
</syntaxhighlight>
 
* let's now download archives


<code lang="bash">
* Let's now download archives:<syntaxhighlight>
cd ~/workspaces/raspberrypi-raspbian/image
cd ~/workspaces/raspberrypi-raspbian/image
wget https://downloads.raspberrypi.org/raspbian/images/raspbian-2019-04-09/2019-04-08-raspbian-stretch.zip
wget https://downloads.raspberrypi.org/raspbian/images/raspbian-2019-04-09/2019-04-08-raspbian-stretch.zip
Line 26: Line 27:
tar xf gcc-6.3.0.tar.gz
tar xf gcc-6.3.0.tar.gz
tar xf binutils-2.28.tar.bz2
tar xf binutils-2.28.tar.bz2
</code>
</syntaxhighlight>


Please note, most likely you would like to download corresponding sha1 to verify the archives.
Please note, most likely you would like to download the corresponding SHA1 to verify the archives.


==Sysroot==
==Sysroot==


To be able to compile things we need a part of sysroot to be present on our build machine. As shown here you could simply start your Raspbian on the boards and then rsync
To be able to compile things, we need a part of sysroot to be present on our build machine. As shown [[RaspberryPi2EGLFS|here]], you could simply start your Raspbian on the board and then rsync required 'libs' and 'includes' to the host machine using the SSH connection.  
over the network required libs and includes to host machine. Here is alternative way of doing the same but by mounting the image via loop device.
However, in this guide we will mount the image via a loop device, use qemu to install build dependencies and than make a local copy.
The reason we need a copy it that we want to modify the adjust the symlinks on our sysroot.  


* first lets extract Raspbian image  
{{note|We need actually a local copy of 'libs' and 'headers' from the image, as we want to adjust the symlinks.}}


<code lang="bash">
* Let's extract the Raspbian image:<syntaxhighlight>
cd ~/workspaces/raspberrypi-raspbian/image
cd ~/workspaces/raspberrypi-raspbian/image
unzip 2019-04-08-raspbian-stretch.zip
unzip 2019-04-08-raspbian-stretch.zip
</code>
</syntaxhighlight>


* check the partition layout and note start sector of root partition (img2)
* We need add at least 2G space to the image to be able to fit qt build with debug info [[ResizeRaspberryPiImage| (see here instructions) ]]


<code lang="bash">
* Make loop devices for the image:<syntaxhighlight >
fdisk -u -l 2019-04-08-raspbian-stretch.img
losetup -fP 2019-04-08-raspbian-stretch.img
losetup -a
/dev/loop0: []: (~/raspberrypi-raspbian/image/2019-04-08-raspbian-stretch.img)
</syntaxhighlight>


Disk 2019-04-08-raspbian-stretch.img: 3.2 GiB, 3481272320 bytes, 6799360 sectors
* Mount the root partition:<syntaxhighlight>
Units: sectors of 1 * 512 = 512 bytes
mount /dev/loop0p2 -t ext4 /media/card
Sector size (logical/physical): 512 bytes / 512 bytes
mount --bind /dev /media/card/dev
I/O size (minimum/optimal): 512 bytes / 512 bytes
mount --bind /sys /media/card/sys
Disklabel type: dos
mount --bind /proc /media/card/proc
Disk identifier: 0xcd48578f
mount --bind /dev/pts /media/card/dev/pts
Device                          Boot Start    End Sectors  Size Id Type
</syntaxhighlight>
2019-04-08-raspbian-stretch.img1      8192  96042  87851 42.9M  c W95 FAT32 (LBA)
2019-04-08-raspbian-stretch.img2      98304 6799359 6701056  3.2G 83 Linux
</code>


* mount the root partition
* We need qemu on the image to able to execute command, therefore copy static qemu binary to image.<syntaxhighlight>
cp /usr/bin/qemu-arm /media/card/usr/bin/
</syntaxhighlight>
{{note| Setup of qemu static interpreter is distribution specific. Please refer to your Linux distribution documentation.}}


<code lang="bash">
* Chroot to sysroot and get qt5 build dependencies in:<syntaxhighlight>
mount -o loop,ro,offset=$((512*98304)) -t ext4 2019-04-08-raspbian-stretch.img  /media/card/
cd /media/card/
</code>
chroot . bin/bash
# uncomment the deb-src line
vi /etc/apt/sources.list
apt update
apt install devscripts   
mk-build-deps libqt5gui5
apt install ./qtbase-opensource-src-build-deps_5.7.1+dfsg-3+rpi1+deb9u1_armhf.deb
apt install libnss3 libnss3-dev
exit
</syntaxhighlight>
{{note| We are going to use mk-build-deps to create dummy package, so we can uninstall dependencies when no longer needed.}}
* rsync the parts that we need:<syntaxhighlight>
cd ~/workspaces/raspberrypi-raspbian
rsync -av /media/card/lib sysroot
rsync -av /media/card/usr/include sysroot/usr
rsync -av /media/card/usr/lib sysroot/usr
</syntaxhighlight>


* rsync what we need
* Adjust symlinks to be relative:<syntaxhighlight>
wget https://raw.githubusercontent.com/Kukkimonsuta/rpi-buildqt/master/scripts/utils/sysroot-relativelinks.py
chmod +x sysroot-relativelinks.py
./sysroot-relativelinks.py sysroot
</syntaxhighlight>


<code lang="bash">
* Cleanup image (optional)<syntaxhighlight>
cd ~/workspaces/raspberrypi-raspbian/
cd /media/card/
mkdir -p sysroot/usr
chroot . bin/bash
rsync -avz /media/card/lib sysroot
apt remove devscripts qtbase-opensource-src-build-deps libnss3-dev
rsync -avz /media/card/usr/include sysroot/usr
apt autoremove
rsync -avz /media/card/usr/lib sysroot/usr
apt clean
</code>
exit
</syntaxhighlight>


* adjust symlinks to be relative
* Umount no longer needed mounts:<syntaxhighlight>
umount /media/card/sys /media/card/proc /media/card/dev/pts /media/card/dev
</syntaxhighlight>


<code lang="bash">
* Detach loop device:<syntaxhighlight>
wget https://raw.githubusercontent.com/Kukkimonsuta/rpi-buildqt/master/scripts/utils/sysroot-relativelinks.py
losetup -d /dev/loop0
chmod +x sysroot-relativelinks.py
</syntaxhighlight>
./sysroot-relativelinks.py sysroot
</code>


==Toolchain==
==Toolchain==


To compile qt we need cross-compiler toolchian. There are many excellent tools to compile a toolchain for you like for example crosstool-ng or buildroot, however
To compile Qt, we need a cross-compiler toolchain. There are many excellent tools to compile a toolchain, such as crosstool-ng or buildroot. However, we choose to
here we will compile gcc from scratch. Compiling a compiler is a bit tricky and requires few steps like:
compile GCC from scratch. Compiling a compiler is a bit tricky and includes a few tasks:
 
* install linux headers, headers are required to make system calls from c library
* building biuntils to get cross-linker, cross-assembler and some other tools using your host compiler
* building first stage / bootstrap gcc, this basic compiler only with c language support and static linking
* building c library using first stage compiler
* building second stage gcc which uses c library and support for dynamic lining and c++ language


We already have a glibc compiled in our sysroot shipped by Rasbian , so we are going to cheat here a bit and skip boot strapping of gcc and building glibc itself.
* Installing Linux headers that are required to make system calls from the C library and to compile it
We can simply use sysroot directly and just compile linker and final cross-compiler.
* Building biuntils to get a cross-linker, a cross-assembler, and some other tools using your host compiler
* Building the first stage GCC (bootstrapping), to have a basic compiler with C language support and static linking
* Building the C library using the first stage compiler  
* Building a second stage GCC, which uses the C library, supports dynamic linking and the C++ language


* first we do initial setup
We already have GlibC compiled in our sysroot shipped by Rasbian, so we are going to cheat here a bit and skip the bootstrapping of GCC and the building of GlibC itself.
We can simply use sysroot directly and just compile the linker, the assembler and final cross-compiler.


<code lang="bash">
* Let's do initial setup:<syntaxhighlight>
export WORKSPACE_ROOT=~/workspaces/raspberrypi-raspbian/toolchain
export WORKSPACE_ROOT=~/workspaces/raspberrypi-raspbian/toolchain
export PREFIX=${WORKSPACE_ROOT}/toolchain
export PREFIX=${WORKSPACE_ROOT}/toolchain
Line 107: Line 129:
mkdir -p ${PREFIX}
mkdir -p ${PREFIX}
cd ${WORKSPACE_ROOT}
cd ${WORKSPACE_ROOT}
</syntaxhighlight>


</code>
* Let's build the linker and assembler: <syntaxhighlight>
 
* let's build linker and assembler  
 
<code lang="bash">
mkdir -p build/binutils
mkdir -p build/binutils
pushd build/binutils
pushd build/binutils
Line 119: Line 138:
make install
make install
popd
popd
</code>
</syntaxhighlight>


* we need extra GMP, MPFR and MPC libraries to be able to build gcc. This can be easily setup by running script in gcc source directory.
* We need additional GMP, MPFR and MPC libraries to be able to build GCC. This can be easily set up by running script in the GCC source directory.<syntaxhighlight>
 
<code lang="bash">
cd ~/workspaces/raspberrypi-raspbian/toolchain/sources/gcc-6.3.0
cd ~/workspaces/raspberrypi-raspbian/toolchain/sources/gcc-6.3.0
contrib/download_prerequisites  
contrib/download_prerequisites  
</code>
</syntaxhighlight>


* let's now build gcc
* Let's now build GCC:<syntaxhighlight>
 
<code lang="bash">
mkdir -p build/gcc2
mkdir -p build/gcc2
pushd build/gcc2
pushd build/gcc2
Line 137: Line 152:
make install
make install
popd
popd
</code>
</syntaxhighlight>


=Compiling Qt=
Note that I got a compiler error, so you might have to edit raspberrypi-raspbian/toolchain/sources/gcc-6.3.0/gcc/ubsan.c line 1474 and change it to:<syntaxhighlight>
|| xloc.file[0] == '\0' || xloc.file[0] == '\xff'
</syntaxhighlight>


As shown here we could do top level build of qt, but instead we are going to do prefix module builds just to show alternative way of building qt.
==Compiling Qt==
We need three modules to have webenigne up and running qtbase, qtdeclarative and qtwebenigne. What is important is to configure qt with linux-rasp-pi3-vc4-g++ device,
since this specs contains newer vc4 opengl drivers. We also compile two backends for qpa, xcb to run it whin Rasbian window manager and eglfs to run as full screen single window application.


* configure qtbase, compile and install
As shown [[RaspberryPi2EGLFS|here]], we could do a top level build of Qt, but we are going to do prefix module builds just to show an alternative way of building Qt.
We need three repositories to have Qt WebEngine up and running: qtbase, qtdeclarative and qtwebengine. It is important to configure Qt with linux-rasp-pi3-vc4-g++ device, since this spec contains newer vc4 OpenGL drivers. We also compile two back-ends for QPA: xcb to run it in the Rasbian window manager and eglfs to run as a full-screen single-window application.


<code lang="bash">
* Let's configure qtbase, compile it and install it:<syntaxhighlight>
cd ~/workspaces/qt/qt5
cd ~/workspaces/raspberrypi-raspbian/qt/qt5
git clone git://code.qt.io/qt/qtbase.git
git clone git://code.qt.io/qt/qtbase.git
git checkout 5.13.1
git checkout 5.13.1
mkdir -p ~/workspaces/qt/build/qtbase
mkdir -p ~/workspaces/raspberrypi-raspbian/qt/build/qtbase
cd ~/workspaces/qt/build/qtbase
cd ~/workspaces/raspberrypi-raspbian/qt/build/qtbase
~/workspaces/qt/qt5/qtbase/configure -release -opengl es2 -device linux-rasp-pi3-vc4-g++ \
~/workspaces/qt/qt5/qtbase/configure -release -opengl es2 -device linux-rasp-pi3-vc4-g++ \
-device-option CROSS_COMPILE=~/workspaces/raspberrypi-raspbian/toolchain/toolchain/bin/arm-linux-gnueabihf- \
    -device-option CROSS_COMPILE=~/workspaces/raspberrypi-raspbian/toolchain/toolchain/bin/arm-linux-gnueabihf- \
-opensource -confirm-license -nomake tests -nomake examples -verbose -no-pch -eglfs -xcb \
    -opensource -confirm-license -nomake tests -nomake examples -verbose -no-pch -eglfs -xcb \
-sysroot /home/stefan/workspaces/raspberrypi-raspbian/sysroot \
    -sysroot /home/stefan/workspaces/raspberrypi-raspbian/sysroot \
-prefix /usr/local/qt/5.13 \
    -prefix /usr/local/qt/5.13 \
-extprefix /opt/qt/5.13/raspbian/sysroot \
    -extprefix /opt/qt/5.13/raspbian/sysroot \
-hostprefix /opt/qt/5.13/raspbian
    -hostprefix /opt/qt/5.13/raspbian
 
make
make
make install
make install
</code>
</syntaxhighlight>


* compile qtdeclartive and install
* Compile qtdeclarative and install it:<syntaxhighlight>
 
cd ~/workspaces/raspberrypi-raspbian/qt/qt5
<code lang="bash">
cd ~/workspaces/qt/qt5
git clone git://code.qt.io/qt/qtdeclarative.git
git clone git://code.qt.io/qt/qtdeclarative.git
git checkout 5.13.1
git checkout 5.13.1
mkdir -p ~/workspaces/qt/build/qtdeclarative
mkdir -p ~/workspaces/raspberrypi-raspbian/qt/build/qtdeclarative
cd ~/workspaces/qt/build/qtdeclarative
cd ~/workspaces/qt/build/qtdeclarative
/opt/qt/5.13/raspbian/bin/qmake ~/workspaces/qt/qt5/qtdeclarative
/opt/qt/5.13/raspbian/bin/qmake ~/workspaces/qt/qt5/qtdeclarative
make
make
make install
make install
</code>
</syntaxhighlight>
 
* compile qtwebengine and install


<code lang="bash">
* Compile qtwebengine and install it:<syntaxhighlight>
cd ~/workspaces/qt/qt5
cd ~/workspaces/raspberrypi-raspbian/qt/qt5
git clone git://code.qt.io/qt/qtwebengine.git
git clone git://code.qt.io/qt/qtwebengine.git
git submodule init
git submodule init
git checkout 5.13.1
git checkout 5.13.1
git submodule update
git submodule update
mkdir -p ~/workspaces/qt/build/qtwebengine
mkdir -p ~/workspaces/raspberrypi-raspbian/qt/build/qtwebengine
cd ~/workspaces/qt/build/qtwebengine
cd ~/workspaces/raspberrypi-raspbian/qt/build/qtwebengine
/opt/qt/5.13/raspbian/bin/qmake ~/workspaces/qt/qt5/qtwebengine
/opt/qt/5.13/raspbian/bin/qmake ~/workspaces/qt/qt5/qtwebengine -- --no-feature-webengine-arm-thumb
make
make
make install
make install
</code>
</syntaxhighlight>
 
* Compile the Simple Browser example:<syntaxhighlight>
mkdir -p ~/workspaces/raspberrypi-raspbian/qt/build/simplebrowser
cd ~/workspaces/raspberrypi-raspbian/qt/build/simplebrowser
/opt/qt/5.13/raspbian/bin/qmake ~/workspaces/qt/qt5/qtwebengine/examples/webenginewidgets/simplebrowser
make
</syntaxhighlight>


* compile simple browser
==Deploy==


<code lang="bash">
We still have our image mounted form the sysroot step. If you chose to rsync sysroot over the network, just replace the rsync steps below with
mkdir -p ~/workspaces/qt/build/simplebrowser
the equivalent network location of your Rasberry Pi board.
cd ~/workspaces/qt/build/simplebrowser
/opt/qt/5.13/raspbian/bin/qmake ~/workspaces/qt/qt5/qtwebengine/examples/widget/simplebrowser
make
</code>


=Deploy=
* Deploy with rsync<syntaxhighlight>
mkdir -p  /media/card/usr/local/qt/5.13
rsync -av /opt/qt/5.13/raspbian/sysroot/ /media/card/usr/local/qt/5.13
cp ~/workspaces/raspberrypi-raspbian/qt/build/simplebrowser/simplebrowser /media/card/usr/local/bin/
</syntaxhighlight>


We still have our image mounted form sysroot step , in case you preferred to rsync sysroot over network, just replace rsync setps below with
* Unmount the image<syntaxhighlight>
equivalent network location of your rasberrypi board.
umount /media/card
</syntaxhighlight>


* deploy with rsync
* Copy the image to the SD card (replace sdX with the device on your machine):<syntaxhighlight>
cd ~/workspaces/raspberrypi-raspbian/image
dd if=2019-04-08-raspbian-stretch.img of=/dev/sdX bs=4M
</syntaxhighlight>


<code lang="bash">
* Boot the image up, and switch to enable OpenGL (Full KMS):<syntaxhighlight>
rsync -avz /opt/qt/5.13/raspbian/sysroot/ /media/card/usr/local/qt/5.13
raspi-config
cp ~/workspaces/qt/build/simplebrowser/simplebrowser /media/card
</syntaxhighlight>
</code>


* umount image
[[File:Opengl kms.png]]


<code lang="bash">
umount /media/card/
</code>


* first lets extract Raspbian on sd card sdX (replace sdX with proper device on your machine)
* Fix run-time linker search paths<syntaxhighlight>
echo /usr/local/qt/5.13/lib > /etc/ld.so.conf.d/00-qt.5.13.conf
ldconfig
</syntaxhighlight>
* Reboot
* To run Simple Browser within Raspbian Desktop (former PIXEL Desktop) open console or SSH:<syntaxhighlight>
export DISPLAY=:0
export QTWEBENGINE_DISABLE_GPU_THREAD=1
/usr/local/bin/simplebrowser -platform xcb
</syntaxhighlight>


<code lang="bash">
* Navigate to chrome://gpu/, and you should see:
cd ~/workspaces/raspberrypi-raspbian/image
dd if=2019-04-08-raspbian-stretch.img of=/dev/sdX bs=4M
</code>


* boot it up, and switch to opengl kms module by running
[[File:Gpu.png]]


<code lang="bash">
* Navigate to https://get.webgl.org/, and you should see:
raspi-config
</code>


* run simple browser
[[File:Webgl.png]]


<code lang="bash">
* To run without x11 , SSH to the device and shut down the login manager:<syntaxhighlight>
export DISPLAY=:0
systemctl stop lightdm
export QTWEBENGINE_DISABLE_GPU_THREAD=1
export QTWEBENGINE_DISABLE_GPU_THREAD=1
./simplebrowser -platform xcb
/usr/local/bin/simplebrowser -platform eglfs
</code>
</syntaxhighlight>

Latest revision as of 14:09, 4 January 2024

This page describes how to set up self-compiled Qt5 WebEngine on Raspberry Pi 3 running Raspbian Stretch with WebGL support using VC4 open source drivers.

To see other guides visit:

Setup

The setup is tested on Rasberry Pi 3 model B. We'll use the latest open source VC4 Gallium3D driver instead of the old closed source binaries from Broadcom. We cannot use the Broadcom toolchain to compile Qt 5.13.2. and Qt WebEngine, because it uses the GCC compiler version 4.8, and we'll need at least version 5.0.

Raspbian Stretch ships with Binutils 2.28, GCC 6.3.0 and GlibC 2.24. Since we would like to use the same GlibC version and try to avoid running into a lot of issues when trying to compiler older GlibC 2.24 with newer GCC, we are going to simply mirror the Raspbian setup and reuse the same versions as Raspbian ships. Therefore we'll start with downloading the sources and Raspbian image.

  • Let's create our workspace:
    mkdir -p ~/workspaces/raspberrypi-raspbian/image
    mkdir -p ~/workspaces/raspberrypi-raspbian/toolchain/sources
    mkdir -p ~/workspaces/raspberrypi-raspbian/qt/qt5
    
  • Let's now download archives:
    cd ~/workspaces/raspberrypi-raspbian/image
    wget https://downloads.raspberrypi.org/raspbian/images/raspbian-2019-04-09/2019-04-08-raspbian-stretch.zip
    cd ~/workspaces/raspberrypi-raspbian/toolchain/sources
    wget https://ftpmirror.gnu.org/binutils/binutils-2.28.tar.bz2
    wget https://ftpmirror.gnu.org/gcc/gcc-6.3.0/gcc-6.3.0.tar.gz
    tar xf gcc-6.3.0.tar.gz
    tar xf binutils-2.28.tar.bz2
    

Please note, most likely you would like to download the corresponding SHA1 to verify the archives.

Sysroot

To be able to compile things, we need a part of sysroot to be present on our build machine. As shown here, you could simply start your Raspbian on the board and then rsync required 'libs' and 'includes' to the host machine using the SSH connection. However, in this guide we will mount the image via a loop device, use qemu to install build dependencies and than make a local copy.

  Note: We need actually a local copy of 'libs' and 'headers' from the image, as we want to adjust the symlinks.

  • Let's extract the Raspbian image:
    cd ~/workspaces/raspberrypi-raspbian/image
    unzip 2019-04-08-raspbian-stretch.zip
    
  • Make loop devices for the image:
    losetup -fP 2019-04-08-raspbian-stretch.img
    losetup -a
    /dev/loop0: []: (~/raspberrypi-raspbian/image/2019-04-08-raspbian-stretch.img)
    
  • Mount the root partition:
    mount /dev/loop0p2 -t ext4 /media/card
    mount --bind /dev /media/card/dev
    mount --bind /sys /media/card/sys
    mount --bind /proc /media/card/proc
    mount --bind /dev/pts /media/card/dev/pts
    
  • We need qemu on the image to able to execute command, therefore copy static qemu binary to image.
    cp /usr/bin/qemu-arm /media/card/usr/bin/
    

  Note: Setup of qemu static interpreter is distribution specific. Please refer to your Linux distribution documentation.

  • Chroot to sysroot and get qt5 build dependencies in:
    cd /media/card/
    chroot . bin/bash
    # uncomment the deb-src line
    vi /etc/apt/sources.list
    apt update
    apt install devscripts    
    mk-build-deps libqt5gui5
    apt install ./qtbase-opensource-src-build-deps_5.7.1+dfsg-3+rpi1+deb9u1_armhf.deb
    apt install libnss3 libnss3-dev
    exit
    

  Note: We are going to use mk-build-deps to create dummy package, so we can uninstall dependencies when no longer needed.

  • rsync the parts that we need:
    cd ~/workspaces/raspberrypi-raspbian
    rsync -av /media/card/lib sysroot
    rsync -av /media/card/usr/include sysroot/usr
    rsync -av /media/card/usr/lib sysroot/usr
    
  • 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
    
  • Cleanup image (optional)
    cd /media/card/
    chroot . bin/bash
    apt remove devscripts qtbase-opensource-src-build-deps libnss3-dev
    apt autoremove
    apt clean
    exit
    
  • Umount no longer needed mounts:
    umount /media/card/sys /media/card/proc /media/card/dev/pts /media/card/dev
    
  • Detach loop device:
    losetup -d /dev/loop0
    

Toolchain

To compile Qt, we need a cross-compiler toolchain. There are many excellent tools to compile a toolchain, such as crosstool-ng or buildroot. However, we choose to compile GCC from scratch. Compiling a compiler is a bit tricky and includes a few tasks:

  • Installing Linux headers that are required to make system calls from the C library and to compile it
  • Building biuntils to get a cross-linker, a cross-assembler, and some other tools using your host compiler
  • Building the first stage GCC (bootstrapping), to have a basic compiler with C language support and static linking
  • Building the C library using the first stage compiler
  • Building a second stage GCC, which uses the C library, supports dynamic linking and the C++ language

We already have GlibC compiled in our sysroot shipped by Rasbian, so we are going to cheat here a bit and skip the bootstrapping of GCC and the building of GlibC itself. We can simply use sysroot directly and just compile the linker, the assembler and final cross-compiler.

  • Let's do initial setup:
    export WORKSPACE_ROOT=~/workspaces/raspberrypi-raspbian/toolchain
    export PREFIX=${WORKSPACE_ROOT}/toolchain
    export TARGET=arm-linux-gnueabihf
    export SYSROOT=${WORKSPACE_ROOT}/../sysroot
    export PATH=${PREFIX}/bin:$PATH
    mkdir -p ${PREFIX}
    cd ${WORKSPACE_ROOT}
    
  • Let's build the linker and assembler:
    mkdir -p build/binutils
    pushd build/binutils
    ../../sources/binutils-2.28/configure --target=${TARGET} --prefix=${PREFIX} --with-arch=armv6 --with-fpu=vfp --with-float=hard --disable-multilib
    make -j12
    make install
    popd
    
  • We need additional GMP, MPFR and MPC libraries to be able to build GCC. This can be easily set up by running script in the GCC source directory.
    cd ~/workspaces/raspberrypi-raspbian/toolchain/sources/gcc-6.3.0
    contrib/download_prerequisites
    
  • Let's now build GCC:
    mkdir -p build/gcc2
    pushd build/gcc2
    ../../sources/gcc-6.3.0/configure --prefix=${PREFIX} --target=${TARGET} --with-sysroot=${SYSROOT} --enable-languages=c,c++ --disable-multilib --enable-multiarch --with-arch=armv6 --with-fpu=vfp --with-float=hard
    make -j12
    make install
    popd
    

Note that I got a compiler error, so you might have to edit raspberrypi-raspbian/toolchain/sources/gcc-6.3.0/gcc/ubsan.c line 1474 and change it to:

|| xloc.file[0] == '\0' || xloc.file[0] == '\xff'

Compiling Qt

As shown here, we could do a top level build of Qt, but we are going to do prefix module builds just to show an alternative way of building Qt. We need three repositories to have Qt WebEngine up and running: qtbase, qtdeclarative and qtwebengine. It is important to configure Qt with linux-rasp-pi3-vc4-g++ device, since this spec contains newer vc4 OpenGL drivers. We also compile two back-ends for QPA: xcb to run it in the Rasbian window manager and eglfs to run as a full-screen single-window application.

  • Let's configure qtbase, compile it and install it:
    cd ~/workspaces/raspberrypi-raspbian/qt/qt5
    git clone git://code.qt.io/qt/qtbase.git
    git checkout 5.13.1
    mkdir -p ~/workspaces/raspberrypi-raspbian/qt/build/qtbase
    cd ~/workspaces/raspberrypi-raspbian/qt/build/qtbase
    ~/workspaces/qt/qt5/qtbase/configure -release -opengl es2 -device linux-rasp-pi3-vc4-g++ \
        -device-option CROSS_COMPILE=~/workspaces/raspberrypi-raspbian/toolchain/toolchain/bin/arm-linux-gnueabihf- \
        -opensource -confirm-license -nomake tests -nomake examples -verbose -no-pch -eglfs -xcb \
        -sysroot /home/stefan/workspaces/raspberrypi-raspbian/sysroot \
        -prefix /usr/local/qt/5.13 \
        -extprefix /opt/qt/5.13/raspbian/sysroot \
        -hostprefix /opt/qt/5.13/raspbian
    make
    make install
    
  • Compile qtdeclarative and install it:
    cd ~/workspaces/raspberrypi-raspbian/qt/qt5
    git clone git://code.qt.io/qt/qtdeclarative.git
    git checkout 5.13.1
    mkdir -p ~/workspaces/raspberrypi-raspbian/qt/build/qtdeclarative
    cd ~/workspaces/qt/build/qtdeclarative
    /opt/qt/5.13/raspbian/bin/qmake ~/workspaces/qt/qt5/qtdeclarative
    make
    make install
    
  • Compile qtwebengine and install it:
    cd ~/workspaces/raspberrypi-raspbian/qt/qt5
    git clone git://code.qt.io/qt/qtwebengine.git
    git submodule init
    git checkout 5.13.1
    git submodule update
    mkdir -p ~/workspaces/raspberrypi-raspbian/qt/build/qtwebengine
    cd ~/workspaces/raspberrypi-raspbian/qt/build/qtwebengine
    /opt/qt/5.13/raspbian/bin/qmake ~/workspaces/qt/qt5/qtwebengine -- --no-feature-webengine-arm-thumb
    make
    make install
    
  • Compile the Simple Browser example:
    mkdir -p ~/workspaces/raspberrypi-raspbian/qt/build/simplebrowser
    cd ~/workspaces/raspberrypi-raspbian/qt/build/simplebrowser
    /opt/qt/5.13/raspbian/bin/qmake ~/workspaces/qt/qt5/qtwebengine/examples/webenginewidgets/simplebrowser
    make
    

Deploy

We still have our image mounted form the sysroot step. If you chose to rsync sysroot over the network, just replace the rsync steps below with the equivalent network location of your Rasberry Pi board.

  • Deploy with rsync
    mkdir -p  /media/card/usr/local/qt/5.13
    rsync -av /opt/qt/5.13/raspbian/sysroot/ /media/card/usr/local/qt/5.13
    cp ~/workspaces/raspberrypi-raspbian/qt/build/simplebrowser/simplebrowser /media/card/usr/local/bin/
    
  • Unmount the image
    umount /media/card
    
  • Copy the image to the SD card (replace sdX with the device on your machine):
    cd ~/workspaces/raspberrypi-raspbian/image
    dd if=2019-04-08-raspbian-stretch.img of=/dev/sdX bs=4M
    
  • Boot the image up, and switch to enable OpenGL (Full KMS):
    raspi-config
    

Opengl kms.png


  • Fix run-time linker search paths
    echo /usr/local/qt/5.13/lib > /etc/ld.so.conf.d/00-qt.5.13.conf
    ldconfig
    
  • Reboot
  • To run Simple Browser within Raspbian Desktop (former PIXEL Desktop) open console or SSH:
    export DISPLAY=:0
    export QTWEBENGINE_DISABLE_GPU_THREAD=1
    /usr/local/bin/simplebrowser -platform xcb
    
  • Navigate to chrome://gpu/, and you should see:

Gpu.png

Webgl.png

  • To run without x11 , SSH to the device and shut down the login manager:
    systemctl stop lightdm
    export QTWEBENGINE_DISABLE_GPU_THREAD=1
    /usr/local/bin/simplebrowser -platform eglfs