6.10. Ré-ajustement de la chaîne d'outils

Maintenant que les bibliothèques C finales ont été installées, il est temps d'ajuster de nouveau la chaîne d'outils. L'ensemble d'outils sera ajusté de façon à ce qu'il lie tout programme nouvellement compilé avec ces nouvelles bibliothèques. C'est le même processus que celui utilisé dans la phase d'« ajustement » au début du Chapitre 5, avec les ajustements inversés. Dans Chapitre 5, l'ensemble était passé des répertoires /{,usr/}lib de l'hôte dans le nouveau répertoire /tools/lib. Maintenant, l'ensemble sera guidé du même répertoire /tools/lib vers les répertoires /{,usr/}lib.

D'abord, sauvegardez l'éditeur de liens de /tools, et remplacez-le par l'éditeur de lien ajusté que nous avons fait au chapitre 5. Nous créerons aussi un lien vers son équivalent dans a /tools/$(gcc -dumpmachine)/bin :

mv -v /tools/bin/{ld,ld-old}
mv -v /tools/$(gcc -dumpmachine)/bin/{ld,ld-old}
mv -v /tools/bin/{ld-new,ld}
ln -sv /tools/bin/ld /tools/$(gcc -dumpmachine)/bin/ld

Puis, modifiez le fichier des specs GCC afin qu'il pointe vers le nouvel éditeur de liens dynamiques. La suppression simple de tous les exemples de « /tools » devrait nous laisser uniquement le bon chemin sur l'éditeur de liens dynamique. Ajustez aussi le fichier de specs pour que GCC sache où trouver les en-têtes corrects et les fichiers de démarrage de Glibc. Une commande sed fait cela :

gcc -dumpspecs | sed -e 's@/tools@@g' \
    -e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
    -e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
    `dirname $(gcc --print-libgcc-file-name)`/specs

C'est une bonne idée d'examiner visuellement le fichier de specs pour vérifier que le changement voulu a bien été effectué.

Il est impératif à ce moment d'arrêter et de vous assurer que les fonctions basiques (compilation et édition des liens) de l'ensemble des outils ajusté fonctionnent comme attendu. Pour cela, réalisez une petite vérification :

echo 'main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'

Si tout fonctionne correctement, il ne devrait pas y avoir d'erreurs et la sortie de la commande sera (avec des différences spécifiques aux plateformes dans le nom de l'éditeur de liens) :

[Requesting program interpreter: /lib/ld-linux.so.2]

Remarquez que /lib est maintenant le préfixe de notre éditeur de liens.

Maintenant, assurez-vous que nous utilisons les bons fichiers de démarrage :

grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log

Si tout fonctionne correctement, il ne devrait pas y avoir d'erreurs et la sortie de la dernière commande sera :

/usr/lib/crt1.o succeeded
/usr/lib/crti.o succeeded
/usr/lib/crtn.o succeeded

Vérifiez que le compilateur cherche les bons fichiers d'en-tête :

grep -B1 '^ /usr/include' dummy.log

Cette commande devrait réussir avec la sortie suivante :

#include <...> search starts here:
 /usr/include

Puis, vérifiez que le nouvel éditeur de liens est utilisé avec les bons chemins de recherche :

grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'

Si tout fonctionne correctement, il ne devrait pas y avoir d'erreurs et la sortie de la dernière commande sera (selon la triplette cible spécifique à chaque plateforme) :

SEARCH_DIR("/tools/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/lib")
SEARCH_DIR("/lib");

Ensuite, assurez-vous que nous utilisons la bonne libc :

grep "/lib.*/libc.so.6 " dummy.log

Si tout fonctionne correctement, il ne devrait pas y avoir d'erreur et la sortie de la dernière commande sera (selon la triplette cible spécifique à chaque plateforme) :

attempt to open /lib/libc.so.6 succeeded

Pour finir, assurez-vous que GCC utilise le bon éditeur de liens dynamiques :

grep found dummy.log

Si tout fonctionne correctement, il ne devrait pas y avoir d'erreurs et la sortie de la commande sera (avec des différences spécifiques aux plateformes dans le nom de l'éditeur de liens et un répertoire lib64 sur les hôtes 64 bits) :

found ld-linux.so.2 at /lib/ld-linux.so.2

Si la sortie n'apparaît pas comme montré ci-dessus ou qu'elle n'apparaît pas du tout, alors quelque chose ne va vraiment pas. Enquêtez et retracez les étapes pour savoir d'où vient le problème et comment le corriger. La raison la plus probable est que quelque chose s'est mal passé lors de la modification du fichier specs ci-dessus. Tout problème devra être résolu avant de continuer le processus.

Une fois que tout fonctionne correctement, nettoyez les fichiers tests :

rm -v dummy.c a.out dummy.log