Un petit tuto pour arrêter de s’embêter avec la compilation de programmes sur Raspberry Pi 2. Le tuto est valable pour toutes les cibles fonctionnant avec un processeur ARM-v7 et bénéficiant d’un accès SSH.
Le but de cet article est de réussir à cross-compiler ses programmes pour Raspberry Pi 2 sans forcement le faire en ligne de commande directement sur la Raspberry via le SSH. L’astuce est de monter le système de fichiers de la Raspberry Pi dans notre système de fichiers pour en bénéficier localement. Une fois qu’on a accès aux fichiers, il nous suffira de cross-compiler notre code avec notre PC et les programmes seront exécutables directement sur la Rasp.
C’est quoi la cross-compilation ?
Chaque machine dispose d’un ou plusieurs processeurs pour pouvoir effectuer des instructions dictées par des exécutables. Ces exécutables sont dit « compilés ». La compilation est le processus qui permet à un ensembles de lignes de code dans un programme de devenir compréhensibles pour un processeur et ainsi être exécuté.
Tout comme les humains en fonctions des pays, les processeurs ont des dialectes différents en fonction de leurs types et de leurs fabricants. On ne cause pas de la même façon à un processeur Intel dit x86 qu’a un processeur Freescale ARM-cortex A9.
Pour se passer de cette traduction de programme(très très complexe), l’homme à inventé le compilateur qui est capable de transformer un programme (C/C++/Rubby… et bien d’autres) en instructions machine. Chaque processeur est différent et heureusement pour nous des familles sont compatibles, ainsi nous pouvons distinguer les grandes familles suivantes :
- x86-64bits
- x86-32bits
- ARM (différentes versions v5, v7)
- Power PC
- DSP
- et beaucoup d’autres …
Dans notre cas c’est la famille x86 et ARM-v7 qui nous intéressent. Les processeurs de type x86 sont ceux présents dans nos PC. Le processeur ARM-v7 est celui présent sur la Raspberry Pi 2. On comprend bien, avec les explications précédentes qu’un exécutable compatible PC x86 ne va donc pas fonctionner sur une Raspberry Pi.
Mais alors comment rendre mon programme, écrit sur mon PC, compatible pour ma Raspberry Pi 2 ?
Il faut savoir que, quand on écrit un programme monProgramme.c et que l’on fait une compilation de ce genre :
$ gcc -o monProgramme monProgramme.c
le programme est alors compilé pour la cible sur laquelle on exécute gcc. Si je suis sur mon PC, l’exécutable monProgramme sera compilé pour mon PC, alors que si je fait la même commande sur ma Raspberry Pi, l’exécutable monProgramme sera compilé pour ma Raspberry Pi …
Un point s’impose ! Nous sommes d’accord sur le fait que la commande gcc n’est qu’un appel à un programme ayant le nom gcc. Ce programme prend de nombreux paramètres dont le nom du fichier à compiler (monProgramme.c) ainsi que le nom du fichier de sortie (monProgramme). Quand on appui sur entrée, gcc s’exécute et viens générer monProgramme grâce au fichier monProgramme.c. Si maintenant je remplace gcc par un « gcc-arm » qui est capable de compiler monProgramme.c pour un processeur ARM, nous aurons donc un fichier de sortie qui sera un exécutable et compatible pour processeur ARM !
C’est ça la cross-compilation ! le fait de compiler un programme pour une cible différente de laquelle on exécute le logiciel de compilation.
Intérêts de la cross-compilation
Maintenant qu’on sait ce qu’est la cross-compilation, on se demande bien pourquoi se faire autant chi… pour juste compiler un programme …
Et bien il est vrai que pour un programme type « hello world » la cross-compilation n’est pas des plus intéressante, quoi que …
Premièrement, la cross-compilation sur un PC pour une cible embarquée est bien souvent la seul alternative possible pour générer un exécutable pour la cible. J’entends par la que de nombreux systèmes embarqués ne disposent par de quoi compiler dans leurs entrailles. La définition même d’un système embarqué est qu’il est pauvre en ressources. C’est donc une hérésie d’aller mettre un programme de plusieurs méga pour compiler son propre programme alors qu’une machine de dev (PC) peut le faire…
Un petit exemple sera le bienvenue. Si vous êtes en train de lire ce tuto, c’est que vous avez sûrement déjà fait un ou plusieurs programmes pour Arduino. Quand je compile mon programme Arduino, je ne fait que compiler le fichier monProgramme.ino en un exécutable compréhensible pour mon Arduino (Uno, Mega, etc.). Nous utilisons alors une chaîne de cross-compilation (son nom est avr-gcc) qui s’occupe de générer l’exécutable, puis un utilitaire transfère le programme dans la carte via la liaison série. On comprend aisément qu’il n’est pas envisageable d’aller mettre notre programme qui sert à la compilation directement dans l’Arduino pour qu’il puisse compiler notre programme … enfin voyons … 🙂
C’est donc l’un des avantages majeur de la cross-compilation.
Deuxièmement, la cross-compilation pour processeur ARM, grâce à une chaine de cross-compilation adaptée, réduit considérablement la taille des programmes générés car elles sont, bien souvent, les plus optimisées possible.
Troisièmement, le temps de compilation ! Quand vous avez un programme qui commence à impliquer plusieurs dizaines de fichiers avec chacun plusieurs milliers de lignes, le temps de compilation est une chose qu’il faut prendre en compte. La cross-compilation permet une compilation sur une machine puissante (type intel-core I3/I5/I7) plutôt que sur un pauvre petit processeur ARM … Une compilation qui dure plus d’une heure sur une Raspberry Pi 2, dure moins de 5min sur un PC !
Avec tous ces avantages on comprend bien l’intérêt de la cross-compilation !
Comment mettre en place une chaine de cross-compilation pour ma Raspberry Pi 2 ?
Aller, rentrons dans le vif du sujet maintenant, on est quand même la pour ça !
Le but de cette partie est d’installer une chaîne de cross-compilation adaptée pour notre Rasberry Pi 2. Plusieurs chaînes existent et il est même possible de compiler sa propre chaîne de cross-compilation … de toute façons, dans le libre TOUT est possible :-p !
Nous on va faire simple et on va prendre une chaîne toute prête que nous propose GCC, cette chaîne est : gcc-arm-linux-gnueabi
Installation de la chaîne sur une distribution type Ubuntu :
$ sudo apt-get install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
Et voila ! vous êtes propriétaire d’une chaîne de cross-compilation pour processeur ARM sur votre PC.
Comment utilise-t-on une chaîne de cross-compilation ?
La encore une étape particulièrement difficile … mais non bien-sur 😀 !
Maintenant, plutôt que de faire gcc -o monProgramme monProgramme.c, il suffira de faire cette commande :
$ arm-linux-gnueabi-gcc -o monProgramme monProgramme.c
Oui mais moi je ne fait pas du C, je fait du C++ !
Comme je suis un petit filou, la commande que je vous ai mise un peu plus haut, installe à la fois gcc mais aussi g++ vous pouvez donc exécuter la commande suivante pour vos programmes codés en C++ :
$ arm-linux-gnueabi-g++ -o monProgramme monProgramme.cpp
WHOAAAA mais c’est trop bien ton truc, on peu recompiler le noyau avec ça !
Et bien OUI ! Il est possible de compiler n’importe quel programme codé en C/C++ avec une chaîne pareille, notamment un noyau Linux ! Si jamais vous voulez cross-compiler un noyau Linux, il suffira de faire une commande de ce type :
$ make ARCH=arm CROSS_COMPIL=arm-linux-gnueabi-
Nous ferrons bientôt un tuto sur comment cross-compiler son noyau pour Raspberry Pi 2. Simplement il est possible de comprendre par cette commande le mot « chaîne » dans chaîne de cross-compilation. En effet, la partie « arm-linux-gnueabi- » est le premier maillon d’une chaîne qui comprend d’autres maillons comme gcc, g++, gcc-4.7, etc.
Astuce d’échange de données via SSH entre son PC et sa Raspberry Pi
C’est bien pratique la cross-compilation mais encore faut-il pouvoir mettre notre programme sur notre cible, en l’occurrence une Raspberry Pi 2. On sous estime bien souvent les possibilités du SSH. Ce n’est pas seulement un moyen d’accéder à un hôte en réseau via la ligne de commande. C’est un véritable protocole de transfert de données comme le FTP. Le serveur openSSH qui est présent dans les distributions Raspbian, propose le montage de dossiers distant. Le protocole s’appel le SFTP.
Il est donc possible de monter un répertoire distant dans notre système de fichiers afin de pouvoir en bénéficier localement.
Pour cela, nous allons installer un utilitaire bien pratique qu’es xsshfs avec les commandes suivantes :
Installation du logiciel pour monter les dossiers distants dans son système de fichier :
$ sudo apt-get install sshfs
Installation de l’interface graphique :
$ wget http://xsshfs.zici.fr/files/xsshfs_current.deb ; sudo dpkg -i xsshfs_current.deb ; sudo apt-get install -f ; rm xsshfs_current.deb
Voila, maintenant plus qu’a mettre l’adresse IP de sa rasp, son nom d’utilisateur (pi par défaut) et son mot de passe (raspberry par défaut)
Conclusion
Avec ce que nous avons vu, il est désormais possible de cross-compiler nos programmes pour notre Raspberry Pi 2 directement dans un dossier monté en SSH dans notre PC.
La solution apporte de nombreux avantages tant sur le plan performance que sur la praticité. Plus besoin de manipuler nos fichiers en lignes de commande directement sur la Raspberry Pi. L’échange de données quelque soit leurs types est aussi beaucoup plus simple, plus besoin de clée ou de Filezilla pour transférer un fichier. Les fichiers distants font parties de votre système, il est donc possible de les ouvrir et les modifier sans aucun problème.
Pour vous prouver que le système du montage de dossiers en SSH fonctionne bien, je peux vous dire que j’héberge des films en Full HD sur un serveur privé. Pour regarder mes films, je monte un dossier en SSH et je lis les films directement avec Kodi sans même les télécharger, il sont lus à la volé sur mon serveur distant.
Étant donné que vous savez cross-compiler vos programmes, il est intéressant de savoir bien faire un Makfile pour organiser la compilation de ses programmes. Je vous invites donc à aller voir notre tuto sur les Makefiles ici : Le Makefile
c’est à la troisieme fois que j’installe une chaine et celle là marche avec des explications qui me vont bien.
Merci pour ce travail partagé