Compilateur croisé pour Raspberry Pi4



Je veux vous dire comment j'ai mis au point un compilateur croisé pour le Raspberry Pi4 en utilisant crosstool-ng. Peut-être que quelqu'un trouvera le sujet trop primitif et ennuyeux. Au début, je pensais moi-même pouvoir assembler rapidement un compilateur croisé, mais j'ai dû bricoler et étudier le problème, certaines nuances m'étaient inattendues. Ensuite, je vais vous dire ce que j'ai fait et comment.



Peut-être que la première question que vous devez vous poser est: "A quoi sert un compilateur croisé?" En fait, le Raspberry Pi4 est assez rapide et vous pouvez compiler des programmes directement dessus. Si le projet est simple, il est tout à fait possible de le faire. Mais lorsque le projet grandit et devient plus complexe, il est déjà préférable de passer à la compilation croisée. Ensuite, il est plus facile de résoudre d'autres problèmes, par exemple, vous pouvez organiser l'assemblage automatique du projet sur le serveur d'intégration. La compilation croisée sur un PC rapide peut augmenter considérablement la vitesse de construction et vous pouvez trouver de meilleurs outils pour éditer des programmes sur un PC.



Deuxième question: «Puis-je prendre un compilateur croisé prêt à l'emploi? Pourquoi collectionner le vôtre? " Pour vous dire la vérité, je n'ai pas trouvé de compilateur croisé normal pour Raspberry. Peut-être que je regardais mal? Sur github de Rasberryil y a un projet d'outils et il y a plusieurs cross-compilateurs, mais ils sont anciens! Eh bien, qu'y at-il Version 4.9.3? En quelque sorte pas sérieux. Sur la page de téléchargement de Linaro, je ne vois que la version 7.5, déjà meilleure, mais, d'une part, sur le Raspberry Buster OS lui-même, la version 8.3 est déjà, et d'autre part, le compilateur Linaro n'a fonctionné pour moi qu'après quelques correctifs. C'est un peu étrange ...



C'est après avoir essayé d'exécuter le compilateur Linaro que j'ai pensé que je pourrais probablement construire moi-même mon propre compilateur croisé. J'ai déjà eu une certaine expérience avec crosstool-ng. Je faisais un compilateur croisé pour Amber SoC .



Quelle est la complexité de l'assemblage? L'outil crosstool-ng a de nombreux paramètres différents qui ne sont pas toujours clairs. Construire le compilateur croisé sur mon ordinateur portable prend environ 45 minutes. Si vous faites une erreur avec les paramètres, le compilateur croisé résultant ne fonctionne pas de cette façon, ne collecte pas quelque chose ou ne collecte pas, mais le binaire résultant ne fonctionne pas sur Raspberry. Après avoir vérifié le compilateur croisé résultant, j'ai à nouveau dû modifier quelque chose dans les paramètres et le générer à nouveau depuis le début. Eh bien, j'ai fait quelques essais jusqu'à ce que ça marche comme je le voulais.



Peut-être que la principale chose que je n'ai pas vraiment comprise au début est que le compilateur doit correspondre au système d'exploitation. Cela a l'air un peu étrange, mais c'est comme ça. En effet, l'OS contient déjà les bibliothèques standard c / c ++. Ils exportent un ensemble de fonctions. Le code généré par le compilateur croisé doit contenir des appels à ces fonctions de bibliothèque. Par conséquent, les versions des bibliothèques dans le compilateur croisé lui-même et dans le système d'exploitation pour lequel le code sera généré doivent correspondre.



Essayons de créer un compilateur croisé.



La procédure sera la suivante:



1) Vérifiez que les packages suivants sont installés sur notre système hôte (j'utilise Ubuntu 18):



gcc g++ gperf bison flex texinfo help2man make libncurses5-dev python3-dev autoconf automake libtool libtool-bin gawk wget bzip2 xz-utils unzip patch libstdc++6 rsync git

      
      





Si quelque chose manque, vous devez installer via sudo apt install.



2) Téléchargez la version 1.24.0 de crosstool-ng depuis leur site Web:



wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.24.0.tar.bz2 

      
      





3) Décompressez l'archive résultante:



tar xjf crosstool-ng-1.24.0.tar.bz2 
cd crosstool-ng-1.24.0 

      
      





4) Assemblage de la crosstool-ng:



./configure
make
make install
      
      





5) Patching Crosstool-ng



C'est une action plutôt étrange, mais sans elle je n’ai pas obtenu un bon résultat. Sans ce correctif, le compilateur croisé a refusé par défaut de rechercher des bibliothèques dans le dossier / usr / lib / arm-linux-gnueabihf par rapport à sysroot.



Le patch doit être obtenu à la framboise très.



Sur le raspberry pi4 avec OS Buster installé (c'est important, je fais un compilateur croisé pour ce système d'exploitation particulier), vous devez prendre les sources binutils:



sudo apt install binutils-source
      
      





et voir /usr/src/binutils/patches/129_multiarch_libpath.patch







Ce fichier que nous mettons dans le dossier crosstool-ng-1.24.0 / packages / binutils / 2.31.1 sur notre ordinateur hôte. Il est important de le mettre dans ce dossier, car sur le Raspberry Pi OS Buster lui-même, la version binutils est 2.31.1. Vérifiez cela avec une commande dans la console sur la framboise:



ld --version
      
      





De plus, vous devez vérifier quel GLIB est sur votre système d'exploitation pour la compression:



ldd --version
      
      





J'ai 2.28 dans Buster, ce qui signifie que crosstool-ng lui-même devra être configuré dans cette version de GLIB 2.28, il existe une version différente par défaut. Si cela n'est pas fait, le compilateur croisé générera du code qui ne fonctionnera pas sur Raspberry dans Buster OS - le binaire peut faire référence à des fonctions inexistantes dans les bibliothèques externes.



6) Préparer la configuration initiale de crosstool-ng



Il existe déjà pas mal de configurations typiques dans crosstool-ng lui-même. Notamment, il existe une configuration très similaire à ce dont nous avons besoin pour le Raspberry Pi3.



Une liste de toutes les configurations possibles peut être visualisée avec la commande:



./ct-ng list-samples
      
      





Ensuite, la configuration sélectionnée doit être «activée» avec la commande:



./ct-ng armv8-rpi3-linux-gnueabihf
      
      





Un nouveau fichier de configuration .config apparaîtra, qui définit complètement les propriétés du futur compilateur croisé. Maintenant, il a besoin d'être corrigé un peu. Vous pouvez le modifier manuellement, mais c'est plus facile à corriger à partir du menu:



./ct-ng menuconfig
      
      





Le tout premier menu ressemble à ceci:







7) Ensuite, changez l'option étrange, éventuellement facultative.



Presque partout où au moins quelque chose est écrit sur la création d'un compilateur croisé pour Raspberry, ils écrivent pour décocher l'option "Rendre la chaîne d'outils en lecture seule". Ce paramètre se trouve dans le menu "Chemins et options diverses". La documentation crosstool-ng indique que par défaut, le compilateur résultant sera en lecture seule afin que le programme compilé ne soit pas installé par inadvertance dans la racine système du compilateur lui-même. À mon avis, c'est une décision parfaitement raisonnable. Je ne sais pas pourquoi des auteurs écrivent pour supprimer la coche d'ici ...



8) Suivant. Accédez à l'élément "Options cibles" et définissez les valeurs en fonction de la capture d'écran:







Je dois dire qu'en fait, le Raspberry Pi4 dispose d'un processeur Cortex-A72 et cela peut être attribué ici dans le menu. Cependant, j'ai gardé le Cortex-A53 pour moi car je vais compiler non seulement pour Pi4, mais aussi pour Pi3. Cependant, le paramètre exact peut déjà être spécifié lors du démarrage du compilateur gcc à l'aide du paramètre de ligne de commande -mcpu = cortex-a72



