6.16. GCC-4.5.3

Le paquet GCC contient la collection de compilateurs GNU, qui inclut les compilateurs C et C++.

Temps aproximatif de construction: 44 SBU
Espace disque requis: 1.1 GB

6.16.1. Installation de GCC

Appliquez une substitution sed qui supprimera l'installation de libiberty.a. À la place, la version de libiberty.a fournie par Binutils sera utilisée :

sed -i 's/install_to_$(INSTALL_DEST) //' libiberty/Makefile.in

Comme au Section 5.10, « GCC-4.5.3 - Passe 2 », appliquez la commande sed suivant pour obliger la construction à utiliser le drapeau de construction -fomit-frame-pointer afin de garantir des constructions de compilateur cohérentes :

case `uname -m` in
  i?86) sed -i 's/^T_CFLAGS =$/& -fomit-frame-pointer/' \
        gcc/Makefile.in ;;
esac

Le script fixincludes est connu pour s'efforcer parfois, de manière inadéquate, de "réparer" les en-têtes du système installées précédemment. Comme les en-têtes installées par GCC-4.5.3 et Glibc-2.12.2 sont connues pour ne pas avoir besoin de réparation, lancez la commande suivante pour empêcher le script fixincludes de s'exécuter :

sed -i 's@\./fixinc\.sh at -c true@' gcc/Makefile.in
sed -i 's@\./fixinc\.sh at -c true@' gcc/Makefile.in

Corrigez GCC pour ajouter -D_FORTIFY_SOURCE=2, -fPIE -pie, -fstack-protector-all, et --param=ssp-buffer-size=4 par défaut :

patch -Np1 -i ../gcc-4.5.3-fortify_source-1.patch
patch -Np1 -i ../gcc-4.5.3-fpie-1.patch
patch -Np1 -i ../gcc-4.5.3-fstack_protector-1.patch

La documentation de GCC recommande de construire GCC en dehors du répertoire source, c'est-à-dire dans un répertoire dédié :

mkdir -v ../gcc-build
cd ../gcc-build

Préparez la compilation de GCC :

../gcc-4.5.3/configure --prefix=/usr \
    --libexecdir=/usr/lib --enable-shared \
    --enable-threads=posix --enable-__cxa_atexit \
    --enable-clocale=gnu --enable-languages=c,c++ \
    --disable-multilib --disable-bootstrap --with-system-zlib

Voici la signification de la nouvelle option de configure :

--with-system-zlib

Ce paramètre dit à GCC de se lier à la copie installée sur le système de la bibliothèque Zlib, plutôt qu'à sa propre copie interne.

Remarquez que pour d'autres langages, il y a des prérequis qui ne sont pas disponibles. Voir le livre BLFS pour des instructions sur la façon de construire tous les langages supportés par GCC.

Compilez le paquet :

make
[Important]

Important

Dans cette section, la suite de tests pour GCC est considérée critique. Ne les sautez sous aucun prétexte.

Un ensemble de tests dans la suite de tests de GCC est connu pour déborder la pile, donc augmentez la taille de la pile avant de lancer les tests :

ulimit -s 16384

Testez les résultats mais ne vous arrêtez pas aux erreurs :

make -k check

Pour recevoir un résumé des résultats de la suite de tests, lancez 

../gcc-4.5.3/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 http://www.linuxfromscratch.org/lfs/build-logs/development/ et http://gcc.gnu.org/ml/gcc-testresults/.

Quelques échecs inattendus sont inévitables. Les développeurs de GCC connaissent ces problèmes, mais ne les ont pas encore résolus. En particulier, les tests de libmudflap sont connus pour être particulièrement problématiques et résultant d'un bogue dans GCC (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20003). Sauf si les résultats du test sont très différents de ceux sur l'adresse ci-dessus, vous pouvez continuer en toute sécurité.

Installez le paquet :

make install

Quelques paquets s'attendent à ce que le préprocesseur C soit installé dans le répertoire /lib Pour supporter ces paquets, créez ce lien symbolique :

ln -sv ../usr/bin/cpp /lib

Beaucoup de paquets utilisent le nom cc pour appeler le compilateur C. Pour satisfaire ces paquets, créez un lien symbolique :

ln -sv gcc /usr/bin/cc

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. Cela se fait en effectuant les mêmes tests de propreté que ceux faits plus haut dans ce chapitre :

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]

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/gcc/i686-pc-linux-gnu/4.5.3/../../../crt1.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.5.3/../../../crti.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.5.3/../../../crtn.o succeeded

