This is part of a series of posts on compiling a custom version of Qt5 in order to develop for both amd64 and a Raspberry Pi.
I split building Qt5 for armhf development in two parts: one cross-build
environment to be installed on amd64
develpment systems, and a runtime part
to be installed on the target armhf
hardware.
Building a Qt5 cross-building environment builds a mix of armhf
and amd64
binares: the amd64 tools to use for cross-building, like moc
, qmake
,
plugins for Qt Creator, and so on; armhf headers and libraries to use at
cross-build time; armhf shared libraries to use at runtime.
The procedure I came up with builds a devel package for amd64
development
machines, which contains everything, and a second package that extracts from it
only what is needed at runtime.
The cross-build environment is coinstallable both with the version of Qt distributed with Debian, and with the amd64 custom Qt development package.
The current build is sadly using -skip qtwebengine
, because I have had no
success so far getting QtWebEngine to compile as part of a cross-build Qt
setup (the last road bump I can't overcome is nss and nspr not being
coinstallable on amd64 and armhf, while both seem to be needed for it).
The resulting packaging is at https://github.com/Truelite/qt5custom.
Set up sources
Open the source tarball, and add the amd64 packaging:
tar axf qt-everywhere-src-5.15.0.tar.xz
cp -a debian-cross qt-everywhere-src-5.15.0/debian
If needed, install the Qt license:
cp qt-license.txt ~/.qt-license
If debugging information are not needed in armhf
development, remove
--no-strip
from ./configure
invocation in the rules
file, to build
significantly smaller .deb
packages.
Install build dependencies
Install cross-compilers:
dpkg --add-architecture armhf
apt install crossbuild-essential-armhf
You can use apt build-dep
to install dependencies manually:
cd qt-everywhere-src-5.15.0
apt build-dep .
apt -a armhf build-dep .
Alternatively, you can create installable .deb
metapackages that depends on
the build dependencies:
apt install devscripts
mk-build-deps --host-arch amd64 debian-cross/control
mk-build-deps --host-arch armhf debian-cross/control
apt -f install qt-everywhere-cross-build-deps_5.15.0-1_amd64.deb qt-everywhere-cross-cross-build-deps_5.15.0-1_armhf.deb
Note that there are two sets of dependencies: one of amd64
packages, and one
of armhf
packages.
Building the cross-build environment
After installing the build dependencies, you can build like this:
cd qt-everywhere-src-5.15.0
fakeroot debian/rules binary
In debian/rules
you can configure NUMJOBS
with the number of available
CPUs in the machine, to have parallel builds.
This will build a package with the cross-build development environment for
amd64
, called qtbase5custom-armhf-dev
Building the runtime environment
To generate the runtime package for armhf
, one needs to have the cross-build
package (qtbase5custom-armhf-dev
) installed in the system together with its
build dependencies.
At that point, the armhf
runtime package can be built using the
debian-armhf
directory without further sources:
apt install crossbuild-essential-armhf debhelper qtbase5custom-armhf-dev*_amd64.deb qt-everywhere-src-cross-build-deps*_armhf.deb
mkdir runtime
cp -a debian-armhf runtime/debian
cd runtime
dpkg-buildpackage -a armhf
Building the runtime environment generates:
- a
libqt5custom
package forarmhf
, installable on the target devices, containing the runtime Qt libraries and depending on the packages that they need to run; - a
libqt5custom-dbgym
package forarmhf
with debugging symbols, to use for debugging on the target hardware.
If, while generating the cross-build environment, --no-strip
was removed, the
libqtcustom-dbgsym
package with debugging symbols will not be generated.
Using the cross-build environment
These install their content in /opt
, and are coninstallable with the version
of Qt distributed in Debian, and with the custom Qt packages for amd64.
One needs to be careful not to create programs that link, either directly or indirectly, with more than one of these coinstalled Qt, because the in memory layout of objects could be different and incompatible, causing unexpected results.
Selecting which Qt version to use: qtchooser
These Qt custom packages integrate with qtchooser
to select the version of Qt
to use at compile time.
qtchooser --list-versions
lists available versions. One can choose what to
use by exporting QT_SELECT
:
# apt install qtchooser qt5-qmake qt5-default
$ qtchooser --list-versions
4
5
qt4-x86_64-linux-gnu
qt4
qt5-x86_64-linux-gnu
qt5
qt5custom-x86_64-linux-gnu
qt5custom
qt5custom-armhf-x86_64-linux-gnu
qt5custom-armhf
$ qmake --version
QMake version 3.1
Using Qt version 5.11.3 in /usr/lib/x86_64-linux-gnu
$ export QT_SELECT=qt5custom-armhf
$ qmake --version
QMake version 3.1
Using Qt version 5.15.0 in /opt/qt5custom-armhf/lib
Cross-building software using custom Qt
One just needs to export QT_SELECT=qt5custom-armhf
in the environment, then
proceed to build normally:
export QT_SELECT=qt5custom-armhf
fakeroot ./debian/rules clean binary
Or:
export QT_SELECT=qt5custom-armhf
qmake file.pro
If switching from one Qt to another, it is possible that the makefiles created by one qmake are not working well with the other. In that case, one can just remove them and regenerate them.
The build result is ready to be copied into, and run in, the target armhf
device.