Looking for Computer Science  & Information Technology online courses ?
Check my new web site: https://www.yesik.it !

La Raspberry Pi est une plate-forme embarquée de faible coût basée sur un micro-contrôleur ARM. Elle peut tourner sous Linux et supporte donc facilement les outils de développement classiques comme gcc. Le problème, c'est que, sur ARM comme sur n'importe quelle autre plate-forme, compiler, ça prend du temps (processeur) et ça consomme de la mémoire. Deux ressources qui sont limitées sur la Raspberry Pi – surtout si on les compares à celle de n'importe quel ordinateur portable un peu récent.

La solution à ce problème s'appelle cross-compiling ou compilation croisée en français. Il s'agit simplement de compiler sur une machine (mon portable quad-core) pour une autre (la Raspberry Pi). En théorie, ce n'est pas compliqué. En pratique, c'est autre chose, car pour compiler le compilateur croisé vous aurez entre autres besoin d'un compilateur hôte, d'outils pour la cible (binutils), ou encore des bibliothèques C adaptées (libc). Cette dernière phrase un peu incompréhensible juste pour vous dire que les choses ne sont pas si évidentes.

Heureusement, des solutions existent pour faciliter la vie du cross-developper. L'une d'entre elles est crosstool-NG. Son rôle? Vous fabriquer sur mesure les outils nécessaires pour faire de la compilation croisée. En l'occurrence, dans le cas qui m'intéresse ici, les outils nécessaires pour compiler sur un PC x86-64 pour une plate-forme ARM. Voici donc comment utiliser crosstool-ng pour faire de la compilation croisée facile pour Raspberry Pi.

Installer crosstool-ng

Installation

Sous Debian vous aurez besoin des paquets bzip2, build-essential, bison, flex, gperf, texinfo, gawk, libtool, automake, libncurses5-dev et subversion pour ce qui suit. Si ces logiciels ne sont pas déjà sur votre machine utilisez le gestionnaire de paquets de votre distribution pour procéder à l'installation.

sh# apt-get install bzip2
sh# apt-get install build-essential
sh# apt-get install bison
sh# apt-get install flex
sh# apt-get install gperf
sh# apt-get install texinfo
sh# apt-get install gawk
sh# apt-get install libtool
sh# apt-get install automake
sh# apt-get install libncurses5-dev
sh# apt-get install subversion

Pour utiliser crosstool-ng, vous devez déjà avoir sur votre machine quelques outils de développement natifs (gcc, make en particulier), ainsi qu'une connexion Internet valide puisque des fichiers vont être téléchargés à la volée. J'ai recensé ci-dessus les paquets que j'ai dû installer sur une machine Linux Debian Squeeze minimale pour y faire fonctionner crosstool-NG 1.17.0 (la dernière version stable au moment où j'écris). Je ne saurais vous garantir que d'autres paquets ne sont pas nécessaires ou que la liste ne risque pas d'évoluer rapidement. Mais c'est je pense une bonne base.

Une fois les pré-requis rassemblés, l'installation à proprement parler se fait de manière on ne peut plus classique:

# 1.17.0 est la dernière version au moment où j'écris
sylvain@arm-builder:~$ export VERSION=1.17.0
sylvain@arm-builder:~$ wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-${VERSION}.tar.bz2
sylvain@arm-builder:~$ tar xjf crosstool-ng-${VERSION}.tar.bz2
sylvain@arm-builder:~$ cd crosstool-ng-${VERSION}
sylvain@arm-builder:~/crosstool-ng-1.17.0$ ./configure --prefix=/opt/crosstool-ng
sylvain@arm-builder:~/crosstool-ng-1.17.0$ make
sylvain@arm-builder:~/crosstool-ng-1.17.0$ sudo make install

Remarque:

Un échec à l'étape du ./configure signifie souvent qu'il vous manque un pré-requis. Vérifiez le message à l'écran et explorez la liste des paquets de votre distribution pour essayer de localiser le logiciel manquant.

Configurer crosstool-ng

