Quand les envies prennent vie !
Installer une distribution c’est bien, c’est pratique, c’est « simple ». Tout un tas de commandes sont à notre disposition, un guide pour partitionner le disque, un autre pour configurer le réseau, il existe même un gestionnaire de paquets qui permet de gérer en toute simplicité les dépendances entre programmes. C’est incroyable ! (bientôt, sur Canal D !)
Dans 99,99999999% des cas cette approche est parfaite mais il y a toujours le 0,00000001% (hey, c’est moi !) qui souhaite essayer autre chose. Comme par exemple, construire pas à pas un système GNU/Linux de zéro (from scratch).
Étant donné que je suis un mec super cool (mes chevilles vont bien, merci), je vais essayer de retranscrire dans une série de billets ma toute récente expérience dans le monde l’embarqué et du from scratch.
En quoi cela consiste ?
L’idée est de compiler uniquement les programmes, librairies, etc… qui me sont nécessaires. Cela permet, par exemple, d’optimiser la compilation d’un programme en fonction des instructions disponibles dans le processeur. L’autre point important est de comprendre comment fonctionne un système GNU/Linux.
Savez-vous par exemple d’où vient la commande mkfs ?
Ah vous le savez ?!
Tant mieux vous allez donc certainement pouvoir me dire d’où vient la commande mkfs.ext4 ?
Bahhhh… c’est un lien symbolique de mkfs !
FAUX ! Et TOC !
Mais pourquoi tant de souffrance ?
Cette idée me trotte en tête depuis longtemps mais je dois avouer que ça prend du temps (je geek tous les soirs depuis deux semaines, elle me hait…) et des connaissances que je n’avais pas spécialement à l’époque (vous connaissiez vous l’option -p de la commande mkdir ? ).
Là ou ça se complique un peu, c’est que ce système doit fonctionner sur une plate-forme de type embarquée et plus particulièrement sur un processeur ARM Cortex-A7. Compiler quoique se soit sur ce type de plate-forme est du suicide sauf si le temps n’est pas un détail important pour vous !
Explications :
Imaginez compiler la librairie Glibc ou un noyau Linux sur un processeur cadencé à 600MHz avec très peu de mémoire cache et un bus pas vraiment rapide, et bien ce qui prendrait quelques minutes sur un processeur x86_64 récent se transformerait en plusieurs heures sur un processeur ARM… 😯
La solution !!
Heureusement il existe la compilation croisée (ou cross-compilation en anglais). Elle permet de créer des exécutables (ou autres) depuis une architecture processeur pour une autre. Ci-dessous une liste non-exhaustive des compilations croisées possibles :
- i386 => x86_64
- x86_64 => ARM
- x86_64 => Mips
- x86_64 => PowerPC
- x86_64 => Sparc
Ce qui veut dire que le binaire bash compilé sur une architecture x86_64 pour une architecture ARM ne pourra se lancer que sur cette dernière. Rien de tel qu’un exemple pour illustrer mes dires :
Le binaire bash est compilé depuis une architecture x86_64 pour une architecture ARM
bash: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, not stripped
Le binaire bash est compilé pour une architecture x86_64
/bin/bash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x5bb332752cc304fa7fbb838bdf7d7766ffc7a8a1, stripped
J’espère qu’avec cet exemple c’est un peu plus clair dans votre esprit.
Mais comment fait-on ?
Avec une chaîne de compilation adaptée pardi ! Une chaîne de compilation (toolchain) est un groupe d’outils permettant la compilation d’un programme d’une architecture processeur à une autre (oui oui je radote). En général on y trouve les outils suivants : Binutils, Cloog, eGlibc, GCC, GMP, ISL, Noyau Linux, MPC, MPFR. Ces librairies sont nécessaires à la compilation de GCC (cf. http://gcc.gnu.org/install/prerequisites.html).
L’ARM Cortex-A7 est « parfaitement » supporté depuis la version 4.8 de GCC. Il existe trois méthodes courantes pour obtenir une chaîne de compilation :
- La première méthode consiste à construire soit même la toolchain en compilant les librairies données ci-dessus une par une, puis de compiler GCC avec les instructions souhaitées du processeur. L’avantage de cette méthode est purement ludique (à mon sens).
- La seconde méthode consiste à passer par des outils qui automatisent la construction de la toochain. Pour ce faire, il existe Crosstool-NG, Buildroot. J’ai une préférence pour Crosstool-NG qui s’occupe uniquement de construire une chaîne de compilation. L’avantage de cette méthode est que Crosstool-NG propose une interface en Ncurses permettant de configurer simplement les options de la toolchain.
- La troisième méthode consiste à passer par le gestionnaire de paquets de la distribution. Cette méthode est la plus simple, la plus rapide mais la moins intéressante.
Conclusion
Dans ce billet il y aura eu peu de technique… désolé !
Je voulais dans un premier temps exposer les bases afin que les prochains billets soient plus compréhensibles (je fais allusion à mon expérience).
Le prochain billet (partie 2) aura pour sujet la mise en place d’une chaîne de compilation via Crosstool-NG sur une Debian GNU/Linux.
Liens
- Explications du HardFloat, FPU, etc…
- Site officiel de Crosstool-NG
- Linux From Scratch pour plate-forme ARM
Gaëtan Trellu (goldyfruit)
Derniers articles parGaëtan Trellu (goldyfruit) (voir tous)
- Qinling, let’s the journey begin! - 23 mai 2019
- systemd-networkd, l’âge de la maturité ? - 13 mars 2018
- Hyper-V, Nova, VxLAN et Open vSwitch, enfin une belle histoire ! - 31 décembre 2017
Linux From Scratch et ARM Cortex-A7 – Partie 1 par Gaëtan Trellu (goldyfruit) est sous Licence Creative Commons Internationale Attribution 4.0.