Dernièrement j’ai ressorti mes notes de mes archives. Et je tombe sur mes essais de cross-compilation avec Qt ! Ce fut laborieux, mais cela s’était conclu par un succès ! Le framework étant récemment passé en version 5.5, je me doit de publier ce tuto réalisé avec la version 5.4.1 de Qt. Je pense que les manipulations seront globalement les mêmes ! Je souhaite un bon courage à tous ceux qui se lance dans la compilation croisée de framework !
Table des matières
Un framework ? Qt ? Késako ?
Un framework, ou en bon français, une structure logicielle est une sorte de grande bibliothèque qui inclus des fonctions et objets déjà pré-programmé et prêt à l’emploi (chouette non ? 🙂 ). Le framework Qt à l’avantage d’être très modulaire, flexible, simple à comprendre et adapté à la compilation multi-OS. Programmer en Qt, c’est en gros faire du C++ avec une surcouche Qt. Qt est un framework principalement graphique qui intègre la notion de connecteurs qui permettent de relier des données entre eux (un peu comme un pattern vue-modèle). Qt possède aussi son propre environnement de développement ainsi qu’une gamme d’outils pour mettre à jour et traduire ses propres créations.
Qt a été développé à l’origine par Nokia. Nokia a abandonné le projet, qui a été repris par Digia. Depuis cette reprise, une communauté s’est formé autour du potentiel de Qt. On a vu apparaître deux versions de Qt : une version professionnelle et une version community. La version community était tout à fait correcte et quasi-complète pour développer des applications très puissantes rapidement. Les fonctionnalités de Qt ont évolué, son IDE a permis de faire de la compilation multi-OS, puis de la compilation croisée, et même du débug croisée ! Qt est même devenu un API de choix pour développer en C++ sur Android !
Seulement, voilà où le bas blesse… Avec l’engouement des technologies mobiles et embarquées, Digia a décidé de séparer son framework en 3 unités distinctes : professionel, mobile et community. Cette nouvelle version mobile de Qt intègre des compilateurs croisées, permet de cross-compiler sur la plupart des machines ARM, ainsi que le débug à distance, et cela, entre autre… sur le Raspberry Pi. Et devinez quoi… cette version mobile est sous licence et payante !
La version community quand à elle se retrouve dépourvue de ces fonctionnalités, même si, avec un peu de pratique et de bons tutos, il est encore possible de développer sous la dernière version de Qt pour ARM.
Pour info, la version 4 de Qt est encore disponible et fonctionnelle sur le Raspberry Pi. Cependant, si vous êtes comme moi, et que vous voulez programmer sur votre ordinateur perso et profiter des dernières nouveautés de Qt (entre autre depuis la v5, la gestion de SQlite), ce tuto est fait pour vous !
Etape 1 – Installation de l’environnement de développement :
J’ai réalisé une nouvelle installation de Ubuntu 32 bits (14.04 LTS) pour réaliser cette partie. Travaillant jusqu’à présent dans une machine virtuelle, j’ai préféré sur un dual boot afin d’avoir un gain de performance au niveau de la compilation. Cependant, il est suffisant de faire ce tuto dans une machine virtuelle.
Pour commencer, récupérons les différents outils nécessaires à la compilation croisée du Framework Qt 5.4.1. Il faut donc récupérer la dernière version de Qt ici : http://www.qt.io/download/.
Grâce à l’installateur web, installer la dernière version en date :
Ensuite, j’ai téléchargé la dernière version de Raspbian sur le site officiel de Raspberry Pi Foundation : http://www.raspberrypi.org/downloads/ . Une fois cette version récupérée, j’en ai extrait extrait l’image (.img) dans le répertoire personnel (/home/ « utilisateur »/). J’ai renommé l’image en « raspbian.img ».
Ensuite j’ai récupéré les outils additionnels qui m’ont permis la compilation croisée. Pour cela, j’ouvre un terminal et je crée un répertoire nommé « rpi-tools » :
Commandes : mkdir rpi-tools && cd rpi-tools
La première chose dont nous avons besoin, c’est le « cross compiler » (compilateur croisée). Une fois dans le répertoire rpi-tools, je télécharge les fichiers du « repository » GitHub grâce à la commande : git clone https://github.com/raspberrypi/tools.git. Pour se faire git doit être installé (si il n’est pas installé, il faudra faire un apt-get install git).
Commandes :
git clone https://github.com/raspberrypi/tools.git
cd tools
ls
Les différents outils téléchargés sont organisés selon la structure de dossier suivante :
Le dossier « arm-bcm2708 » contient le compilateur armv6 pour Raspberry Pi.
Je télécharge ensuite le package qui permet de corriger des erreurs sur la compilation de liens symboliques lors de l’installation du Framework sur l’image Raspbian.
Commandes :
cd ..
git clone git://gitorious.org/cross-compile-tools/cross-compile-tools.git
Maintenant que nous avons tous les outils, on va pouvoir préparer notre image. Le but ici est de réaliser une image du Raspberry Pi intégrant le Framework Qt 5.4.1 compilé pour ARMv6. Cette image va nous servir lors de 2 étapes : l’installation du système sur le Raspberry Pi et la compilation croisée de programmes Qt 5.4.1 pour Raspberry Pi.
Commandes :
sudo mkdir /mnt/rasp-pi-rootfs
sudo mount -v -o loop,offset=62914560 -t ext4 raspbian.img /mnt/rasp-pi-rootfs/
L’image du système d’exploitation est maintenant montée dans /mnt/rasp-pi-rootfs/. Maintenant nous allons réparer les liens symboliques de l’image en utilisant le script «fixQualifiedLibraryPath ».
Commandes :
cd ~/rpi-tools/cross-compile-tools
./fixQualifiedLibraryPaths /mnt/rasp-pi-rootfs ~/rpi-tools/tools/arm-bcm2708/gcc-linaro-arm-linuxgnueabihf-
raspbian/bin/arm-linux-gnueabihf-gcc
Maintenant les liens symboliques correspondent à la bonne chaîne de compilation croisée. J’exporte quelques variables afin de simplifier les commandes qui suivront :
Commandes :
export RPI_SYSROOT=/mnt/rasp-pi-rootfs
export RPI_TOOLCHAIN=~/rpi-tools/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-
Nous allons maintenant configurer Qt 5.4.1 pour le Raspberry Pi. Cela a pour but de nous créer un Makefile, un fichier de compilation :
Commandes :
cd ~/Qt/5.4/Src
./configure -opengl es2 -device linux-rasp-pi-g++ -device-option CROSS_COMPILE=$RPI_TOOLCHAIN -sysroot $RPI_SYSROOT -opensource -confirm-license -optimized-qmake -reduce-exports -release -make libs -prefix /usr/local/qt5pi -skip qtwebkit
Cette opération a duré environ 10 minutes.
L’opération suivante consiste à cross-compiler Qt 5.4.1 pour le Raspberry Pi. Cette opération peut prendre du temps (la durée est estimée à 40 heures si la compilation est effectuée directement sur le Raspberry Pi). Comme j’ai effectué cette opération sur un ordinateur portable, nous j’ai utiliser les 4 coeurs d’un processeur Intel i5 2.67 GHz avec l’opération make –j 4. L’opération a duré environ 2 heures et 30 minutes.
Commandes :
make -j 4
sudo make install
Pour finir, j’ai synchronisé notre image raspbian.img avec la carte microSDHC de la Raspberry Pi :
Commandes :
sync
sudo umount /mnt/rasp-pi-rootfs
sudo dd bs=4M if=raspbian.img of=/dev/sdX; sync
Pour l’option bs=4M, j’avais mis bs=1M, il s’agit de l’allocation mémoire de la carte. Il se trouve qu’avec 1M, la Raspberry ne démarrait pas tout le temps parfaitement. La Raspberry Pi Foundation recommande 4M.
Cette opération prend un moment (variable selon la classe de la carte microSDHC). sdX correspond à l’adressage de la carte SD, à vérifier avec la commande « df –h ».
Etape 2 – Construction de la chaîne de compilation croisée :
La chaîne de compilation croisée permet de compiler n’importe quel programme Qt 5.4.1 de Ubuntu vers le Raspberry Pi, du moment que les bibliothèques existent sur le Raspberry Pi (cf. chapitre précédent).
Lors de cette réalisation, nous sommes toujours sur le PC sous Ubuntu 32 bits avec Qt-sdk 5.4.1.
Tout d’abord, configurons la connexion qui va nous servir à déployer notre programme sur le Raspberry Pi. Cette connexion se fera de manière filaire, avec un câble Ethernet entre la machine hôte (PC) et la machine cible (Raspberry Pi).
Sur le PC, dans les options de QtCreator, nous ajoutons un compilateur : « ~/rpi-tools /tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ ».
Puis je rajoute un appareil mobile, dans l’onglet « Appareils mobiles ». Je sélectionne « Generic Linux Device » et configure avec les paramètres réseaux et SSH :
Nous avons maintenant le compilateur et le périphérique distant ! On peut désormais créer le kit de compilation !
Maintenant nous avons la configuration pour réaliser une compilation croisée sur Raspberry Pi. Il nous faut pas oublier de monter l’image de la Raspberry Pi « raspbian.img » sur /mnt/rasp-pi-rootfs/ avant de compiler. Pour déployer, il faut connecter le PC au Raspberry Pi via Ethernet.
Commande : sudo mount -v -o loop,offset=62914560 -t ext4 raspbian.img /mnt/rasp-pi-rootfs/
MAJ 17/07/2015 : Il est aussi possible de le faire en utilisant sshfs (si nécessaire, pour installer : sudo apt-get install sshfs) qui permet de monter le Rasberry Pi à distance. Ceci est même préférable en cas d’ajout de bibliothèque sur le Raspberry Pi (pas besoin de les installer aussi dans raspbian.img). Il faut aussi préalablement débloquer le compte root sur le Raspberry Pi avec « sudo passwd root »
Commande Raspberry Pi : sudo passwd root
Puis vous devez ajouter un mot de passe au compte root.
Commande PC : sshfs -o follow_symlinks root@Adresse_IP_du_Pi:/ /mnt/rasp-pi-rootfs/
Pour définir le répertoire de déploiement de l’application, il faut rajouter ces options dans le fichier .pro du projet :
Conclusion :
Vous pouvez maintenant programmer et compiler pour le Raspberry Pi. Votre programme se retrouvera dans le répertoire que vous avez défini. Vous n’aurez plus qu’à le lancer. Les applications graphiques Qt se lanceront en plein écran, que ce soit à partir du bureau graphique ou de la console. Les performances sont correctes sans être exceptionnelles (j’y ai développé un serveur avec une API graphique pour gérer des comptes utilisateurs). J’avais testé cette compilation croisée sur un Raspberry Pi type B+. Certains modules de Qt ne sont pas compatible avec cette compilation croisée. Cela pose aussi des problèmes avec des modules et bibliothèques complémentaires. Par exemple, il m’était impossible d’utiliser le dernier connecteur mySQL compatible avec la version 5.4 de Qt. Il est possible de compiler ce dernier à partir des sources, sauf que cette compilation n’est apparemment pas compatible avec le processeur hard float de la Raspberry Pi… Dommage…
BenTeK.
Très bon tutoriel.
SVP pourriez-vous me aider avec un semblable tutoriel sur la carte RIoTboard?
Je ne connais pas cette carte. A première vu, c’est du ARMv9, il faudrait donc compiler l’ensemble du framework pour l’ARMv9… à voir si c’est compatible. C’est une belle découverte cette RIoTBoard 🙂