Le Raspberry Pi est un nano-ordinateur monocarte à processeur ARM conçu par le créateur de jeux vidéo David Braben, dans le cadre de sa fondation Raspberry Pi.
Le Raspberry Pi (B et B+) possède un processeur ARM11 à 700 MHz. Il inclut 2 ou 4 ports USB, un port RJ45 et 512 Mo de mémoire vive. Le Raspberry Pi 2 est équipé d’un processeur Broadcom BCM2836, quatre cœurs ARMv7 à 900 MHz, accompagné de 1 Go de RAM. Il possède les mêmes dimensions et connectiques que le modèle B+. La Raspberry Pi 3 dispose d’un processeur Broadcom BCM2837 64 bits à quatre cœurs ARM Cortex-A53 à 1,2 GHz et d’une puce Wifi 802.11n et Bluetooth 4.1 intégrée.
Une chaîne de compilation (toolchain) désigne l’ensemble des paquets utilisés dans le processus de compilation d’un programme, pour un processeur donné. Le compilateur n’est qu’un élément de cette chaîne, laquelle varie selon l’architecture matérielle cible. Une chaîne de compilation croisée est une chaîne compilée pour fonctionner sur l’architecture de processeurs de la machine hôte, mais qui va compiler des logiciels pour une architecture cible différente. La compilation croisée fait donc référence aux chaînes de compilation capables de traduire un code source en code objet dont l’architecture processeur diffère de celle où la compilation est effectuée. Ces chaînes sont principalement utilisés en informatique industrielle et dans les systèmes embarqués.
Pour une machine 64 bits (Ubuntu 12.04) :
$ wget https://s3.amazonaws.com/RTI/Community/ports/toolchains/raspbian-toolchain-gcc-4.7.2-linux64.tar.gz
$ tar xvzf raspbian-toolchain-gcc-4.7.2-linux64.tar.gz
$ export PATH=$(pwd)/raspbian-toolchain-gcc-4.7.2-linux64/bin:$PATH
$ echo $PATH
$ arm-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/home/tv/Téléchargements/raspberry-pi-cross-compilation/raspbian-toolchain-gcc-4.7.2-linux64/bin/../libexec/gcc/arm-raspbian-linux-gnueabi/4.7.2/lto-wrapper
Target: arm-raspbian-linux-gnueabi
Configured with: /home/rticonnext/rti_workspace/toolchains/tmp/.build/src/gcc-4.7.2/configure --build=x86_64-build_unknown-linux-gnu --host=x86_64-build_unknown-linux-gnu --target=arm-raspbian-linux-gnueabi --prefix=/home/rticonnext/rti_workspace/toolchains/raspbian-toolchain-gcc-4.7.2-linux64 --with-sysroot=/home/rticonnext/rti_workspace/toolchains/raspbian-toolchain-gcc-4.7.2-linux64/arm-raspbian-linux-gnueabi/sysroot --enable-languages=c,c++ --with-float=hard --with-pkgversion='crosstool-NG 1.17.0' --with-bugurl=http://community.rti.com --enable-__cxa_atexit --disable-libmudflap --disable-libgomp --disable-libssp --disable-libquadmath --disable-libquadmath-support --with-gmp=/home/rticonnext/rti_workspace/toolchains/tmp/.build/arm-raspbian-linux-gnueabi/buildtools --with-mpfr=/home/rticonnext/rti_workspace/toolchains/tmp/.build/arm-raspbian-linux-gnueabi/buildtools --with-mpc=/home/rticonnext/rti_workspace/toolchains/tmp/.build/arm-raspbian-linux-gnueabi/buildtools --with-ppl=/home/rticonnext/rti_workspace/toolchains/tmp/.build/arm-raspbian-linux-gnueabi/buildtools --with-cloog=/home/rticonnext/rti_workspace/toolchains/tmp/.build/arm-raspbian-linux-gnueabi/buildtools --with-libelf=/home/rticonnext/rti_workspace/toolchains/tmp/.build/arm-raspbian-linux-gnueabi/buildtools --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++ -lm -L/home/rticonnext/rti_workspace/toolchains/tmp/.build/arm-raspbian-linux-gnueabi/buildtools/lib -lpwl' --enable-threads=posix --enable-target-optspace --disable-nls --disable-multilib --with-local-prefix=/home/rticonnext/rti_workspace/toolchains/raspbian-toolchain-gcc-4.7.2-linux64/arm-raspbian-linux-gnueabi/sysroot --enable-c99 --enable-long-long
Thread model: posix
gcc version 4.7.2 (crosstool-NG 1.17.0)
La chaîne de compilation croisée est prête à l’emploi.
On commence par écrire le célèbre programme Hello world.
Remarque : Hello world (« bonjour le monde ») sont les mots traditionnellement écrits par un programme informatique simple dont le but est de faire la démonstration rapide d’un langage de programmation ou le test d’un compilateur.
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Hello world\n");
return 0;
}
Tout d’abord, on va tester sur la machine de développement :
$ gcc hello-world.c
$ file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x75af707611b680c50dc4abd819b8040d767620ae, not stripped
$ ./a.out
Hello world
Maintenant, on passe à la compilation croisée :
$ arm-linux-gnueabihf-gcc hello-world.c
$ file a.out
a.out: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, not stripped
$ arm-linux-gnueabihf-gcc hello-world.c -static
$ file a.out
a.out: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, not stripped
Pour finir, il suffit de déployer l’application fabriquée sur la cible (la Raspberry Pi) et de l’exécuter :
$ scp a.out pi@xxx.xxx.xxx.xxx:/home/pi
$ ssh pi@xxx.xxx.xxx.xxx
$ ./a.out
Hello world
On commence par écrire le célèbre programme Hello world.
Remarque : Hello world (« bonjour le monde ») sont les mots traditionnellement écrits par un programme informatique simple dont le but est de faire la démonstration rapide d’un langage de programmation ou le test d’un compilateur.
#include <iostream>
using namespace std;
int main()
{
cout << "Hello world\n";
return 0;
}
Maintenant, on passe à la compilation croisée :
$ arm-linux-gnueabihf-g++ hello-world.cpp
$ arm-linux-gnueabihf-g++ hello-world.cpp -static
Pour finir, il suffit de déployer l’application fabriquée sur la cible (la Raspberry Pi) et de l’exécuter :
$ scp a.out pi@xxx.xxx.xxx.xxx:/home/pi
$ ssh pi@xxx.xxx.xxx.xxx
$ ./a.out
Hello world
Il est évidemment possible de compiler une application Qt directement sur la Raspberry Pi (la machine cible). Le processus de fabrication sera tout simplement plus long que sur votre machine hôte de développement.
Il faut tout d’abord une chaîne de compilation croisée pour la Rasperry Pi fonctionnelle. Il est possible de l’installer à partir du github officiel pour la raspbian.
On télécharge la chaîne de compilation croisée raspbian officielle à partir de github :
$ sudo apt-get install build-essential git
$ git clone git://github.com/raspberrypi/tools.git
$ cd ./tools/arm-bcm2708
Pour une machine 64 bits, la chaîne se trouve dans gcc-linaro-arm-linux-gnueabihf-raspbian-x64.
$ export PATH=$(pwd)/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:$PATH
$ arm-linux-gnueabihf-gcc -v
On va maintenant préparer sa machine hôte (le PC) pour pouvoir fabriquer des applications Qt 4 en utilisant SSHFS :
$ sudo apt-get install sshfs
Il faut ajouter votre compte utilisateur (ici tv) dans le groupe fuse :
$ sudo usermod -a -G fuse tv
Vous devez maintenant vérifier si votre chaîne de compilation Qt 4 est aussi installée sur le PC. Un programme Qt nécessite le préprocesseur moc pour les mécanismes propres à Qt comme les signaux et les slots :
$ moc-qt4 -v
Qt Meta Object Compiler version 63 (Qt 4.8.1)
Sinon, pour installer le kit de développement Qt 4 :
$ sudo apt-get install libqt4-dev-bin
On va ensuite monter la racine du système de fichiers de la Raspebbry Pi sur la machine hôte :
$ mkdir $HOME/rpi
$ sudo sshfs pi@xxx.xxx.xxx.xxx:/ $HOME/rpi -o transform_symlinks -o allow_other
$ ls ~/rpi/
bin boot dev etc home lib lost+found media mnt opt proc root run sbin selinux srv sys tmp usr var
$ sudo ln -s $HOME/rpi/usr/lib/arm-linux-gnueabihf/ /usr/lib/arm-linux-gnueabihf
$ sudo ln -s $HOME/rpi/lib/arm-linux-gnueabihf/ /lib/arm-linux-gnueabihf
$ ls -ld /lib/arm-linux-gnueabihf
lrwxrwxrwx 1 root root 37 mars 6 06:57 /lib/arm-linux-gnueabihf -> /home/tv/rpi/lib/arm-linux-gnueabihf/
$ ls -ld /usr/lib/arm-linux-gnueabihf
lrwxrwxrwx 1 root root 41 mars 6 06:56 /usr/lib/arm-linux-gnueabihf -> /home/tv/rpi/usr/lib/arm-linux-gnueabihf/
Remarque : L’option transform_symlinks est nécessaire pour que les liens symboliques absolus soient transformés en relatifs. De cette façon, un lien symbolique sur le système de fichiers de la Raspebbry Pi pointera vers le fichier approprié sur le système de fichiers de la Raspebbry Pi et non sur un fichier du même nom sur le système hôte.
Maintenant, il faut créer un fichier de configuration Qt adaptée pour la compilation croisée ARM en spécifiant VOTRE chemin du point de montage RPI dans la variable ROOTFS :
$ sudo mkdir /usr/share/qt4/mkspecs/linux-arm-g++
$ sudo vim /usr/share/qt4/mkspecs/linux-arm-g++/qmake.conf
#
# qmake configuration for linux-arm-g++
#
CROSS_COMPILE = arm-linux-gnueabihf
ROOTFS = /home/tv/rpi
MAKEFILE_GENERATOR = UNIX
TARGET_PLATFORM = unix
TEMPLATE = app
CONFIG += qt warn_on release incremental link_prl gdb_dwarf_$
QT += core gui
QMAKE_INCREMENTAL_STYLE = sublib
include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)
QMAKE_CXX = $$CROSS_COMPILE-g++
QMAKE_LINK = $$CROSS_COMPILE-g++
QMAKE_LINK_SHLIB = $$CROSS_COMPILE-g++
QMAKE_AR = $$CROSS_COMPILE-ar cr
QMAKE_OBJCOPY = $$CROSS_COMPILE-objcopy
QMAKE_STRIP = $$CROSS_COMPILE-strip
QMAKE_LFLAGS_RELEASE = -Wl,-O1
QMAKE_RPATHDIR += $$ROOTFS/lib/arm-linux-gnueabihf
QMAKE_RPATHDIR += $$ROOTFS/usr/lib/arm-linux-gnueabihf
QMAKE_INCDIR = $$ROOTFS/usr/include
QMAKE_INCDIR_QT = $$ROOTFS/usr/include/qt4
QMAKE_RPATHDIR = $$ROOTFS/lib/arm-linux-gnueabihf
QMAKE_RPATHDIR += $$ROOTFS/usr/lib/arm-linux-gnueabihf
QMAKE_LIBDIR = $$ROOTFS/usr/lib
QMAKE_LIBDIR_QT = $$ROOTFS/usr/lib/arm-linux-gnueabihf
QMAKE_LIBDIR_QT += $$ROOTFS/lib/arm-linux-gnueabihf
QMAKE_INCDIR_X11 = $$ROOTFS/usr/include
QMAKE_LIBDIR_X11 = $$ROOTFS/usr/lib/arm-linux-gnueabihf
QMAKE_LIBDIR_X11 += $$ROOTFS/lib/arm-linux-gnueabihf
QMAKE_INCDIR_OPENGL = $$ROOTFS/usr/include
QMAKE_LIBDIR_OPENGL = $$ROOTFS/usr/lib
load(qt_config)
Pour générer un fichier Makefile pour la Raspeberry Pi à partir d’un fichier de projet Qt .pro, il suffira de faire :
$ qmake -spec linux-arm-g++
$ make
Pour déployer son application sur la Raspberry Pi, il suffira de copier l’exécutable dans $HOME/rpi/home/pi.
Pour tester en ssh, il ne faut oublier d’activer l’option -Y (forward X11) quand vous vous connectez.