Konfigurieren Sie ein Embedded Linux Gerät
Die Cross-Kompilierung von Qt für ein bestimmtes Gerät erfordert eine Toolchain und eine Sysroot. Es wird erwartet, dass die Toolchain eine Version des gcc oder eines anderen Compilers und zugehörige Werkzeuge für die Cross-Kompilierung enthält. Das bedeutet, dass diese Tools auf dem Host-System (in der Regel x64) ausgeführt werden, während sie Binärdateien für die Zielarchitektur (z. B. 32- oder 64-Bit-ARM) erzeugen. Die Sysroot enthält die Header und Bibliotheken für das Zielsystem, was das Kompilieren und Linken von Bibliotheken und Anwendungen auf dem Hostsystem ermöglicht.
Diese Übersichtsseite beschreibt den generischen Ansatz, bei dem keine Distributionserstellungssysteme wie Yocto oder Buildroot verwendet werden. Es ist immer möglich, Qt auf einem Gerät zu kompilieren und einzusetzen, solange eine geeignete Toolchain und Sysroot verfügbar sind.
Warnung: Diese Seite kann nur einen generischen, allgemeinen Überblick geben. Es gibt eine große Anzahl von Details, die je nach Build-Umgebung, Zielgerät und Toolchain variieren können. Im Zweifelsfall sollten Sie sich an Ihren Systemintegrator wenden. Vorgefertigte Referenz-Images und SDKs finden Sie im Boot to Qt Angebot.
Wenn Sie Qt-basierte Anwendungen ohne ein Windowing-System wie X11 oder Wayland ausführen, benötigen einige Geräte herstellerspezifischen Anpassungscode für EGL- und OpenGL ES-Unterstützung. Dieser wird in Form von Backends für das EGLFS-Plattform-Plugin bereitgestellt. Dies ist nicht relevant für nicht-beschleunigte Plattformen, wie z.B. solche, die das LinuxFB-Plattform-Plugin verwenden, das nur für softwarebasiertes Rendering gedacht ist. Ab Qt 6 verwenden viele eingebettete Systeme drm, um einen Videomodus zu setzen, Display-Konnektoren und grafische Oberflächen zu verwalten. Beispielsweise verwenden ein NXP i.MX8-basiertes Gerät oder ein Raspberry Pi 4 diesen Ansatz, und daher ist das am häufigsten verwendete Backend für EGLFS eglfs_kms, das EGL- und OpenGL ES-basiertes Rendering mit drm
ermöglicht und gbm
für Oberflächen- und Puffermanagement verwendet. Ältere Geräte, wie z.B. der NXP i.MX6, verwenden weiterhin den alten, GPU-Hersteller-spezifischen Ansatz, um EGL-Fensteroberflächen mit dem Framebuffer zu verbinden, unter Verwendung von speziellen eglfs-Backends, wie z.B. eglfs_viv
.
Hinweis: Beachten Sie, dass Qt nur eine Komponente im Software-Stack für ein Embedded-Gerät ist. Insbesondere wenn es um beschleunigte Grafik geht, erwartet Qt einen funktionierenden Grafik-Stack mit einer entsprechenden Konfiguration für die Userspace- und Kernel-Komponenten, wie z.B. den Display-Treiber. Diese Komponenten liegen außerhalb der Domäne von Qt, und es liegt in der Verantwortung des Systemintegrators, sicherzustellen, dass das Basissystem voll funktionsfähig und optimal ist, einschließlich beschleunigter Grafik.
Weitere Informationen zur Grafik- und Eingabekonfiguration für Embedded Linux Systeme finden Sie in Qt for Embedded Linux.
Toolchain-Dateien versus Geräte-Makespecs
In Qt 5 verwenden Sie typischerweise ein Device Spec unter dem Verzeichnis qtbase/mkspecs/devices. Diese enthalten die entsprechenden Compiler- und Linker-Flags für ein bestimmtes Gerät und stellen auch sicher, dass die korrekten EGL- und OpenGL ES-Bibliotheken abgeholt werden, falls sie sich an einem nicht standardmäßigen Ort in der Sysroot befinden.
Sie könnten zum Beispiel einen Qt 5 Build für einen Raspberry Pi 2 mit einem configure-Befehl wie dem folgenden konfiguriert haben:
./configure -release -opengl es2 -device linux-rasp-pi2-g++ -device-option CROSS_COMPILE=$TOOLCHAIN/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- -sysroot $ROOTFS -prefix /usr/local/qt5
Hinweis: configure verwendet immer das Ninja Generator- und Build-Tool, wenn eine ninja
ausführbare Datei verfügbar ist. Ninja ist plattformübergreifend, funktionsreich, leistungsfähig und wird für alle Plattformen empfohlen. Die Verwendung anderer Generatoren kann funktionieren, wird aber nicht offiziell unterstützt.
Mit Qt 6 und CMake ist dieser Ansatz allein nicht mehr ausreichend. Stattdessen muss eine CMake-Toolchain-Datei bereitgestellt werden, bevor die Konfiguration erfolgen kann. In dieser Datei erfolgt die Anpassung in Bezug auf Compiler- und Linker-Flags sowie toolchain- und sysroot-spezifische Eigenheiten.
In den folgenden Abschnitten wird eine Toolchain-Datei vorgestellt, die in vielen Fällen mit minimalen Anpassungen verwendet werden kann. Sie basiert auf dem Ansatz, der in diesem Blogbeitrag vorgestellt wurde.
Hinweis: Bei der unten vorgestellten Toolchain-Datei handelt es sich um ein Beispiel, das häufig weitere Anpassungen für ein bestimmtes Gerät erfordert. Benutzern und Systemintegratoren steht es außerdem frei, ihre eigenen Toolchain-Dateien auf jede erdenkliche Weise zu erstellen.
Während CMake das einzige unterstützte Build-System für die Erstellung von Qt selbst ist, können Anwendungen in Qt 6.0 weiterhin mit qmake
erstellt werden. Um ein qmake
Setup zu erhalten, das mit Cross-Compilation funktioniert, muss man einige der Legacy-Argumente für CMake oder configure angeben.
Host-Werkzeuge
Die Cross-Kompilierung von Qt setzt voraus, dass ein Host-Build von Qt verfügbar ist. Während des Builds werden Werkzeuge wie moc
, rcc
, qmlcachegen
, qsb
und andere von dort aus aufgerufen. Wenn man zum Beispiel auf einem x64-Rechner für ARM crosskompiliert, muss zuerst ein lokaler x64-Build der gleichen Qt-Version zur Verfügung gestellt werden. Der Pfad zu diesem Qt-Build wird dann an configure oder cmake übergeben.
Qt konfigurieren
Nehmen wir an, dass die folgenden Dinge vorhanden sind:
- eine Toolchain und sysroot unter
$HOME/rpi-sdk
, - ein Checkout von Qt, mindestens das qtbase-Modul, unter
$HOME/qt-cross
, - ein Host-Build von Qt unter
$HOME/qt-host
.
Darüber hinaus muss vor der Konfiguration Folgendes entschieden werden:
- Wo wird der Qt-Build auf dem lokalen System installiert, sobald der Build abgeschlossen ist? In diesem Beispiel verwenden wir
$HOME/qt6-rpi
. - Wo wird der Qt-Build auf dem Gerät bereitgestellt? In diesem Beispiel verwenden wir
/usr/local/qt6
.
Im Beispiel verwenden wir ein Raspberry Pi 4 SDK (toolchain+sysroot), das über Yocto generiert wurde, aber die Anweisungen hier sind völlig allgemein gehalten und hängen nicht von Yocto ab. Die Schritte sind die gleichen mit jeder anderen Toolchain und Sysroot, sobald die Toolchain-Datei mit dem korrekten Cross-Compiler und anderen Pfaden aktualisiert wird.
Nach dem Erstellen und Wechseln in ein build
Verzeichnis:
$HOME/qt-cross/qtbase/configure -release -opengl es2 -nomake examples -nomake tests \ -qt-host-path $HOME/qt-host \ -extprefix $HOME/qt6-rpi \ -prefix /usr/local/qt6 \ -- -DCMAKE_TOOLCHAIN_FILE=$HOME/qt-cross/toolchain.cmake
In der Praxis ist dieser configure-Befehl gleichbedeutend mit dem folgenden direkten CMake-Aufruf:
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DINPUT_opengl=es2 -DQT_BUILD_EXAMPLES=OFF -DQT_BUILD_TESTS=OFF \ -DQT_HOST_PATH=$HOME/qt-host \ -DCMAKE_STAGING_PREFIX=$HOME/qt6-rpi \ -DCMAKE_INSTALL_PREFIX=/usr/local/qt6 \ -DCMAKE_TOOLCHAIN_FILE=$HOME/qt-cross/toolchain.cmake \ $HOME/qt-cross/qtbase
Mit der entsprechenden Toolchain-Datei reicht dies aus, um einen Qt-Build zu erzeugen, der es dann ermöglicht, Anwendungen mit CMake zu bauen. Damit Anwendungen auch mit qmake
gebaut werden können, müssen zusätzlich zu den oben genannten Argumenten die Qt 5 style device spec und device options angegeben werden:
$HOME/qt-cross/qtbase/configure ... ... -device linux-rasp-pi4-v3d-g++ \ -device-option CROSS_COMPILE=$HOME/rpi_sdk/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi- \ -device-option DISTRO_OPTS="hard-float" \ ...
Standardmäßig werden beim Cross-Kompilieren nur die Qt-Bibliotheken und -Tools gebaut, die auf dem Zielgerät laufen sollen. Build-bezogene Werkzeuge wie moc
und uic
werden nicht gebaut. Die Erstellung solcher Tools kann durch Setzen von QT_FORCE_BUILD_TOOLS
auf ON
aktiviert werden.
Hinweis: Wenn QT_FORCE_BUILD_TOOLS
aktiviert ist, werden die Ziel-Binärdateien von Tools wie qmake
in den Bereitstellungsspeicherort installiert. Wenn qmake
zur Erstellung von Anwendungen verwendet wird, rufen Sie daher stattdessen das Skript host-qmake
auf.
Sobald die Konfiguration ohne Fehler abgeschlossen ist, führen Sie cmake --build . --parallel
zum Erstellen aus. Nach der Erstellung führen Sie cmake --install .
aus, um die Ergebnisse auf $HOME/qt6-rpi
zu installieren. Von dort aus kann der Qt-Build mit rsync, scp oder einer anderen Methode auf dem Gerät bereitgestellt werden.
Wenn Sie einzelne Qt-Module bauen, können Sie das Skript qt-configure-module
aus dem Verzeichnis bin
der Staging Location (im Beispiel$HOME/qt6-rpi
) verwenden, um zusätzliche Module wie qtdeclarative, qtquick3d usw. zu konfigurieren. Sie können dann mit cmake --build .
gebaut und in den Staging-Speicherort installiert werden, indem Sie cmake --install .
Hinweis: Bevor Sie mit dem Build beginnen, sollten Sie die Ausgabe des Konfigurationsschritts immer sorgfältig prüfen: Sind alle erwarteten Funktionen aktiviert? Die Erstellung eines Builds und dessen Bereitstellung auf dem Gerät ist sinnlos, wenn wesentliche Funktionen zur Konfigurationszeit nicht aktiviert sind.
Wenn beispielsweise eine beschleunigte Grafik über OpenGL gewünscht ist, sollten Sie besonders auf die folgenden Funktionen achten:
EGL .................................... yes OpenGL: Desktop OpenGL ....................... no OpenGL ES 2.0 ........................ yes OpenGL ES 3.0 ........................ yes ... evdev .................................. yes libinput ............................... yes ... EGLFS .................................. yes EGLFS details: EGLFS OpenWFD ........................ no EGLFS i.Mx6 .......................... no EGLFS i.Mx6 Wayland .................. no EGLFS RCAR ........................... no EGLFS EGLDevice ...................... yes EGLFS GBM ............................ yes EGLFS VSP2 ........................... no EGLFS Mali ........................... no EGLFS Raspberry Pi ................... no EGLFS X11 ............................ no LinuxFB ................................ yes
Beim Beispiel des Raspberry Pi 4 erwarten wir, dass EGL, OpenGL ES und EGLFS GBM
alle als yes
gemeldet werden, andernfalls werden das EGLFS-Plattform-Plugin und sein eglfs_kms-Backend auf dem Gerät nicht funktionieren. Um Maus-, Tastatur- und Berührungseingaben zu erhalten, muss entweder evdev
oder libinput
aktiviert sein.
Wenn X11 als Fenstersystem (oder eines der Fenstersysteme) auf dem Gerät verwendet werden soll, muss sichergestellt werden, dass die xcb- und X11-bezogenen Funktionen als yes
markiert sind.
Ein Beispiel für eine Toolchain-Datei
Wir gehen davon aus, dass unter $HOME/rpi-sdk
eine Sysroot- und Toolchain vorhanden ist. TARGET_SYSROOT
und CROSS_COMPILER
müssen an die verwendete Toolchain und Sysroot angepasst werden. Das Beispiel hier ist nur für ein bestimmtes, von Yocto generiertes SDK geeignet. Das gleiche gilt für CMAKE_C_COMPILER
und CMAKE_CXX_COMPILER
.
Wir verlassen uns nicht auf irgendwelche Wrapper-Skripte, die Umgebungsvariablen wie PKG_CONFIG_* bereitstellen würden. Vielmehr wird der Pfad zu den .pc-Dateien in der Toolchain-Datei angegeben. Es ist wahrscheinlich, dass eine andere Sysroot in PKG_CONFIG_LIBDIR
angepasst werden muss. Bei einer Sysroot, die aus einem Raspberry Pi OS (ehemals Raspbian) Image erzeugt wurde, würde man stattdessen /usr/lib/arm-gnueabihf/pkgconfig
verwenden.
Die Compiler- und Linker-Flags sind im Beispiel nicht optimal erforderlich. Passen Sie sie nach Bedarf an das Zielgerät an.
Weitere Informationen zu den CMake-Spezifika in der Beispiel-Toolchain-Datei finden Sie in diesem Blogbeitrag und in der CMake-Dokumentation.
cmake_minimum_required(VERSION 3.18) include_guard(GLOBAL) set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(TARGET_SYSROOT /home/user/rpi-sdk/sysroots/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi) set(CROSS_COMPILER /home/user/rpi-sdk/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi) set(CMAKE_SYSROOT ${TARGET_SYSROOT}) set(ENV{PKG_CONFIG_PATH} "") set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig) set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT}) set(CMAKE_C_COMPILER ${CROSS_COMPILER}/arm-poky-linux-gnueabi-gcc) set(CMAKE_CXX_COMPILER ${CROSS_COMPILER}/arm-poky-linux-gnueabi-g++) set(QT_COMPILER_FLAGS "-march=armv7-a -mfpu=neon -mfloat-abi=hard") set(QT_COMPILER_FLAGS_RELEASE "-O2 -pipe") set(QT_LINKER_FLAGS "-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed") 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) 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()
Erstellen von Anwendungen für das Zielgerät
Sobald der Qt-Build abgeschlossen und im Staging-Speicher installiert ist, können Beispiele oder Anwendungen erstellt werden.
Verwenden Sie mit CMake das generierte Skript qt-cmake
im Verzeichnis bin
des Bereitstellungsortes (im Beispiel$HOME/qt6-rpi
), um die Konfiguration vorzunehmen, und führen Sie dann ninja
aus. Ein Beispiel:
$HOME/qt6-rpi/bin/qt-cmake . cmake --build .
Das resultierende Anwendungsbinary kann dann auf dem Gerät bereitgestellt werden. Die Verwendung des qt-cmake
Hilfsskripts ist praktisch, da das Skript sicherstellt, dass die Toolchain-Datei, die zum Erstellen von Qt verwendet wurde, geladen wird, so dass sie nicht für jede Anwendung wiederholt angegeben werden muss.
Im Gegensatz zu Qt selbst wird das Erstellen von Anwendungen mit qmake in Qt 6.0 immer noch unterstützt, solange eine geeignete Gerätespezifikation vorhanden ist und die entsprechenden Legacy-Argumente bei der Konfiguration von Qt an CMake oder configure übergeben wurden. Wenn dies alles zutrifft, dann wird durch das Ausführen von qmake
und make
auch ein Anwendungsbinary für das Zielgerät erzeugt.
Standardwerte für Plattform-Plugins und EGLFS
Nach der Konfiguration wird ein Standard-Plattform-Plugin ausgewählt. Dieses wird verwendet, wenn eine Anwendung ohne das Argument -platform
gestartet wird und die Umgebungsvariable QT_QPA_PLATFORM
nicht gesetzt ist.
In ähnlicher Weise hat das EGLFS-Plattform-Plugin mehrere Backends. Das Standard-Backend wird auf der Grundlage der Verfügbarkeit und einer vordefinierten Prioritätsreihenfolge ausgewählt. Wenn drm und gbm verfügbar sind, wird als Standard das eglfs_kms-Backend verwendet. Dies kann zur Laufzeit durch Setzen der Umgebungsvariablen QT_QPA_EGLFS_INTEGRATION
jederzeit überschrieben werden.
Um diese Voreinstellungen für den Build zu ändern, ohne einen bestimmten Wert zur Laufzeit erzwingen zu müssen, sind die folgenden zwei CMake-Cache-Variablen verfügbar, nachdem CMake einmal ausgeführt wurde:
QT_QPA_DEFAULT_PLATFORM
(STRING
) - Der Name des Standard-Plattform-Plugins.QT_QPA_DEFAULT_EGLFS_INTEGRATION
(STRING
) - Das standardmäßige EGLFS-Backend.
Diese Variablen können auch innerhalb der Toolchain-Datei gesetzt werden.
Für weitere Informationen zur Konfiguration von Qt siehe Qt Configure Options.
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.