Je veux également ajouter que je préfère que le compilateur croisé ait exactement le même tuple que le compilateur sur la carte Raspberry elle-même. Autrement dit, le compilateur final sera arm-linux-gueabihf et rien d'autre. C'est plus facile pour moi. De nombreux packages existants incluent des fichiers cmake prêts à l'emploi, où le compilateur est affecté à arm-linux-gnueabihf. Nous ne voulons pas réparer tous ces fichiers cmake à la main et écrire quelque chose comme armv8-mygcc-linux-gnueabihf? Pour ce faire, je désactive l'option "Omettre la partie fournisseur du tuple cible".



9) Allez dans le menu "Utilitaires binaires" et installez la version binutils 2.31.1 (Rappelez-vous que nous avons encore un correctif pour cela?)







10) Allez dans le menu "Système d'exploitation" et installez la version 4.20 du noyau







En fait, Raspberry Buster OS a déjà un noyau 5.10, mais le maximum est que vous ne pouvez l'installer que 4.20



11) Allez dans le menu "C-bibliothèques" et installez le GLIB 2.28 version







12) Allez dans le "C-compilateur" menu







Installez la version désirée du futur cross-compilateur 8.3.0 et ajoutez l'option --enable-multiarch aux paramètres de base du compilateur de configuration supplémentaire de gcc. Il est important que le compilateur croisé trouve les bibliothèques dans sysroot le long du chemin / usr / lib / arm-linux-gnueabihf

Maintenant, nous quittons tous les menus, enregistrons les modifications apportées à la demande et commençons à construire.



13) L'assemblage se fait avec des commandes simples:



export DEB_TARGET_MULTIARCH=arm-linux-gnueabihf 
./ct-ng build
      
      





Devra attendre. Il m'a fallu environ 45 minutes pour l'assembler sur mon ordinateur portable. Après la construction, votre nouveau compilateur croisé se trouve dans le chemin ~ / x-tools / arm-linux-gnueabihf



Vous pouvez vérifier quels chemins de bibliothèque seront utilisés par le compilateur croisé par défaut. Regardera-t-il dans le chemin / usr / lib / arm-linux-gnueabihf?



Pour ce faire, exécutez la commande:



~/x-tools/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-ld --verbose | grep "SEARCH"

      
      





La commande devrait renvoyer quelque chose comme ceci:



SEARCH_DIR("=/usr/local/lib/arm-linux-gnueabihf"); SEARCH_DIR("=/lib/arm-linux-gnueabihf"); SEARCH_DIR("=/usr/lib/arm-linux-gnueabihf"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/home/nick/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/lib");
      
      





Notez que les chemins commencent par le signe "=". Cela signifie qu'il s'agit de chemins relatifs à la racine système s'ils sont spécifiés lors de l'exécution de gcc avec l'option de ligne de commande --sysroot = PATH_TO_YOUR_SYSROOT.



C'est probablement tout. Il reste à décider où obtenir sysroot. Le moyen le plus simple est d'installer tous les packages de développement nécessaires sur le Raspberry Pi, puis, en retirant la carte SD de l'appareil, de la transférer sur le PC hôte. Mais il y a aussi quelques nuances.



Maintenant que nous avons un compilateur croisé, nous pouvons créer une sorte de programme spécifique à l'analyseur. Par exemple, les démos userland de Raspberry lui-même:



git clone https://github.com/raspberrypi/userland.git
cd userland
export PATH=${HOME}/x-tools/arm-linux-gnueabihf/bin:$PATH
./buildme

      
      





Le résultat de la compilation sera dans le dossier build / bin.



À la fin de l'article, je voudrais donner un tableau de paramètres supplémentaires pour les compilateurs gcc lors de la construction de projets pour différentes versions de raspberry:



Raspberry Pi 1:	-mcpu=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp (alias for vfpv2)
Raspberry Pi 2:  -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4                      
Raspberry Pi 3:	-mcpu=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mneon-for-64bits
Raspberry Pi 4:	-mcpu=cortex-a72 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mneon-for-64bits

      
      





J'espère que mon article sera utile à quelqu'un.



All Articles