Selon l'architecture de votre machine, le message ci-dessus peut légèrement différer, la différence portant normalement sur le nom du répertoire après /usr/lib/gcc. Si votre machine est un système 64 bits, il se peut que vous voyiez un répertoire nommé lib64vers la fin de la chaîne. La chose importante à chercher est que gcc ait trouvé les trois crt*.o sous le répertoire /usr/lib.

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

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

Cette commande devrait réussir avec la sortie suivante :

#include <...> search starts here:
 /usr/local/include
 /usr/lib/gcc/i686-pc-linux-gnu/4.5.3/include
 /usr/lib/gcc/i686-pc-linux-gnu/4.5.3/include-fixed
 /usr/include

A nouveau, notez que le nom du répertoire apres votre triplette cible peut être différent de celui ci-dessus, selon votre architecture.

[Remarque]

Remarque

Depuis la version 4.3.0, GCC installe maintenant sans condition le fichier limits.h dans un répertoire à part include-fixed, et ce répertoire doit être en place.

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("/usr/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");

Il se peut qu'un système 64 bits voie un peu plus de répertoires. Par exemple, voici la sortie d'une machine x86_64 :

SEARCH_DIR("/usr/x86_64-unknown-linux-gnu/lib64")
SEARCH_DIR("/usr/local/lib64")
SEARCH_DIR("/lib64")
SEARCH_DIR("/usr/lib64")
SEARCH_DIR("/usr/x86_64-unknown-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/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

Vérifiez que -D_FORTIFY_SOURCE=2 fonctionne :

cat > memcpy.c << "EOF"
/* Issu de NetBSD usr/src/regress/lib/libc/ssp/memcpy/memcp.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
  char b[10];
  int len = atoi(argv[1]);
  (void)memcpy(b, "1020202020202", len);
  (void)printf("%*.*s\n", len, len, b);
  return 0;
}
EOF
gcc -o memcpy memcpy.c -Wall -O2
./memcpy 10
./memcpy 11
rm -v memcpy memcpy.c

Ceci devrait donner les résultats suivants :

# ./memcpy 10
1020202020
# ./memcpy 11
*** buffer overflow detected ***: ./memcpy terminated
...

Vérifiez que -fstack-protector-all fonctionne :

cat > ssptest.c << "EOF"
 /* Issu de Ashish http://old.nabble.com/gcc--fstack-protector-all-option-to5867717.html */
#include <stdio.h>
#include <stdlib.h>

void buffer_overflow ( )
{
  long int        i = 0;
  char    str[29];
  for ( i = 0; i < 50; i++){
    str[i] = '\0';
  }
}
int main ()
{
  buffer_overflow ( );
  exit ( 0);
} 

EOF
gcc -o ssptest ssptest.c -Wall
./ssptest
rm -v ssptest ssptest.c

Ceci devrait donner les résultats suivants :

# ./ssptest
*** stack smashing detected ***: ./ssptest terminated
...

6.16.2. Contenu de GCC

Programmes installés: c++, cc (lien vers gcc), cpp, g++, gcc, gccbug et gcov
Bibliothèques installés: libgcc.a, libgcc_eh.a, libgcc_s.so, libgcov.a, libgomp.{a,so}, libmudflap.{a,so}, libmudflapth.{a,so}, libssp.{a,so}, libssp_nonshared.a, libstdc++.{a,so} et libsupc++.a
Répertoires installés: /usr/include/c++, /usr/lib/gcc, /usr/share/gcc-4.5.3

Descriptions courtes

c++

Le compilateur C++

cc

Le compilateur C

cpp

Le préprocesseur C ; il est utilisé par le compilateur pour l'extension des instructions #include, #define et d'autres instructions similaires dans les fichiers sources

g++

Le compilateur C++

gcc

Le compilateur C

gccbug

Un script shell utilisé pour aider à la création de bons rapports de bogues

gcov

Un outil de tests ; il est utilisé pour analyser les programmes et savoir où des optimisations seraient suivies du plus d'effet

libgcc

Contient un support en exécution pour gcc

libgcov

Cette bibliothèque est liée à un programme on demande à GCC d'activer le profiling

libgomp

Implémentation GNU de l'API OpenMP API pour la programmation en mémoire parallèle partagée pour plusieurs plateforme en C/C++ et Fortran

libmudflap

Contient des routines qui supportent la fonctionnalité de test des limites de GCC

libssp

Contient des routines supportant la fonctionalité de GCC de protection contre les débordements de mémoire

libstdc++

La bibliothèque C++ standard

libsupc++

Fournit des routines de support pour le langage de programmation C++