L'installation de crosstool-NG a seulement installé sur votre machine les scripts nécessaires pour fabriquer les outils de compilation croisée. L'étape suivante va consister à expliquer à crosstool-NG de quelle toolchain – c'est à dire de quels outils – vous avez besoin. Par exemple, en précisant l'architecture cible ou la version du compilateur qui vous intéresse. Les options sont nombreuses. Et pour les sélectionner l'outil propose une interface menuconfig qui vous sera un peu familière si vous avez déjà compilé un noyau Linux:

sylvain@arm-builder:~/crosstool-ng-1.17.0$ cd
sylvain@arm-builder:~$ export PATH="${PATH}:/opt/crosstool-ng/bin"

# Créer un dossier pour la configuration des outils à construire
# Attention: ce n'est pas là que les outils seront installés à la fin!
sylvain@arm-builder:~$ mkdir my-dev
sylvain@arm-builder:~$ cd my-dev
# Configuration de la toolchain à fabriquer
sylvain@arm-builder:~/my-dev$ ct-ng menuconfig

Dans menuconfig vous aurez un certain nombre d'options à modifier pour créer une toolchain ARM pour la Raspberry Pi:

crosstool-NG - Path and misc options.png

Dans Path and misc options

  • Cochez Try feature marked as experimental: cela permet en particulier de choisir le compilateur linaro lors d'une étape ultérieure
  • Vous pouvez modifier également l'emplacement d'installation de la toolchain. Par défaut il s'agit du dossier ${HOME}/x-tools/${CT_TARGET}
  • Une fois vos modifications terminées dans cette section, choisissez exit pour remonter au menu principal


crosstool-NG - Target options.png

Dans Target options:

  • Pour Target architecture choisissez arm: c'est le type de micro-contrôleur qui équipe la Raspberry Pi
  • Pour endianness vérifiez que little endian est bien sélectionnée
  • De même assurez vous que bitness est sur 32-bits
  • Une fois vos modifications terminées dans cette section, choisissez exit pour remonter au menu principal


crosstool-NG - Operating system.png

Dans Operating system

  • Changez Target OS pour Linux
  • Une fois vos modifications terminées dans cette section, choisissez exit pour remonter au menu principal


crosstool-NG - Binary utilities.png

Dans Binary utilities:

  • Choisissez une version récente de binutil en évitant si possible les versions expérimentales
  • Une fois vos modifications terminées dans cette section, choisissez exit pour remonter au menu principal


crosstool-NG - C compiler.png

Dans C compiler

  • Activez Show Linaro versions (EXPERIMENTAL)
  • et dans gcc version chosissez un compilateur Linaro récent.
  • Une fois vos modifications terminées dans cette section, choisissez exit pour remonter au menu principal


crosstool-NG - save and exit.png

Sélectionnez à nouveau exit pour quitter menuconfig et validez lorsque l'outil vous propose d'enregistrer vos modifications.


Remarque:

Finalement, c'est cette seule étape qui est spécifique à la plate-forme Raspberry Pi. Si vous développez pour une autre plate-forme, tout le reste de cet article est valide. Il vous faudra juste faire une configuration spécifique pour votre cible.

Construire la toolchain

Une fois l'étape de configuration terminée, c'est à crosstool-NG de jouer. En principe, sans intervention humaine. À l'invite du shell, tapez la commande suivante:

sylvain@arm-builder:~/my-dev$ ct-ng build

Et c'est parti: crosstool-NG va télécharger et décompresser les sources nécessaires, puis compiler et installer la toolchain. S'il en cache la complexité, le processus reste quand même long et gourmand en mémoire et en espace disque. Lors de mes tests, sur une machine virtuelle avec 8 cpu, il m'a fallut étendre la mémoire à 2Go de RAM sans quoi la compilation n'allait pas « au bout ». Et au final, près de 3,5Go d'espace disque sont occupés (peut-être plus en cours d'exécution?) Selon la puissance de votre machine et la vitesse de téléchargement, comptez entre 20 minutes et 1h30 avant de passer à la suite…

