Linux Embedded

Le blog des technologies libres et embarquées

Crosstool-ng : human crossing

La plupart des développeurs ont l’habitude d’utiliser les chaînes de compilation fournies par leur distribution. Elles sont généralement faciles à installer et  fiables car fréquemment utilisées.

Elles sont en revanche peu configurables. Créer sa propre chaîne de compilation permet de l’adapter à une cible et à des besoins spécifiques. Il pourra être possible de choisir la libc, la version de linux, le compilateur, configurer les accélérations matérielles, etc.

Crosstool-ng, en plus de permettre cela, amène un avantage majeur : la chaîne de compilation créée est indépendante de l’endroit où elle est fabriquée. Elle peut être déplacée et même transmise à un tiers, et ainsi, il est possible de créer une toolchain pour une machine différente, dédiée à son architecture.

Cet article s'appuie sur la documentation de crosstool-ng.

Installation de crosstool-ng

Crosstool-ng peut être installé sur n’importe quelle distribution Linux ou BSD, sur MacOS X ou  Windows. Pour chaque OS supporté, une liste des prérequis nécessaires est disponible sur le site.

Certaines distributions proposent un paquet mais il est préférable de compiler crosstool-ng soi-même. Les dernières versions des sources peuvent être téléchargées sur le site ou alors directement depuis le dépôt Git. Sur un PC équipé d'une version récente de gcc, il est possible qu’il faille partir de la branche master du dépôt. Les deux méthodes sont détaillées sur la page d’installation.

$ git clone https://github.com/crosstool-ng/crosstool-ng
$ cd crosstool-ng
$ ./bootstrap

Le répertoire de destination peut être spécifié avec l’option --prefix lors de l'appel à configure. Par défaut, l'outil sera installé dans /usr/local, ce qui nous convient très bien :

$ ./configure
$ make
$ sudo make install

Ajout au PATH

Si un répertoire de destination a été choisi, il faudra penser à le rajouter dans le PATH. Attention également aux distributions qui n'ont pas /usr/local par défaut dans le PATH.

Auto-complétion bash

Les commandes de crosstool-ng pouvant être très longues, l'auto-complétion s'avère très pratique et par chance un script est disponible. Pour les versions antérieures à 1.24, il faut sourcer le script ct-ng.comp à la racine des sources.
À partir de la version 1.24 de crosstool-ng (pas encore disponible à ce jour), le script est directement installé dans le répertoire de destination. S'il est sur /usr/local, il devrait être chargé automatiquement. Sinon, il faut sourcer le fichier /your/installation/path/share/bash-completion/ct-ng.

Utiliser crosstool-ng pour créer une toolchain

Plaçons-nous maintenant dans un répertoire spécifique de compilation, par exemple ~/mytarget.

$ mkdir ~/mytarget
$ cd ~/mytarget

L'utilitaire peut être utilisé par la commande ct-ng. Reportez-vous à l’aide pour un résumé des commandes ou au manuel pour plus de détails.

$ ct-ng help [COMMAND]
$ man 1 ct-ng

Configuration de la toolchain

Pour commencer, il faut configurer la toolchain pour la cible désirée. Pour faciliter la tâche, une liste de configurations de base est disponible. Elle est observable avec les commandes ct-ng list-samples et ct-ng list-samples-short :

Beaucoup d'architectures sont déjà configurées, et sont un excellent point de départ sur la quasi-totalité des projets.

Il est possible d'obtenir des informations sur une cible en la préfixant par show-. Par exemple, pour un ARM avec GNU/Linux :

$ ct-ng show-arm-unknown-linux-gnueabi
[G..] arm-unknown-linux-gnueabi
 OS : linux-4.16.1
 Companion libs : gmp-6.1.2 mpfr-4.0.1 mpc-1.1.0 isl-0.19 libelf-0.8.13 expat-2.2.5 ncurses-6.1 libiconv-1.15 gettext-0.19.8.1
 Binutils : binutils-2.30
 Compiler : gcc-8.1.0
 Languages : C,C++
 C library : glibc-2.27
 Debug tools : duma-2_5_15 gdb-8.1 ltrace-0.7.3 strace-4.22
 Companion tools : autoconf-2.69 automake-1.16.1

Une fois la cible choisie, elle doit être sélectionnée :

$ ct-ng arm-unknown-linux-gnueabi

Cela a pour effet de créer un fichier .config dans le répertoire actuel. Ce fichier répertorie la configuration de la cible. Il peut être transmis à un tiers qui pourra ainsi construire une toolchain identique.

