Configurer un périphérique Linux embarqué
La compilation croisée de Qt pour un dispositif donné nécessite une chaîne d'outils et un sysroot. La chaîne d'outils est censée contenir une version de gcc, ou d'un autre compilateur, et des outils associés conçus pour la compilation croisée. Cela signifie que ces outils fonctionnent sur le système hôte (généralement x64), tout en produisant des binaires pour l'architecture cible (par exemple, 32 ou 64 bits ARM). Le sysroot contient les en-têtes et les bibliothèques pour le système cible, ce qui permet de compiler et de lier les bibliothèques et les applications sur l'hôte.
Cette page de présentation décrit l'approche générique, dans laquelle aucun système de construction de distribution, tel que Yocto ou Buildroot, n'est utilisé. Il est toujours possible d'effectuer une compilation croisée et de déployer Qt sur un périphérique tant qu'une chaîne d'outils et un sysroot appropriés sont disponibles.
Avertissement : Cette page ne peut fournir qu'une vue d'ensemble générique et de haut niveau. Il existe un grand nombre de détails qui peuvent varier en fonction de l'environnement de construction, de l'appareil cible et de la chaîne d'outils. En cas de doute, adressez-vous à votre intégrateur de système. Pour les images de référence et les SDK préconstruits, reportez-vous à l'offre Boot to Qt offre.
Lors de l'exécution d'applications basées sur Qt sans système de fenêtrage, tel que X11 ou Wayland, certains appareils nécessitent un code d'adaptation spécifique au fournisseur pour le support EGL et OpenGL ES. Ce code est fourni sous la forme de backends pour le plugin de plateforme EGLFS. Ceci n'est pas pertinent pour les plateformes non accélérées, telles que celles qui utilisent le plugin de plateforme LinuxFB, qui est destiné à un rendu basé sur le logiciel uniquement. Depuis Qt 6, de nombreux systèmes embarqués utilisent drm pour définir un mode vidéo, gérer les connecteurs d'affichage et les surfaces graphiques. Par exemple, un appareil basé sur NXP i.MX8 ou un Raspberry Pi 4 utiliseront cette approche, et donc le backend le plus couramment utilisé pour EGLFS est eglfs_kms, qui permet un rendu basé sur EGL et OpenGL ES avec drm, en utilisant gbm pour la gestion de la surface et de la mémoire tampon. Les appareils plus anciens, tels que l'i.MX6 de NXP, continueront à utiliser l'ancienne approche spécifique au fournisseur de GPU pour connecter les surfaces de fenêtres EGL au framebuffer, en utilisant des backends eglfs dédiés, tels que eglfs_viv.
Note : Soyez conscient que Qt n'est qu'un composant de la pile logicielle d'un appareil embarqué. En particulier lorsque des graphiques accélérés sont impliqués, Qt s'attend à une pile graphique fonctionnelle, avec une configuration appropriée pour l'espace utilisateur et les composants du noyau, tels que le pilote d'affichage. Ces composants ne relèvent pas du domaine de Qt, et il est de la responsabilité de l'intégrateur du système de s'assurer que le système de base est entièrement fonctionnel et optimal, y compris les graphiques accélérés.
Pour plus d'informations sur la configuration des graphiques et des entrées pour les systèmes Linux embarqués, reportez-vous à Qt pour Linux embarqué.
Fichiers de la chaîne d'outils et spécifications techniques des périphériques
Dans Qt 5, vous utilisez généralement une spécification de périphérique dans le répertoire qtbase/mkspecs/devices. Elles contiennent les drapeaux appropriés du compilateur et de l'éditeur de liens pour un certain périphérique, et s'assurent également que les bibliothèques EGL et OpenGL ES correctes sont récupérées, au cas où elles se trouveraient à un emplacement non standard dans le sysroot.
Par exemple, vous auriez pu configurer une version de Qt 5 pour un Raspberry Pi 2 avec une commande configure comme la suivante :
./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
Remarque : configure utilise toujours l'outil de génération et de construction Ninja si un exécutable ninja est disponible. Ninja est multiplateforme, riche en fonctionnalités, performant et recommandé sur toutes les plateformes. L'utilisation d'autres générateurs peut fonctionner mais n'est pas officiellement supportée.
Avec Qt 6 et CMake, cette approche n'est plus suffisante en soi. Un fichier CMake toolchain doit être fourni avant que la configuration puisse avoir lieu. C'est dans ce fichier que la personnalisation des drapeaux du compilateur et de l'éditeur de liens, ainsi que des bizarreries spécifiques à la chaîne d'outils et au sysroot, a lieu.
Dans les sections suivantes, nous présenterons un fichier de chaîne d'outils qui peut être utilisé dans de nombreux cas, avec une personnalisation minimale. Il est basé sur l'approche présentée dans ce billet de blog.
Remarque : le fichier de chaîne d'outils présenté ci-dessous est un exemple, qui nécessitera souvent une personnalisation plus poussée pour un appareil donné. Les utilisateurs et les intégrateurs de systèmes sont également libres de créer leurs propres fichiers de chaîne d'outils de la manière qu'ils jugent la plus appropriée.
Bien que CMake soit le seul système de construction pris en charge pour construire Qt lui-même, les applications peuvent toujours être construites à l'aide de qmake dans Qt 6.0. Afin d'obtenir une configuration de qmake qui soit fonctionnelle avec la compilation croisée, il faudra spécifier certains des anciens arguments à CMake ou à configure.
Outils de l'hôte
La compilation croisée de Qt nécessite la disponibilité d'une version hôte de Qt. Voir Compilation croisée de Qt pour plus de détails.
Configuration de Qt
Supposons que les éléments suivants soient disponibles :
- une chaîne d'outils et un sysroot sous
$HOME/rpi-sdk, - un checkout de Qt, au minimum le module qtbase, sous
$HOME/qt-cross, - une version hôte de Qt sur
$HOME/qt-host.
En outre, les points suivants doivent être décidés avant la configuration :
- Où la compilation de Qt sera-t-elle installée sur le système local une fois la compilation terminée ? Dans l'exemple, nous utiliserons
$HOME/qt6-rpi. - Où la version de Qt sera-t-elle déployée sur l'appareil ? Dans l'exemple, nous utiliserons
/usr/local/qt6.
Dans l'exemple, nous allons utiliser un SDK Raspberry Pi 4 (toolchain+sysroot) généré via Yocto, mais les instructions ici sont complètement génériques, sans dépendance à Yocto. Les étapes sont les mêmes avec n'importe quel autre toolchain et sysroot, une fois que le fichier toolchain est mis à jour avec le compilateur croisé correct et d'autres chemins.
Après avoir créé et basculé vers un répertoire build:
$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
En pratique, cette commande configure est équivalente à l'appel direct suivant de CMake :
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
Compte tenu du fichier de chaîne d'outils approprié, cela suffit pour générer une compilation Qt qui permet ensuite de construire des applications à l'aide de CMake. Pour permettre aux applications d'être également construites avec qmake, la spécification et les options de périphérique du style Qt 5 doivent être spécifiées, en plus de tous les arguments indiqués ci-dessus :
$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" \ ...
Par défaut, lors de la compilation croisée, seuls les bibliothèques et outils Qt censés fonctionner sur le périphérique cible sont construits. Les outils liés à la compilation comme moc et uic ne sont pas compilés. La construction de ces outils peut être activée en réglant QT_FORCE_BUILD_TOOLS sur ON.
Remarque : lorsque QT_FORCE_BUILD_TOOLS est activé, les binaires cibles d'outils tels que qmake sont installés dans l'emplacement de stockage. Par conséquent, si qmake est utilisé pour construire des applications, appelez le script host-qmake à la place.
Une fois la configuration terminée sans erreur, exécutez cmake --build . --parallel pour construire l'application. Une fois la construction terminée, exécutez cmake --install . pour installer les résultats sur $HOME/qt6-rpi. À partir de là, la version Qt peut être déployée sur l'appareil à l'aide de rsync, scp ou d'une autre méthode.
Si l'on construit des modules Qt XML individuels, on peut utiliser le script qt-configure-module du répertoire bin de l'emplacement de stockage ($HOME/qt6-rpi dans l'exemple) pour configurer des modules supplémentaires, tels que qtdeclarative, qtquick3d, et ainsi de suite. Ils peuvent ensuite être construits à l'aide de cmake --build . et installés dans l'emplacement de stockage en exécutant le script suivant cmake --install .
Remarque : avant de lancer la compilation, vérifiez toujours soigneusement le résultat de l'étape de configuration : toutes les fonctionnalités attendues sont-elles activées ? Créer une version et la déployer sur l'appareil est inutile si des fonctionnalités essentielles ne sont pas activées au moment de la configuration.
Par exemple, si l'on souhaite obtenir des graphiques accélérés via OpenGL, il convient de prêter une attention particulière aux fonctionnalités suivantes :
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
Avec l'exemple du Raspberry Pi 4, nous nous attendons à ce que EGL, OpenGL ES et EGLFS GBM soient tous signalés comme yes, sinon le plugin de plateforme EGLFS et son backend eglfs_kms ne seront pas fonctionnels sur l'appareil. Pour que la souris, le clavier et les entrées tactiles fonctionnent, evdev ou libinput doivent être activés.
De même, s'il est prévu d'utiliser X11 comme système de fenêtrage (ou l'un des systèmes de fenêtrage) sur l'appareil, assurez-vous que les fonctionnalités liées à xcb et X11 sont marquées comme yes.
Un exemple de fichier de chaîne d'outils
Nous supposerons qu'il existe un sysroot et une chaîne d'outils disponibles sous $HOME/rpi-sdk. TARGET_SYSROOT et CROSS_COMPILER doivent être adaptés à la chaîne d'outils et au sysroot utilisés. L'exemple présenté ici ne convient qu'à un SDK spécifique, généré par Yocto. Il en va de même pour CMAKE_C_COMPILER et CMAKE_CXX_COMPILER.
Nous ne nous appuyons pas sur des scripts d'encapsulation qui fourniraient des variables d'environnement telles que PKG_CONFIG_*. Le chemin d'accès aux fichiers .pc est plutôt spécifié dans le fichier de la chaîne d'outils. Il est probable qu'un autre sysroot nécessite des ajustements dans PKG_CONFIG_LIBDIR. Par exemple, avec un sysroot généré à partir d'une image Raspberry Pi OS (anciennement Raspbian), on utilisera plutôt /usr/lib/arm-gnueabihf/pkgconfig.
Les drapeaux du compilateur et de l'éditeur de liens ne sont pas nécessaires de manière optimale dans l'exemple. Ajustez-les si nécessaire en fonction de l'appareil cible.
Pour plus d'informations sur les spécificités de CMake dans le fichier de la chaîne d'outils de l'exemple, reportez-vous à ce billet de blog et à la documentation de CMake.
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()Construire des applications pour l'appareil cible
Une fois que la construction de Qt Location est terminée et installée dans l'emplacement de stockage, les exemples ou les applications peuvent être construits.
Avec CMake, utilisez le script qt-cmake généré dans le répertoire bin de l'emplacement staging ($HOME/qt6-rpi dans l'exemple) pour configurer, puis exécutez ninja. Par exemple :
$HOME/qt6-rpi/bin/qt-cmake . cmake --build .
L'application binaire résultante peut alors être déployée sur l'appareil. L'utilisation du script d'aide qt-cmake est pratique, car le script garantit que le fichier de chaîne d'outils utilisé pour la construction de Qt est chargé, de sorte qu'il n'est pas nécessaire de le spécifier à plusieurs reprises pour chaque application.
Contrairement à Qt lui-même, la construction d'applications avec qmake est toujours supportée dans Qt 6.0, tant qu'une spécification de périphérique appropriée est disponible, et que les arguments appropriés ont été passés à CMake ou configure lors de la configuration de Qt. Si tout cela est vrai, l'exécution de qmake et make générera également un binaire d'application pour le périphérique cible.
Paramètres par défaut des plugins de plateforme et de l'EGLFS
Une fois configuré, un plugin de plateforme par défaut est choisi. Il est utilisé lors du lancement d'une application sans l'argument -platform et sans que la variable d'environnement QT_QPA_PLATFORM soit définie.
De même, le plugin de plateforme EGLFS dispose de plusieurs backends. Le plugin par défaut est choisi en fonction de sa disponibilité et d'un ordre de priorité prédéfini. Si drm et gbm sont disponibles, le backend par défaut sera eglfs_kms. Ceci peut toujours être surchargé au moment de l'exécution en définissant la variable d'environnement QT_QPA_EGLFS_INTEGRATION.
Pour modifier ces valeurs par défaut lors de la compilation, sans avoir à forcer une valeur spécifique lors de l'exécution, les deux variables de cache CMake suivantes sont disponibles après que CMake ait été exécuté une fois :
QT_QPA_DEFAULT_PLATFORM(STRING) - Le nom du plugin de plate-forme par défaut.QT_QPA_DEFAULT_EGLFS_INTEGRATION(STRING) - Le backend EGLFS par défaut.
Ces variables peuvent également être définies dans le fichier de la chaîne d'outils.
Pour plus d'informations sur la configuration de Qt, voir les options de configuration de Qt.
© 2026 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.