ERROR 404: Not Found.

Si le build échoue, vérifiez dans le journal build.log si le problème ne viendrait pas d'un problème de téléchargement:

sylvain@arm-builder:~/my-dev$ tail -25 build.log
[...]
[ALL  ]    --2012-12-06 18:17:03--  http://launchpad.net/gcc-linaro/4.5/4.5-2012.03/+download/gcc-linaro-4.5-2012.03
[ALL  ]    Resolving launchpad.net... 91.189.89.223, 91.189.89.222
[ALL  ]    Connecting to launchpad.net|91.189.89.223|:80... connected.
[ALL  ]    HTTP request sent, awaiting response... 404 Not Found
[ALL  ]    2012-12-06 18:17:03 ERROR 404: Not Found.
[ALL  ]    
[DEBUG]    Not at this location: "http://launchpad.net/gcc-linaro/4.5/4.5-2012.03/+download/gcc-linaro-4.5-2012.03"
[ERROR]  
[ERROR]  >>
[ERROR]  >>  Build failed in step 'Retrieving needed toolchain components' tarballs'
[ERROR]  >>        called in step '(top-level)'
[...]

Il est toujours possible qu'un site soit inaccessible (justement) au moment ou vous en avez besoin. J'ai moi-même eu des soucis pour télécharger gcc-linaro sur launchpad.net. Dans ce cas, la meilleure solution est de patienter – puis de retentez l'opération un peu plus tard.

Contrairement aux conseils que l'on trouve sur internet [1], inutile de modifier les fichiers de crosstool-NG.

Tester votre toolchain

C'est le moment le plus excitant de l'affaire: tester la toolchain:

sylvain@arm-builder:~/my-dev$ cd

# Programme de test (hautement sophistiqué)
sylvain@arm-builder:~$ mkdir test 
sylvain@arm-builder:~$ cd test 
sylvain@arm-builder:~/test$ cat > hello.c << EOF 
#include <stdio.h>
 
int main() {
    printf("Greetings from RPi!\n");
    return 0;
}
EOF
# Ajouter le chemin vers les outils de la toolchain au path
sylvain@arm-builder:~/test$ export PATH="${PATH}:/home/sylvain/x-tools/arm-unknown-linux-gnueabi/bin"
 # Compiler
sylvain@arm-builder:~/test$ arm-unknown-linux-gnueabi-gcc hello.c -o hello
sylvain@arm-builder:~/test$ ls -ls
total 12
8 -rwxr-xr-x 1 sylvain sylvain 4960 Dec  8 10:21 hello
4 -rw-r--r-- 1 sylvain sylvain   55 Dec  7 19:32 hello.c
# Le programme est bien un exécutable pour la cible, et ne peut donc pas
# fonctionner sur l'hôte:
sylvain@arm-builder:~/test$ file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.6.3, not stripped
sylvain@arm-builder:~/test$ ./hello 
-bash: ./hello: cannot execute binary file

Reste maintenant à vérifier le fonctionnement de l'exécutable produit sur la cible. Pour cela, il faut y télécharger le programme. Une option bien pratique est d'utiliser ssh:

# 10.129.36.203 est l'adresse IP de ma Raspberry Pi
# Copier le programme vers la cible
sylvain@arm-builder:~/test$ scp hello pi@10.129.36.203:.
pi@10.129.36.203's password: 
hello                                         100% 4960     4.8KB/s   00:00
# Exécuter *sur* la cible
sylvain@arm-builder:~/test$ ssh pi@10.129.36.203 ./hello
Greetings from RPi!

Et voilà™, vous venez de compiler sur votre PC un programme exécutable sur Raspberry Pi. Vous pouvez déjà commencer à vous amuser un peu. Mais vite, vous aurez envie – ou besoin – de faire des choses plus complexes. Lesquelles? Et bien par exemple, faire la compilation croisée d'un module Linux pour Rasberry Pi. Un programme alléchant, n'est-ce pas?

Ressources