8.30.1. Installation de GCC
Si vous construisez sur x86_64, changez le nom du répertoire par
défaut des bibliothèques 64 bits en « lib » :
case $(uname -m) in
x86_64)
sed -e '/m64=/s/lib64/lib/' \
-i.orig gcc/config/i386/t-linux64
;;
esac
La documentation de GCC recommande de construire GCC dans un
répertoire de construction dédié :
mkdir -v build
cd build
Préparez la compilation de GCC :
../configure --prefix=/usr \
LD=ld \
--enable-languages=c,c++ \
--enable-default-pie \
--enable-default-ssp \
--enable-host-pie \
--disable-multilib \
--disable-bootstrap \
--disable-fixincludes \
--with-system-zlib
Nous n'activons que le C et le C++ ici pour gagner du temps de
construction car aucun paquet de LFS ni BLFS n'ont besoin de GCC
pour d'autres langages. Ajoutez cobol
pour le Cobol (remarquez que cela fera échouer GCC sur un système
LFS 32-bits), fortran
pour Fortran,
go
pour Go, objc
pour Objective C, obj-c++
pour Objective C++ et m2
pour Modula 2 à la valeur de l'option
--enable-languages
si vous
souhaitez compiler des programmes dans un ou plusieurs de ces
langages avec GCC. GCC prend également en charge Ada et D, mais
lecode pour prendre en charge Ada et D est écrit en Ada ou en D,
donc la prise en charge ne peut être construite qu'avec un
compilateur Ada ou D existant et nous ne pouvons pas activer leur
prise en charge ici.
Voici la signification des nouveaux paramètres de
configuration :
-
LD=ld
-
Ce paramètre permet de s'assurer que le script configure
utilise le ld installé par Binutils, construit plus tôt dans
ce chapitre, au lieu de la version compilée de manière
croisée qui serait autrement utilisée.
-
--disable-bootstrap
-
Par défaut, le système de construction de GCC va le
bootstrapper en trois étapes à moins qu'il ne soit construit
en tant que compilateur croisé ou qu'il soit compilé de
manière croisée. Le processus de bootstrap est requis pour la
robustesse, surtout quand on met à jour GCC vers une nouvelle
version. Dans LFS nous utilisons une méthode différente pour
bootstrapper GCC (comme introduit dans le Remarques
techniques sur la chaîne de compilation), donc nous
n'avons pas besoin du processus de bootstrap fourni par le
système de construction et nous le désactivons ici pour
réduire considérablement le temps de construction. Supprimez
cette option si vous mettez à jour GCC sur un système LFS
complet (au lieu de construire une nouvelle LFS).
-
--disable-fixincludes
-
Par défaut, pendant l'installation de GCC, certains en-têtes
du système seraient « corrigés » pour fonctionner avec
GCC. Ce n'est pas nécessaire sur un système Linux moderne, et
peut être dangereux si un paquet est réinstallé après
l'installation de GCC. Ce paramètre évite que GCC ne
« corrige » les en-têtes.
-
--with-system-zlib
-
Ce paramètre dit à GCC de se lier à la copie de la
bibliothèque Zlib installée sur le système, plutôt qu'à sa
propre copie interne.
Note
PIE (exécutable indépendant de la position) est une technique
pour produire des programmes binaires qui peuvent être chargés
n'importe où en mémoire. Sans PIE, la fonctionnalité de sécurité
nommée ASLR (randomisation de l'agencement de l'espace
d'adressage) peut être appliquée pour les bibliothèques
partagées, mais pas pour l'exécutable lui-même. Activer PIE
permet l'ASLR des exécutables en plus des bibliothèques partagées
et réduit certaines attaques basées sur des adresses fixes de
code sensible ou de données dans les exécutables.
SSP (protection contre l'écrasement de la pile) est une technique
qui s'assure que la pile des paramètres n'est pas corrompue. La
corruption de pile peut par exemple changer l'adresse de retour
d'une sous-routine, ce qui permettrait de transférer le contrôle
à du code dangereux (qui existerait dans le programme ou les
bibliothèques partagées, ou éventuellement injecté par
l'attaquant) au lieu du code d'origine.
Compilez le paquet :
make
Important
Dans cette section, la suite de tests de GCC est considérée comme
importante, mais elle prend beaucoup de temps. Les novices sont
encouragés à ne pas l'ignorer. La durée des tests peut être
significativement réduite en ajoutant -jx à la commande
make -k check
ci-dessous, où x désigne le nombre de cœurs sur votre système.
GCC peut avoir besoin de plus d'espace en pile pour compiler
certains motifs de code particulièrement complexes. Par précaution,
sur les distributions qui ont une limite de pile réduite,
configurez la limite de taille de pile à l'infini. Sur la plupart
des distributions hôtes (et le système LFS final) la limite stricte
est infinie par défaut, mais il n'y a pas d'inconvénient à
l'indiquer explicitement. Il n'est pas nécessaire de limiter la
limite non stricte car GCC la configurera à une valeur appropriée,
tant que cette valeur ne dépasse pas la limite stricte :
ulimit -s -H unlimited
Maintenant, supprimez plusieurs échecs aux tests connus :
sed -e '/cpython/d' -i ../gcc/testsuite/gcc.dg/plugin/plugin.exp
Testez les résultats en tant qu'utilisateur non privilégié, mais ne
vous arrêtez pas aux erreurs :
chown -R tester .
su tester -c "PATH=$PATH make -k check"
Pour recevoir un résumé des résultats de la suite de tests,
lancez :
../contrib/test_summary
Pour n'avoir que les résumés, redirigez la sortie vers
grep -A7 Summ
.
Vous pouvez comparer les résultats avec ceux situés dans https://www.linuxfromscratch.org/lfs/build-logs/development/
et https://gcc.gnu.org/ml/gcc-testresults/.
Les tests liés à pr90579.c
sont
connus pour échouer.
Quelques échecs inattendus sont parfois inévitables. Dans certains
cas les échecs des tests dépendent du matériel spécifique du
système. Sauf si les résultats des tests sont très différents de
ceux sur l'adresse ci-dessus, vous pouvez poursuivre en toute
sécurité.
Installez le paquet :
make install
Le répertoire de construction de GCC appartient maintenant à
tester
et la propriété du
répertoire des en-têtes installé (et son contenu) sera incorrecte.
Transférez la propriété à l'utilisateur et au groupe root
:
chown -v -R root:root \
/usr/lib/gcc/$(gcc -dumpmachine)/15.2.0/include{,-fixed}
Créez un lien symbolique requis par le FHS
pour des raisons « historiques ».
ln -svr /usr/bin/cpp /usr/lib
Beaucoup de paquets utilisent le nom cc pour appeler le compilateur C.
Nous avons déjà créé cc comme un lien symbolique dans
gcc-pass2, créez également sa
page de manuel avec un lien symbolique :
ln -sv gcc.1 /usr/share/man/man1/cc.1
Ajoutez un lien symbolique de compatibilité pour permettre la
compilation de programmes avec l'optimisation à l'édition des liens
(LTO) :
ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/15.2.0/liblto_plugin.so \
/usr/lib/bfd-plugins/
Maintenant que notre chaîne d'outils est en place, il est important
de s'assurer à nouveau que la compilation et l'édition de liens
fonctionneront comme prévu. Vous devez alors effectuer plusieurs
contrôles d'intégrité :
echo 'int main(){}' | cc -x c - -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
Il ne devrait pas y avoir d'erreurs et la sortie de la dernière
commande aura cette forme (en permettant au nom de l'éditeur des
liens de différer en fonction de la plateforme) :
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
Maintenant, assurez-vous que vous êtes prêt à utiliser les bons
fichiers :
grep -E -o '/usr/lib.*/S?crt[1in].*succeeded' dummy.log
La sortie de la dernière commande devrait être :
/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.0/../../../../lib/Scrt1.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.0/../../../../lib/crti.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.0/../../../../lib/crtn.o succeeded
Selon l'architecture de votre machine, le message ci-dessus peut
légèrement différer. La différence porte sur le nom du répertoire
après /usr/lib/gcc
. Il est important
de vérifier que gcc a
trouvé les trois fichiers crt*.o
sous
le répertoire /usr/lib
.
Vérifiez que le compilateur recherche les bons fichiers
d'en-têtes :
grep -B4 '^ /usr/include' dummy.log
Cette commande devrait renvoyer la sortie suivante :
#include <...> search starts here:
/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.0/include
/usr/local/include
/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.0/include-fixed
/usr/include
À nouveau, le répertoire nommé selon votre triplet cible peut être
différent de celui ci-dessus, selon l'architecture de votre
système.
Ensuite, 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'
Les références au chemins qui ont des composantes comme
« -linux-gnu » devraient être ignorés, mais sinon la
sortie de la dernière commande devrait être :
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64")
SEARCH_DIR("/usr/local/lib64")
SEARCH_DIR("/lib64")
SEARCH_DIR("/usr/lib64")
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");
Un système 32 bits peut voir quelques répertoires
différemment. Par exemple, voici la sortie d'une machine
i686 :
SEARCH_DIR("/usr/i686-pc-linux-gnu/lib32")
SEARCH_DIR("/usr/local/lib32")
SEARCH_DIR("/lib32")
SEARCH_DIR("/usr/lib32")
SEARCH_DIR("/usr/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");
Ensuite assurez-vous que vous utilisez la bonne libc :
grep "/lib.*/libc.so.6 " dummy.log
La sortie de la dernière commande devrait être :
attempt to open /usr/lib/libc.so.6 succeeded
Assurez-vous que GCC utilise le bon éditeur dynamique :
grep found dummy.log
La sortie de la dernière commande devrait être (avec éventuellement
des différences spécifiques à votre plateforme dans le nom de
l'éditeur dynamique) :
found ld-linux-x86-64.so.2 at /usr/lib/ld-linux-x86-64.so.2
Si la sortie ne ressemble pas à celle montrée ci-dessus ou si elle
n'est pas disponible du tout, cela signifie que quelque chose s'est
vraiment mal passé. Enquêtez et répétez les étapes pour trouver où
les problèmes se trouvent et corrigez-les. Tout problème doit être
résolu avant de continuer le processus.
Une fois que tout fonctionne correctement, nettoyez les fichiers de
test :
rm -v a.out dummy.log
Enfin, déplacez un fichier mal placé :
mkdir -pv /usr/share/gdb/auto-load/usr/lib
mv -v /usr/lib/*gdb.py /usr/share/gdb/auto-load/usr/lib