5.8. GCC-4.6.2 - 2. Durchgang

5.8.1. Installation des GCC

Zuerst packen wir wieder aus:

tar -xjf pakete/gcc-4.6.2.tar.bz2 &&
cd gcc-4.6.2/

und dazu kommt gleich einmal eine Reparatur:

patch -Np1 -i ../patches/gcc-4.6.2-startfiles_fix-1.patch

Warum? Der GCC nach 4.3 verhält sich wie ein verirrter Kompiler und sucht daher nicht mehr dort nach den Startdateien, die dort mit dem --prefix angegeben sind. Jetzt wäre das nicht mehr hilfreich und so wird GCC zu einem ordentlichen Verhalten angehalten.

Normalerweise wird mit dem Skript fixincludes versucht, eventuelle defekte Dateien für GCC zu reparieren. Wir haben bereits ein installiertes GCC, Glibc und die dazugehörigen Dateien sind soweit mit dem Vermerk fehlerfrei versehen und ein fixincludes wäre nicht sinnvoll. Ja ein neuer Durchgang wäre nicht nur nicht hilfreich, sondern schon genau deswegen schlecht, könnten doch dabei Dateien des Muttersystems wieder einbezogen werden. In jedem Fall bewahrt uns das Folgende vor genau diesen Gefahren:

cp -v gcc/Makefile.in{,.orig} &&
sed 's@\./fixinc\.sh@-c true@' gcc/Makefile.in.orig > gcc/Makefile.in

Bei Architekturen der Art x86 wird ein Bau der Art bootstrap mit der Marke -fomit-frame-pointer beim Compiler verwendet. Ohne bootstrap wird das aber verschluckt und wollen wir trotzdem diese Marke (flag) und genau einen Compiler, als ob der wie einer mit bootstrap wäre, hilft folgender Befehl:

cp -v gcc/Makefile.in{,.tmp} &&
sed 's/^T_CFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in.tmp > gcc/Makefile.in

Mit der folgenden Befehlsfolge wird für GCC der Ort des voreingestellten dynamischen Linkers dahin gehend geändert, dass nur mehr der in /tools verwendet wird. Auch wird der Weg /usr/include aus dem Verzeichnis der Pfade gestrichen, die GCC beim Suchen verwendet. Und jetzt wird beim Bau von GCC genau unser neuer Linker beim Kompilieren eingeprägt und ab sofort kennen alle übersetzten Programme nur mehr die Verbindung zu unserer neuen Glibc.

for file in \
 $(find gcc/config -name linux64.h -o -name linux.h -o -name sysv4.h)
do
  cp -uv $file{,.orig}
  sed -e 's@/lib\(64\)\?\(32\)\?/ld@/tools&@g' \
  -e 's@/usr@/tools@g' $file.orig > $file
  echo '
#undef STANDARD_INCLUDE_DIR
#define STANDARD_INCLUDE_DIR 0
#define STANDARD_STARTFILE_PREFIX_1 ""
#define STANDARD_STARTFILE_PREFIX_2 ""' >> $file
  touch $file.orig
done

Wir analysieren ein wenig: Finden wir zuerst noch alle Dateien im Verzeichnis gcc/config mit den Namen linux.h, respektive linux64.h und sysv4.h, kopieren wir die mit der Endung „.orig“ beiseite. Dann stellt sed vor jede Datei /tools vor allen in /lib/ld und beim folgenden Durchgang noch einmal ein /usr davor. Dann werden an das Ende sowohl die Suchpfade, als auch für die Startdatei neu geschrieben. Mit cp -u werden die Originaldateien davor bewahrt, versehentlich umgeschrieben zu werden.

Wieder kommen die folgenden Pakete dazu:

tar -xjf ../pakete/mpfr-3.1.0.tar.bz2 &&
mv -v mpfr-3.1.0 mpfr &&
tar -xjf ../pakete/gmp-5.0.2.tar.bz2 &&
mv -v gmp-5.0.2 gmp &&
tar -xzf ../pakete/mpc-0.9.tar.gz &&
mv -v mpc-0.9 mpc

