Dieser Abschnitt soll Ihnen einige technische Details zum gesamten Kompilier- und Installationsprozess erläutern. Sie müssen nicht alles in diesem Abschnitt sofort verstehen, das Meiste ergibt sich von selbst sobald Sie die ersten Pakete installiert haben. Scheuen Sie sich nicht, zwischendurch noch einmal hierhin zurückzublättern und nachzulesen, wenn etwas unklar ist.
In Kapitel 5 soll eine gut funktionierende temporäre Arbeitsumgebung erschaffen werden, in die Sie sich später abkapseln und von wo aus Sie in Kapitel 6 ohne Schwierigkeiten ein sauberes endgültiges LFS-System erstellen können. Sie werden sich so weit wie möglich vom Host-System abschotten und eine in sich geschlossene Toolchain erzeugen. Bitte beachten Sie, dass der gesamte Vorgang dafür ausgelegt ist, die Risiken für neue Leser zu minimieren und gleichzeitig den Lerneffekt zu maximieren.
Bevor Sie fortfahren, sollten Sie den Namen der Plattform kennen,
auf der Sie LFS installieren; diesen bezeichnet man oft auch als
das Ziel-Tripplet. Für die
meisten Leser wird das Ziel-Tripplet zum Beispiel i686-pc-linux-gnu sein. Sie können Ihr
Ziel-Tripplet herauszufinden, indem Sie das Skript config.guess auszuführen; es wird
mit den Quellen vieler Pakete mitgeliefert. Entpacken Sie die
Binutils-Quellen und führen Sie das Skript aus: ./config.guess
. Notieren Sie die
Ausgabe.
Auch den Namen des dynamischen
Linkers für Ihre Plattform sollten Sie kennen (manchmal
wird der Linker auch als dynamischer
Lader bezeichnet). Bitte verwechseln Sie den
dynamischen Linker nicht mit dem Standard-Linker ld aus dem Paket Binutils. Der
dynamische Linker kommt mit Glibc und seine Aufgabe ist es, die von
einem Programm benötigten gemeinsamen Bibliotheken zu finden und zu
laden, das Programm zur Ausführung vorzubereiten und schließlich
das Programm selbst auszuführen. Im Regelfall wird der Name des
dynamischen Linkers ld-linux.so.2
sein. Für weniger gängige Systeme könnte der Name auch ld.so.1
sein und auf neueren 64-Bit-Plattformen
könnte er sogar völlig verschieden sein. Sie müssten den Namen
Ihres dynamischen Linkers herausfinden können, wenn Sie auf Ihrem
Host-System in den Ordner /lib
schauen. Um wirklich sicher zu gehen, können Sie eine beliebige
Binärdatei auf Ihrem Host-System überprüfen: readelf -l <Name einer Binärdatei> | grep
interpreter
. Notieren Sie die Ausgabe. Eine
Referenz, die alle Plattformen abdeckt, finden Sie in der Datei
shlib-versions
im Basisordner des
Glibc-Quellordners.
Hier ein paar technische Anmerkungen zum Kompiliervorgang in Kapitel 5:
Der Kompiliervorgang ist im Grunde ähnlich wie Cross-Kompilieren. Dabei funktionieren Programme im selben Prefix in Kooperation und benutzen dazu ein wenig GNU-„Magie“.
Durch vorsichtiges Anpassen des Suchpfades für den Standard-Linker erreichen Sie, dass Programme nur gegen die gewünschten Bibliotheken gelinkt werden.
Durch vorsichtiges Anpassen von gccs specs
-Datei teilen Sie dem Compiler mit,
welcher Dynamische Linker verwendet wird.
Als erstes wird Binutils installiert, da sowohl GCC als auch Glibc beim Durchlaufen des configure-Skriptes einige Tests zum Assembler und Linker durchführen und auf dem Ergebnis basierend bestimmte Funktionen ein- bzw. ausschalten. Das ist wichtiger als man zunächst denken mag. Ein falsch eingerichteter GCC oder Glibc kann zu Fehlern in der Toolchain führen, die erst am Ende der Installation des LFS-Systems bemerkt werden. Zum Glück weisen Fehlschläge beim Durchlaufen der Testsuites im Regelfall auf solche Probleme hin, bevor zuviel Zeit vergeudet wird.
Binutils installiert seinen Assembler an zwei Stellen, /tools/bin
und /tools/$ZIEL_TRIPPLET/bin
. In Wirklichkeit sind die
Programme an der einen Stelle mit denen an der anderen durch einen
harten Link verknüpft. Ein wichtiger Aspekt des Linkers ist seine
Suchreihenfolge für Bibliotheken. Genaue Informationen erhalten Sie
mit ld und dem
Parameter --verbose
. Zum
Beispiel: ld --verbose | grep
SEARCH
gibt die aktuellen Suchpfade und ihre
Reihenfolge aus. Sie können sehen, welche Dateien tatsächlich von
ld verlinkt werden,
indem Sie ein Dummy-Programm kompilieren und den Parameter --verbose
angeben. Zum Beispiel:
gcc dummy.c -Wl,--verbose 2>&1
| grep succeeded
zeigt, dass alle Dateien beim Linken
erfolgreich geöffnet werden konnten.
Das nächste zu installierende Paket ist GCC. Während des Durchlaufs von configure sehen Sie zum Beispiel:
checking what assembler to use...
/tools/i686-pc-linux-gnu/bin/as
checking what linker to use... /tools/i686-pc-linux-gnu/bin/ld
Das ist aus den oben genannten Gründen wichtig. Hier wird auch
deutlich, dass GCCs configure-Skript nicht die PATH
-Ordner durchsucht, um herauszufinden, welche
Werkzeuge verwendet werden sollen. Dennoch werden beim tatsächlichen
Ausführen von gcc nicht
unbedingt die gleichen Suchpfade verwendet. Welchen Standard-Linker
gcc wirklich verwendet,
kann man mittels gcc
-print-prog-name=ld
herausfinden.
Detaillierte Informationen erhält man von gcc, indem man den Parameter
-v
beim Kompilieren eines
Dummy-Programmes übergibt. gcc -v
dummy.c
zum Beispiel gibt Informationen über den
Präprozessor, Komilierungs- und Assemblierungsphasen inklusive
gccs Suchpfaden und der
Reihenfolge aus.
Das nächste zu installierende Paket ist Glibc. Die wichtigsten
Überlegungen zum Kompilieren von Glibc beschäftigen sich mit dem
Compiler, Binutils und den Kernel-Headern. Der Compiler ist
normalerweise kein Problem, weil Glibc immer den gcc nimmt, der in den PATH
-Ordnern gefunden wird. Die Binutils und die
Kernel-Header können da schon etwas schwieriger sein. Daher gehen wir
kein Risiko ein und benutzen die verfügbaren configure-Optionen, um die
korrekten Entscheidungen zu erzwingen. Nach dem Durchlauf von
./configure können Sie
den Inhalt von config.make
im Ordner
glibc-build
nach den Details
durchsuchen. Sie werden ein paar interessante Dinge finden, wie zum
Beispiel CC="gcc
-B/tools/bin/"
zum Kontrollieren der verwendeten
Binutils, oder die Parameter -nostdinc
und -isystem
zum Kontrollieren des
Suchpfades des Compilers. Diese Besonderheiten heben einen wichtigen
Aspekt von Glibc hervor — Sie ist kompiliertechnisch gesehen
eigenständig und nicht von Voreinstellungen der Toolchain abhängig.
Nach der Installation von Glibc nehmen Sie noch ein paar Anpassungen
vor; dadurch stellen Sie sicher, dass Suchen und Verlinken nur
innerhalb unseres Prefix /tools
stattfindet. Sie installieren einen angepassten ld, welcher einen fest angegebenen
Suchpfad auf /tools/lib
hat. Dann
bearbeiten Sie die specs
-Datei von
gcc so, dass sie auf
den neuen Dynamischen Linker in /tools/lib
verweist. Der letzte Schritt ist
entscheidend für den gesamten Ablauf. Wie oben bereits angemerkt,
wird ein fest eingestellter Pfad zum Dynamischen Linker in jeder
ausführbaren ELF-Datei eingebettet. Sie können das überprüfen, indem
Sie dieses Kommando ausführen: readelf -l <Name der ausführbaren Datei> |
grep interpreter
. Durch das Anpassen der specs-Datei
von gcc stellen wir sicher, dass jedes von nun an kompilierte
Programm bis zum Ende des Kapitels unseren neuen Dynamischen Linker
in /tools/lib
benutzt.
Weil unbedingt der neue Linker verwendet werden muss, wird der
Specs-Patch auch im zweiten Durchlauf von GCC angewendet. Hierbei
darf kein Fehler passieren, denn sonst würden die GCC-Programme
selbst den Linker aus /lib
im
Host-System verwenden. Eine saubere Trennung vom Host-System wäre
dann nicht mehr gegeben und unser Ziel wäre verfehlt.
Im zweiten Durchlauf der Binutils können Sie den configure-Parameter
--with-lib-path
benutzen, um
den Bibliotheksuchpfad von ld zu kontrollieren. Von diesem
Punkt an ist die Toolchain unabhängig. Die verbleibenden Pakete aus
Kapitel 5
kompilieren alle mit der neuen Glibc in /tools
und alles ist in Ordnung.
Aufgrund ihrer bereits erwähnten eigenständigen Natur ist die Glibc
das erste wichtige Paket, das Sie nach dem Eintreten in die
chroot-Umgebung in Kapitel
6 installieren. Wenn die Glibc erstmal nach /usr
installiert ist, werden Sie schnell ein paar
Voreinstellungen in der Toolchain ändern und dann schreiten Sie mit
dem Erstellen des endgültigen LFS-Systems fort.