Personnalisation

Cette configuration est personnalisable avec menuconfig :

$ ct-ng menuconfig

Les options sont nombreuses, voici une liste non exhaustive de ce qu'il est possible de faire :

  • changer le nom de la toolchain (utile pour avoir arm-none-eabi au lieu de arm-unknown-eabi)
  • activer les logs et le debug de compilation
  • activer des optimisations (calcul flottant, etc.)
  • choisir le répertoire de destination
  • configurer des miroirs
  • modifier l’architecture, l’"endianisme"
  • choisir la libc
  • ajouter la compilation des compilateurs pour les langages C++, Fortran etc.
  • compiler les outils de debug :
    • gdb/gdbserver
    • strace
    • ltrace
    • duma

Build

La compilation est lancée avec la commande build. Pour l'accélérer, le nombre de threads peut être réglé en suffixe. Il n'y aura pas de parallélisation des tâches, mais plutôt un multithreading de chaque tâche.

$ ct-ng build
$ ct-ng build.4

La chaîne est construite par défaut dans ~/x-tools. Ce répertoire peut être déplacé (dans la distribution hôte).

Utilisation de la toolchain générée

Les utilitaires générés sont répartis sur deux répertoires :

  • Les utilitaires pour la machine hôte dans /your/toolchain/path/bin
  • Les utilitaires pour la cible dans /your/toolchain/path/<tuple>/debug-root/usr/bin

Cross-compilation avec GCC ou G++

Il est maintenant possible de compiler un programme avec gcc :

$ /your/toolchain/path/bin/arm-unknown-linux-gnueabi-gcc helloworld.c -o hello
$ file hello
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 4.16.1, with debug_info, not stripped

Cross-compilation avec autoconf

Un projet utilisant autoconf peut être compilé facilement en spécifiant la cible lors de la configuration :

$ autoreconf -i
$ ./configure --host arm-unknown-linux-gnueabi
$ make

Outils de debug

S’ils ont été compilés, les outils de debug (gdb, strace…) pour la machine hôte sont installés dans le sous-dossier /your/toolchain/path/<tuple>/debug-root/usr/bin :

$ ls ~/x-tools/arm-unknown-linux-gnueabi/arm-unknown-linux-gnueabi/debug-root/usr/bin/
duma gcore gdb gdbserver ltrace strace strace-graph strace-log-mergeConclusion

On pourra par exemple installer gdbserver et utiliser le gdb correspondant :

$ ~/x-tools/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-gdb

 

Quel que soit l'environnement, la version de distribution, ou même le système d'exploitation utilisé (Linux, MacOS X ou Windows), Crosstool-ng permet de construire une même toolchain, simplement en partageant un fichier de configuration.

Mis à part quelques éventuelles difficultés dans la compilation de ct-ng, son utilisation épargnera au final bien des soucis.

Bibliographie

http://crosstool-ng.github.io/docs

https://www.blaess.fr/christophe/2012/10/19/toolchain-crosstool-ng-pour-raspberry-pi/

https://en.wikipedia.org/wiki/Cross_compiler

    • le 29 septembre 2018 à 17:02

      Louis,

      Est ce que crosstool-ng propose des outils (testsuite) pour tester la toolchain générée ?

      Je constate que les PR sur github sont (build) testé avec Travis en utilisant les cible suivante:
      arm-unknown-eabi, arm-unknown-linux-musleabi, aarch64-unknown-linux-gnu, mips64el-multilib-linux-uclibc,
      powerpc-e500v2-linux-gnuspe, x86_64-unknown-linux-uclibc et xtensa-fsf-linux-uclibc
      Ce qui est déjà pas mal mais cela ne permet pas de détecter un problème au runtime...

      Connais-tu le projet toolchain-builder ? [1]
      Toolchain-builder permet de compiler la toolchain, générer un système minimal et de l'exécuter dans Qemu (lorsque le support Qemu est disponible).
      Cependant, le test reste limité car le système ne fait que démarrer jusqu'au shell.
      Aussi, Toolchain-builder se base sur l'infrastructure de Buildroot pour générer une toolchain interne, le choix de la cible est limité par ce qui est supporté par Buildroot.

      Crosstool-ng est capable de générer des toolchain baremetal et supporte des cibles qui ne sont pas disponible dans Buildroot (alpha, s390, mingw).

      [1] https://gitlab.com/free-electrons/toolchains-builder

      Romain

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.