I have been asked to create a system that makes it easy to do cross-architecture Qt development with Debian Stretch.
The goal is this:
- Do development with Qt Creator, including remote debugging on the target architecture
- Compile using native code, to avoid running the compilers inside an emulator making the build slower
- Leverage all of Debian as development environment, using existing Debian packages for build-dependencies
- Set everything up just by installing a single
.debpackage, which ideally gives Qt Creator a new kit that just works
Now I'm trying to build on all that. I need to target Stretch so I cannot build on the recent improvements in Qt packaging, but I can at least use the experience that went into those changes.
This post has the notes from the first day of trying out different strategies.
I imported the two projects in Qt creator, installed their
and make sure they build for the current system, with the default kit, no
That works, good.
Now let's see about the rest:
dpkg --add-architecture armhf apt install crossbuild-essential-armhf
A cross-build kit for Qt Creator
I created a new
armhf kit for Qt Creator:
- Device type: Generic Linux Device
- Device: my hi-fi
- Sysroot: blank
- C compiler:
- C++ compiler:
- Qt version:
I ran qmake from Qt Creator and go this:
10:59:49: Starting: "/usr/lib/arm-linux-gnueabihf/qt5/bin/qmake" …/project.pro -spec linux-g++ CONFIG+=debug CONFIG+=qml_debug sh: 1: /usr/lib/arm-linux-gnueabihf/qt5/bin/rcc: not found 10:59:50: The process "/usr/lib/arm-linux-gnueabihf/qt5/bin/qmake" exited normally.
rcc is provided by
qtbase5-dev-tools, which cannot be coinstalled alongside
other architectures' version of itself:
# apt install qtbase5-dev-tools:armhf Reading package lists... Done Building dependency tree Reading state information... Done The following packages will be REMOVED: qtbase5-dev-tools The following NEW packages will be installed: qtbase5-dev-tools:armhf 0 upgraded, 1 newly installed, 1 to remove and 0 not upgraded. Need to get 651 kB of archives. After this operation, 985 kB disk space will be freed. Do you want to continue? [Y/n] q
I'll try with a very dirty hack:
# cd /usr/lib/arm-linux-gnueabihf/qt5/bin # ln -s `which rcc` . # ln -s `which uic` . # ln -s `which moc` . # ls -la total 1944 drwxr-xr-x 2 root root 4096 Nov 29 11:04 . drwxr-xr-x 7 root root 4096 Nov 28 17:05 .. lrwxrwxrwx 1 root root 12 Nov 29 11:04 moc -> /usr/bin/moc -rwxr-xr-x 1 root root 1982208 Jan 11 2017 qmake lrwxrwxrwx 1 root root 12 Nov 29 11:04 rcc -> /usr/bin/rcc lrwxrwxrwx 1 root root 12 Nov 29 11:04 uic -> /usr/bin/uic
This is ugly:
- It places files in
/usr/localthat are not maintained by the package manager
- It places amd64 executables in
/usr/lib/arm-linux-gnueabihfwhich should contain
Let's see what happens in Qt Creator:
11:14:35: Starting: "/usr/lib/arm-linux-gnueabihf/qt5/bin/qmake" …/project.pro -spec linux-g++ CONFIG+=debug CONFIG+=qml_debug 11:14:35: The process "/usr/lib/arm-linux-gnueabihf/qt5/bin/qmake" exited normally. 11:14:35: Starting: "/usr/bin/make" qmake_all make: Nothing to be done for 'qmake_all'. 11:14:36: The process "/usr/bin/make" exited normally.
11:15:29: Starting: "/usr/bin/make" g++ -c -pipe -std=c++11 -g -Wall -W -D_REENTRANT -fPIC -DQT_DEPRECATED_WARNINGS -DQT_QML_DEBUG -DQT_SVG_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I../project -I. -isystem /usr/include/arm-linux-gnueabihf/qt5 -isystem /usr/include/arm-linux-gnueabihf/qt5/QtSvg -isystem /usr/include/arm-linux-gnueabihf/qt5/QtWidgets -isystem /usr/include/arm-linux-gnueabihf/qt5/QtGui -isystem /usr/include/arm-linux-gnueabihf/qt5/QtCore -I. -I/usr/lib/arm-linux-gnueabihf/qt5/mkspecs/linux-g++ -o main.o ../project/main.cpp
Unfortunately, it is using
g++ even though I configured the kit to use
Trying an explicit override in the
QMAKE_CXX = /usr/bin/arm-linux-gnueabihf-g++ QMAKE_LINK = /usr/bin/arm-linux-gnueabihf-g++
And the project builds and runs fine on the Raspberry Pi, using a kit and two
simple overrides in the
.pro, all build dependencies as packaged by Debian,
and a toolchain that entirely runs on native code.
$ file /usr/lib/arm-linux-gnueabihf/qt5/bin/qmake /usr/lib/arm-linux-gnueabihf/qt5/bin/qmake: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=1f5b063926570702f5568b1e5cec6c70d214fc73, stripped $ dpkg-architecture -q DEB_HOST_ARCH amd64 $ /usr/lib/arm-linux-gnueabihf/qt5/bin/qmake -v QMake version 3.0 Using Qt version 5.7.1 in /usr/lib/arm-linux-gnueabihf
armhf code that runs happily on my
amd64 laptop because I
accidentally have qemu-user-static
This strategy produces results, although it depends on a dirty hack. To summarise it:
- Depend on
:armhfversions of Qt and all build-dependencies
- Symlink native
uicinto the armhf bin directory (argh!)
- Configure a kit as before
QMAKE_LINKin the .pro
Other things to investigate, besides removing the need for that dirty hack:
- Find out if there is a way to package and install a kit for Qt Creator
- Find out why qmake is ignoring the compiler settings from the kit and needs
overrides in the
.pro. Ideally the
.proshould be unmodified, so that it can be used for all builds
A native qmake
Would it be possible to build a native version of qmake tweaked to point to all the right bits out of the box?
$ apt source qtbase-opensource-src-5.7.1+dfsg $ qtbase-opensource-src-5.7.1+dfsg$ $ DEB_HOST_MULTIARCH=arm-linux-gnueabihf DEB_HOST_ARCH_BITS=32 debian/rules override_dh_auto_configure MAKEFLAGS="-j1" ./configure \ -confirm-license \ -prefix "/usr" \ -bindir "/usr/lib/arm-linux-gnueabihf/qt5/bin" \ -libdir "/usr/lib/arm-linux-gnueabihf" \ -docdir "/usr/share/qt5/doc" \ -headerdir "/usr/include/arm-linux-gnueabihf/qt5" \ -datadir "/usr/share/qt5" \ -archdatadir "/usr/lib/arm-linux-gnueabihf/qt5" \ -plugindir "/usr/lib/arm-linux-gnueabihf/qt5/plugins" \ -importdir "/usr/lib/arm-linux-gnueabihf/qt5/imports" \ -translationdir "/usr/share/qt5/translations" \ -hostdatadir "/usr/lib/arm-linux-gnueabihf/qt5" \ -sysconfdir "/etc/xdg" \ -examplesdir "/usr/lib/arm-linux-gnueabihf/qt5/examples" \ -opensource \ -plugin-sql-mysql \ -plugin-sql-odbc \ -plugin-sql-psql \ -plugin-sql-sqlite \ -no-sql-sqlite2 \ -plugin-sql-tds \ -system-sqlite \ -platform linux-g++ \ -system-harfbuzz \ -system-zlib \ -system-libpng \ -system-libjpeg \ -system-doubleconversion \ -openssl \ -no-rpath \ -verbose \ -optimized-qmake \ -dbus-linked \ -no-strip \ -no-separate-debug-info \ -qpa xcb \ -xcb \ -glib \ -icu \ -accessibility \ -compile-examples \ -no-directfb \ -gstreamer 1.0 \ -plugin-sql-ibase -opengl desktop \ … $ file bin/qmake bin/qmake: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=ba868730cf34c54d7ddf6df0ab4b6ce5c7d6f2a0, not stripped $ bin/qmake -v QMake version 3.0 Using Qt version 5.7.1 in /usr/lib/arm-linux-gnueabihf
./configure in Qt builds
qmake, and there is no need to run make
DEB_HOST_ARCH_BITS=32 is a hack I added to avoid
-platform linux-g++-64 instead of
Let's try to use that in Qt Creator:
sudo cp bin/qmake /usr/local/bin/qmake-arm-linux-gnueabihf
Qt Creator autodetects the new qmake and offers it as one of the available versions of Qt. Nice.
The need for the symlink hack is still there:
11:46:51: Starting: "/usr/local/bin/qmake-arm-linux-gnueabihf" ../project.pro -spec linux-g++-64 CONFIG+=debug CONFIG+=qml_debug sh: 1: /usr/lib/arm-linux-gnueabihf/qt5/bin/rcc: not found
So is the need for the
QMAKE_LINK overrides in the .pro.
Still, this way I could remove
qemu-user-static from my system and the
project still builds on my laptop and runs on my Raspberry Pi.
qemu dependency is not needed anymore, the rest of the problems still
stand. I wonder, since I'm rebuilding
qmake, if there's a way to tell it to
use the compilers I want, and the tools I want, removing the need for the dirty
hack and the overrides in the
How about the other project that depends on
# apt install qtwebengine5-dev qtwebengine5-dev:armhf Reading package lists... Done Building dependency tree Reading state information... Done qtwebengine5-dev is already the newest version (5.7.1+dfsg-6.1). Some packages could not be installed. This may mean that you have requested an impossible situation or if you are using the unstable distribution that some required packages have not yet been created or been moved out of Incoming. The following information may help to resolve the situation: The following packages have unmet dependencies: qtwebengine5-dev:armhf : Depends: libqt5webengine5:armhf (= 5.7.1+dfsg-6.1) but it is not going to be installed Depends: libqt5webenginecore5:armhf (= 5.7.1+dfsg-6.1) but it is not going to be installed Depends: libqt5webenginewidgets5:armhf (= 5.7.1+dfsg-6.1) but it is not going to be installed E: Unable to correct problems, you have held broken packages.
It turns out that something in the big chain of dependencies of qtwebengine5-dev makes the amd64 and armhf versions not coinstallable.
It seems that I have to abandon the idea of installing armhf build-dependencies in the main development system, and I need to start considering to leave the host system untouched to do the native builds, and use a chroot for the cross-compilers and the cross-build-dependencies.
In the next post, I'll see how that goes.
This has been done as part of my work with Truelite.