Erneut legen wir das separate Buildverzeichnis an:

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

Noch einmal und ganz wichtig, wir ändern die Umgebungsvariablen dahingehend, dass sie nicht die Optimierungsmarken zerstören:

CC="$MOLLI_TGT-gcc -B/tools/lib/" \
    AR=$MOLLI_TGT-ar RANLIB=$MOLLI_TGT-ranlib \
    ../gcc-4.6.2/configure --prefix=/tools \
    --with-local-prefix=/tools --enable-clocale=gnu \
    --enable-shared --enable-threads=posix \
    --enable-__cxa_atexit --enable-languages=c,c++ \
    --disable-libstdcxx-pch --disable-multilib \
    --disable-bootstrap --disable-libgomp \
    --without-ppl --without-cloog \
    --with-mpfr-include=$MOLLI/sources/gcc-4.6.2/mpfr/src \
    --with-mpfr-lib=$MOLLI/sources/gcc-build/mpfr/src/.libs

Ein wenig Erklärung auch dazu, soweit noch notwendig:

--enable-clocale=gnu

Damit sollte das einzig wahre locale für die C++ Bibliotheken garantiert werden. Steht da vielleicht kein de_DE, dann kann es ein Problem geben bei nicht passenden Application Binary Interface (ABI) C++ Bibliotheken, die dann nicht recht zusammenarbeiten wollen.

--enable-threads=posix

Damit können die Ausnahmen für C++ und dabei möglichen mehrfach aufgereihten Programmabläufen Platz greifen.

--enable-__cxa_atexit

damit kann man __cxa_atexit statt nur atexit zur Merken von C++ destructors bei lokalen Statistiken und globalen Objekten nutzen und das brauchen die eben für die mitverwendeten C++ Bibliotheken und C++ Programmen wie auch für Application Binary Interface (ABI) und Anwendungen auch anderer Linux Versionen.

--enable-languages=c,c++

Jetzt endlich kann auch C++ übersetzt werden.

--disable-libstdcxx-pch

Vorgefertigte Dateien (header) sollen nicht verwendet werden. Die sind nutzlos und auch Platzverschwendung.

--disable-bootstrap

GCC ist berufen, mit bootstrap zu arbeiten. Jetzt wird aber GCC beim Bau nicht nur ein einziges Mal durchlaufen, sondern drei Mal, und auch wenn bei den weiteren Durchgängen eher nur mehr auf flüssigen Durchgang Wert gelegt wird, ein bootstrap ist dabei nicht unbedingt notwendig.

Das Paket kompilieren:

make

Nun installieren:

make install

Es wird noch eine weiche Anknüpfung notwendig, weil immer noch Programme cc statt gcc haben wollen, wie auch UNIX. Auch manche Administratoren sind versucht, das zu verwenden:

ln -vs gcc /tools/bin/cc

Nun verlassen wir das Verzeichnis und löschen es:

cd .. &&
rm -rf gcc-*
[Achtung]

Achtung

an diesem Punkt ist es absolut wichtig unseren neuen Kompiler zu testen:

echo 'main(){}' > dummy.c &&
cc dummy.c &&
readelf -l a.out | grep ': /tools'

Das Ergebnis sollte wieder folgendes sein:

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

Bei einem 64bit System sollte es dies sein:

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

Vor den dynamischen Linkern soll noch /tools/lib stehen, gibt es auch da wieder anders lautende Ergebnisse oder gar keine, ist da das Ende, bis der Fehler gefunden ist. Gerne schleichen sich Fehler bei Pfaden ein, Kontrolle echo $PATH, bei der weichen Anbindung „ln“, wenn man nicht als Benutzer molli arbeitet und bei dessen Umgebung und erst wenn alle Fehler beseitigt sind, mache man das:

rm -v dummy.c a.out