Notes techniques sur l'atelier d'outils

Cette section essaie d'expliquer quelques détails techniques et logiques concernant la méthode de construction. Il n'est pas essentiel de tout comprendre immédiatement. La plupart des explications prendra du sens une fois que vous aurez réalisé une construction complète. Vous pouvez aussi vous y référer plus tard.

Le but global du chapitre 5 est de construire un environnement sain et temporaire dans lequel nous pouvons entrer avec chroot et à partir duquel nous pouvons constuire un système LFS propre, sans problème lors du chapitre 6. Pou le moment, nous essayons de nous affranchir du système hôte autant que possible en créant un atelier (ensemble d'outils) qui se suffit à lui-même. Il doit être noté que le processus de construction a été construit de telle façon que les risques sont minimisés pour les nouveaux lecteurs et qu'il apporte une valeur éducative maximum en même temps. En d'autres termes, des techniques plus avancées pourraient être utilisées pour construire le système.

Important : Avant de continuer, vous devez réellement savoir le nom de votre plate-forme actuelle, souvent aussi appelé le triplé cible. Pour beaucoup de personnes, ce triplé sera, par exemple : i686-pc-linux-gnu. Une façon simple de déterminer votre triplé cible est de lancer le script config.guess fourni avec le source de nombreux packages. Déballez les sources de Binutils, lancez le script ./config.guess et notez la sortie.

Vous aurez aussi besoin de connaître le nom de l'éditeur de liens dynamiques de votre plateforme, aussi appelé chargeur dynamique, à ne pas confondre avec l'éditeur de liens standard ld faisant partie de Binutils. L'éditeur de liens dynamique est fourni par Glibc et a pour but de trouver et charger les bibliothèques dynamiques nécessaires à un programme, préparant l'exécution de ce programme et le lançant. Pour la plupart des personnes, le nom de l'éditeur de liens dynamique ser ld-linux.so.2. Sur des plateformes moins communes, le nom pourrait être ld.so.1 et pour les nouvelles plateformes 64 bit, cela pourrait être complètement différent. Vous devez être capable de déterminer le nom de l'éditeur de liens dynamiques de votre plateforme en regardant dans le répertoire /lib de votre système hôte. Vous pouvez inspecter un binaire quelconque sur votre système hôte en lançant 'readelf -l <name of binary> | grep interpreter' et en notant la sortie. La référence concernant toutes les plateformes est dans le fichier shlib-versions à la racine du répertoires des sources de Glibc.

Quelques points techniques clés sur la façon dont fonctionne la méthode de construction au chapitre 5 :

Binutils est installé en premier parce que GCC et Glibc réalisent des tests de fonctionnalités sur l'assembleur et l'éditeur de liens durant leur lancement respectif de ./configure pour déterminer les fonctionnalités (dés)activées pour le logiciel. Ceci est plus important que ce que vous pouvez imaginer. Un GCC ou Glibc mal configurés peuvent avoir pour résultat un ensemble d'outils subtilement bogués et l'impact d'une telle erreur n'apparaîtra qu'à la fin de la construction de la distribution complète. Heureusement, un échec de la suite de tests nous alertera habituellement avant que trop de temps ne se soit passé.

Binutils installe son assembleur et son éditeur de liens en deux emplacements, /tools/bin et /tools/$TARGET_TRIPLET/bin. En fait, les outils dans un emplacement sont des liens vers les autres. Une importante facette de l'éditeur de liens réside dans l'ordre de son chemin de recherche des bibliothèques. Des informations détaillées sont disponibles sur ld en lui passant l'option --verbose. Par exemple, 'ld --verbose | grep SEARCH' vous montrera le chemin actuel et leur ordre. Vous pouvez voir quels fichiers sont actuellement liés par ld en compilant un programme et en ajoutant l'option --verbose switch. Par exemple, 'gcc dummy.c -Wl,--verbose 2>&1 | grep succeeded' vous affichera tous les fichiers ouverts avec succès lors du lien.

Le prochain package installé est GCC et, lors de exécution de ./configure, vous verrez par exemple :

checking what assembler to use... /tools/i686-pc-linux-gnu/bin/as
checking what linker to use... /tools/i686-pc-linux-gnu/bin/ld

Ceci est important pour les raisons mentionnées ci-dessus. Cela démontre aussi que le script configure de GCC ne cherche pas dans les répertoires $PATH pour trouver les outils à utiliser. Néanmoins, lors des opérations sur gcc lui-même, les mêmes chemins de recherche ne sont pas nécessairement utilisés. Vous pouvez trouver quel éditeur de liens standard gcc va utiliser en lançant : 'gcc -print-prog-name=ld'. Des informations détaillées peuvent être obtenues à partir de gcc en lui passant l'option -v lors de la compilation d'un programme. Par exemple : 'gcc -v dummy.c' vous affichera des informations sur le préprocesseur, les étapes de compilation et d'assemblage en incluant les chemins de recherche des en-têtes de gcc ainsi que leur ordre.

Le prochain paquet installé est Glibc. L'attention la plus importante, lors de la compilation de Glibc, doit être portée sur le compilateur et les outils. Le compilateur n'est généralement pas un problème car Glibc utilise toujours le gcc trouvé dans un répertoire de $PATH. Les outils binaires et les en-têtes du noyau peuvent poser plus de problèmes. Donc, nous ne prenons aucun risque et utilisons les options disponibles par configure. Après le lancement de ./configure, vous pouvez vérifier le contenu du fichier config.make du répertoire glibc-build pour tous les détails importants. Vous noterez des éléments intéressants comme l'utilisation de CC="gcc -B/tools/bin/" pour contrôler quels outils binaires sont utilisés, mais aussi l'utilisation des options -nostdinc et -isystem pour contrôler le chemin de recherche des fichiers include du compilateur. Ces éléments aident à souligner un aspect important du package Glibc : il est tout à fait suffisant en terme de machinerie de construction et ne repose pas en général sur les valeurs par défaut de l'ensemble des outils.

Après l'installation de Glibc, nous faisons quelques ajustements pour nous assurer que la recherche et l'édition de liens prennent place dans notre préfixe /tools. Nous installons un ld personnalisé, disposant d'un chemin de recherche en dur vers /tools/lib. Ensuite, nous modifions le fichier specs de gcc pour pointer vers notre éditeur de liens dynamique dans /tools/lib. Cette dernière étape est vitale pour tout le processus. Comme mentionné ci-dessus, un chemin codé en dur vers un éditeur de liens dynamiques est embarqué dans chaque exécutable ELF. Vous pouvez l'inspecter en lançant : 'readelf -l <name of binary> | grep interpreter'. En modifiant le fichier specs de gccnous nous assurons que tout programme compilé ici (et jusqu'à la fin du chapitre 5) utilisera notre nouvel éditeur de liens compris dans /tools/lib.

La nécessité d'utiliser le nouvel éditeur de liens dynamiques est aussi la raison pour laquelle nous appliquons le correctif Specs lors de la deuxième passe pour GCC. Son échec aura pour résultat des programmes GCC comprenant le nom de l'éditeur de liens du répertoire /lib sur le système hôte, ce qui ferait échouer notre but de s'éloigner de l'hôte.

Lors de la deuxième passe pour Binutils, nous sommes capable d'utiliser l'option configure --with-lib-path pour contrôler le chemin de recherche de la bibliothèque de ld. A partir de ce moment, notre atelier principal d'outils se suffit à lui-même. Le reste des packages du chapitre 5 sera construit avec le répertoire /tools.

En entrant dans l'environnement chroot chapitre 6, le premier paquet majeur que nous installons est Glibc, en raison de sa nature auto suffisante. Une fois que cette Glibc est installée dans /usr, nous réalisons un rapide changement dans les paramètres par défaut de l'atelier des outils, puis procédons à la construction du reste de la cible chapitre 6.

Notes sur l'édition de liens statiques

La plupart des programmes doivent réaliser, en plus de leur tâches spécifiques, beaucoup d'opérations communes et quelques fois triviales. Cela inclut l'allocation de mémoire, la recherche dans des répertoires, la lecture et l'écriture de fichiers, la gestion de chaînes de caractères, la correspondance de modèles, l'arithmétique et bien d'autres tâches. Au lieu d'obliger tout programme à réinventer la roue, le système GNU apporte toutes les fonctions de base dans des bibliothèques toutes prêtes. La bibliothèque principale sur tout système Linux est Glibc.

Il existe principalement deux façons de lier les fonctions d'une bibliothèque à un programme qui les utilise : statiquement ou dynamiquement. Quand un programme est lié statiquement, le code des fonctions utilisées est inclut dans l'exécutable, générant ainsi un programme lourd. Lorsqu'un programme est lié dynamiquement, ce qui est inclu est une référence de l'éditeur de liens, du nom de la bibliothèque et du nom de la fonction, résultant en un exécutable bien plus petit. (Une troisième façon est d'utiliser l'interface de programmation de l'éditeur de liens. Voir la page man dlopen pour plus d'informations.)

L'édition de liens dynamiques est réalisée par défaut sur Linux et a trois avantages majeurs sur l'édition de liens statiques. Tout d'abord, vous n'avez besoin que d'une copie du code de la bibliothèque exécutable sur votre disque dur au lieu d'avoir plusieurs copies du même code inclut dans un grand nombre de programmes, donc en sauvant de l'espace disque. Deuxièmement, quand plusieurs programmes utilisent la même fonction d'une bibliothèque en même temps, seule une copie de la fonction de la bibliothèque est requise dans le coeur, ce qui sauve de l'espace mémoire. Enfin, quand une bibliothèque de fonction est déboguée ou améliorée, vous n'avez besoin que de recompiler cette bibliothèque, au lieu d'avoir à recompiler tous les programmes utilisant la fonction améliorée.

Si l'édition de liens a plusieurs avantages, alors pourquoi lier statiquement les deux premiers packages de ce chapitre ? Il existe trois raisons : historique, éducationnel et technique. Historique parce que les anciennes versions de LFS liaient statiquement tous les programmes de ce chapitre. Educationnel parce que connaître la différence est utile. Technique parce que nous gagnons un élément d'indépendance sur l'hôte. Néanmoins, il est bon de rappeler qu'une construction complète et réussie de LFS peut toujours s'achever lorsque les deux premiers packages sont liés dynamiquement.