LFS - Linux From Scratch

Linux selber bauen - Schritt für Schritt.

Einführung

Nicht zuletzt aufgrund des Rummels um die Abkündigung von Urgesteinen wie CentOS 8 auf Ende 2021 und daraus entstehenden Diskussionen um Alternativen wie Rocky Linux mag sich so mancher überlegt haben, ein eigenes Linux zu bauen. Dieser Artikel erklärt auf Basis von Linux from Scratch (LFS), wie das funktioniert.

Linux from Scratch (LFS) und Beyond Linux From Scratch (BLFS) sind online verfügbare Anleitungen bzw. Bücher, die das Compilieren und Zusammenstellen eines eigenen Linux-Systems direkt aus frei verfügbaren Quellen Schritt für Schritt beschreiben. Hier wird die Abkürzung LFS sowohl für die Dokumentation als auch für das daraus entstehende Linux-System verwendet. LFS und BLFS werden meist zweimal im Jahr im März und im September aktualisiert.

1998 begann Gerard Beekmans, der Autor von LFS, sich mit Linux zu beschäftigen. Nach Einsatz diverser Distributionen reifte die Erkenntnis, dass es für ihn kein „one size fits all“ gibt, und es vielleicht ein eigenes System sein sollte - Open Source bot ihm per Definition die Möglichkeit dazu. Er begann zu compilieren und sich mit Compile-Time-Errors sowie zirkulären Abhängigkeiten auseinanderzusetzen. Die gesammelten Erfahrungen, die er mit der Linux-Community teilte, stiessen auf so breites Interesse, dass daraus das Projekt „LFS“ entstand.

../_images/lfs3.png

LFS bei der Arbeit

LFS versucht soweit wie möglich, dem POSIX.1-2008-Standard, der ein Betriebssystem-Interface mit Environment zu Portabilitätszwecken definiert, dem Filesystem Hierarchy Standard (FHS) Version 3.0 sowie der Linux Standard Base (LSB) Version 5.0 (2015) zu folgen. Die Linux Standard Base definiert vier - teils kontrovers diskutierte - Standards für Core, Desktop, Runtime Languages und Imaging, die LFS schon aufgrund seiner minimalen Software-Ausstattung nur in Teilen umsetzen kann. Aber man hat die Trümpfe ja in der Hand, dies zu ändern…

Wer der Anleitung folgt, erhält Stand LFS v10.1 von März 2021 ein minimales Linux-System mit

  • Ext4-Dateisystem

  • GRUB 2.04

  • Kernel 5.10.17

  • Bash 5.1

  • GCC 10.2

  • Perl 5.32.1

  • Python 3.9.2

  • Vim 8.2

Man hat die Wahl zwischen LFS mit SysVinit-basiertem Bootsystem und LFS mit Systemd und D-Bus . Dieser Artikel behandelt die letztere Variante. Die Vorteile: Mit Systemd erhält LFS nicht nur das modernere Boot-System, sondern auch einen DHCP- und NTP-Client sowie andere Kleinigkeiten, die in der SysVinit-Variante erst im BLFS behandelt werden.

Mit dem Herunterladen der Kernel-Quellen und dem Anwerfen des C-Compilers ist es nicht getan. LFS unterteilt das Erstellen eines Linux-Systems in drei relevante Teile: die Konfiguration eines Build-Hosts (Part II, Abschnitt 2 bis 4), das Bauen einer Cross-Toolchain und nur temporär benötigter Tools (Part III, Abschnitt 5 bis 7) und erst daran anschliessend die Erstellung des eigentlichen LFS-Systems (Part IV, Abschnitt 8 bis 11). Die Abschnitte 2 bis 11 werden hier zusammengefasst beschrieben und so auch in den Shell-Kommentaren am Ende des Artikels referenziert.

Im Gegensatz zum LFS-Buch folgt man der BLFS-Anleitung übrigens nicht linear, sondern sucht sich aus über 50 Abschnitten diejenigen aus, welche das eigene Linux in die gewünschte Richtung bringen. Da von Security über Virtualisierung bis hin zu Desktop-Umgebungen so ziemlich alle Bereiche und die gängigsten Software-Pakete abgehandelt werden, verwundert es nicht, dass BLFS ungefähr dreimal so umfangreich wie LFS ist.

Dieser Artikel fasst die LFS-Anleitung zusammen und erklärt zunächst die Prinzipien und die Vorgehensweise. Am Ende des Artikels finden sich die Kommandos, die - soweit wie möglich - per Copy & Paste auf einem CentOS 8 Build-Host auszuführen sind, um in einem Rutsch zum ersten, selbst gebauten Linux zu kommen. Die Anleitung hier verfrachtet /home darüber hinaus auf eine eigene Partition und bereitet die LFS-Disk auf einen autarken Boot vor.

Das Bauen nimmt Zeit in Anspruch. Zur Orientierung: Mit der hier beschriebenen Test-VM unter KVM auf Basis eines Core i7 10th Gen mit NVMe dauert der Build auch mit abgeschalteten Tests mehrere Stunden.

Wer nach dem Build, dem Boot in LFS und den ersten Tests tiefer in die Materie eintauchen möchte, sei auf die vorbildliche Original-Dokumentation verwiesen.

Links

Da linuxfromscratch.org so seine Mühen mit Geschwindigkeit und Erreichbarkeit hat, empfiehlt sich die Nutzung einer der Mirror-Server.

Selber bauen oder nicht?

Man kann sich natürlich fragen, ob der Bau eines eigenen Linux-Systems lohnt, wo man doch aus einer breiten Masse an Distributionen auswählen kann. Das Team um den LFS-Projektleiter Gerard Beekmans hat darauf mehrere Antworten:

  • Das Projekt möchte zeigen, wie Linux gebaut wird, aus welchen Komponenten Linux besteht, wie diese zusammenarbeiten und voneinander abhängen. Wer will kann LFS jedoch als Ausgangspunkt für eigene Weiterentwicklungen nutzen.

  • Mit LFS erhält man ein aktuelles, funktionierendes und sehr kompaktes Linux-System, was aus nicht viel mehr als dem Kernel und ein paar Tools besteht. Die Doku berichtet von einem auf LFS laufenden Apache mit einer Gesamtgrösse von 8 MB und weniger, was besonders für Embedded Systeme von Interesse sein kann.

  • Wer selber baut, ist extrem flexibel. Mit LFS erhält man den Rohbau eines Hauses, aus dem sich ganz nach Geschmack ein individuelles Zuhause vom 1-Zimmer-Apartment bis zum Luxus-Resort gestalten lässt.

  • Security: LFS lässt sich bei Bedarf komplett auditieren, und - vielleicht noch wichtiger - man hat das Management aller Sicherheitspatches selbst in der Hand. Mehr Kontrolle als bei LFS über das, was auf dem System läuft, kann man nicht haben.

Und zugegeben, es ist einfach cool. Man stelle sich die Situation vor:

Guy: BTW I use Arch.
You: :-)

Um die Erwartungen etwas zu dämpfen: Im produktiven Betrieb lässt sich mit LFS nicht komfortabel arbeiten. Ein SSH-Daemon fehlt, Werkzeuge wie sudo, wget oder parted sind nicht mit an Bord. Das Dateisystem wird beispielsweise nicht durch LVM verwaltet, und der Netzwerk-Stack ist alles andere als komplett. Das wird zwar im Rahmen von BLFS als Advanced Topic nachgeliefert, ein Paket-Manager kommt aber im ganzen Projekt nicht zum Einsatz. Man muss seine eigene Distribution daher per Download und Compile selbst aktuell halten und regelmässig mit Updates und Sicherheitspatches versorgen. Wer auf Slackware & Co. zu Hause ist, wird sich LFS jedoch auch in dieser Hinsicht erweitern können, indem ein Manager wie Pacman oder GNU Stow hinzugefügt oder eine Strategie wie der Package User-Ansatz verfolgt wird. Überhaupt gilt im Projekt: Linux-Kenntnisse werden nicht vermittelt, sie werden vorausgesetzt.

Bis zur echten Linux-Distribution ist es ohnehin noch ein weiter Weg, zeichnen sich diese doch durch Merkmale aus wie:

  • eine aktive User Community

  • QA-geprüfte Pakete inkl. Errata und Patch-Management

  • ein umfangreiches Mirror-Netzwerk

  • zuständige und kontaktierbare Entwickler

  • Umsysteme wie Wiki, IRC-Chat, Mailinglisten, Foren, Bug Tracker, FAQ, …

Ob sich neben dem Lerneffekt auch ein praktischer Nutzen findet, hängt also wie immer von den eigenen Anforderungen ab. Mit LFS bekommt man jedenfalls ansatzweise ein Gefühl dafür, welcher Invest an Zeit und Know-How im Linux-Kernel, in Open Source Software und in allen Linux-Distributionen steckt.

Bemerkung

Neben LFS gibt es eine Reihe an Linux-Distributionsbaukästen, von denen die meisten auf den Embedded-Bereich spezialisiert sind und deren bekanntester Verteter BitBake aus dem Yocto-Projekt ist. Andere sind Linux Target Image Builder, OpenWrt oder Scratchbox.

Aufbau der LFS-Doku

Der Aufbau der Dokumentation entspricht geichzeitig dem Ablauf, um LFS zu bauen.

┌─────────────────────────────────────────────┐
│ Part II                                     │
│ Der Build-Host                              │
└──┬─┬────────────────────────────────────────┤
   │ ├────────────────────────────────────────┤
   │ │ 02. Build-Host aufsetzen               │
   │ ├────────────────────────────────────────┤
   │ │ 03. Pakete und Patches laden           │
   │ ├────────────────────────────────────────┤
   │ │ 04. Abschlussarbeiten vornehmen        │
   │ └────────────────────────────────────────┘
   │
┌──▼──────────────────────────────────────────┐
│ Part III                                    │
│ LFS Cross-Toolchain und temporäre           │
│ Tools bauen                                 │
└──┬─┬────────────────────────────────────────┤
   │ ├────────────────────────────────────────┤
   │ │ 05. Cross-Toolchain compilieren        │
   │ ├────────────────────────────────────────┤
   │ │ 06. Nur temporär benötigte Tools bauen │
   │ ├────────────────────────────────────────┤
   │ │ 07. Zusätzliche temporäre Tools bauen  │
   │ └────────────────────────────────────────┘
   │
┌──▼──────────────────────────────────────────┐
│ Part IV                                     │
│ LFS bauen                                   │
└────┬────────────────────────────────────────┤
     ├────────────────────────────────────────┤
     │ 08. Basis-Software installieren        │
     ├────────────────────────────────────────┤
     │ 09. System konfigurieren               │
     ├────────────────────────────────────────┤
     │ 10. System bootfähig machen            │
     ├────────────────────────────────────────┤
     │ 11. Abschluss und Reboot               │
     └────────────────────────────────────────┘

Der Build-Host

Build-Host aufsetzen

Ohne einen perfekt funktionierenden Build-Host geht es nicht. Diese Anleitung setzt daher eine unbenutzte, virtuelle Maschine auf Basis eines aktuellen CentOS 8.3 „Minimal Install“ mit BIOS-Boot voraus, fully patched. Der C-Compiler GCC profitiert von einem schnellen Core. Ein auf mehrere Cores verteilter, multi-threaded Build wird in der Dokumentation diskutiert, ist aber wegen immer mal wieder auftretender Race-Conditions nicht zu empfehlen.

Für den Build-Server genügen daher tatsächlich

  • 2 Cores

  • 2 GB RAM

  • SSD-basierter Hypervisor

  • Disks: 1x 10 GB (VirtIO, /dev/vda) für das System, 1x 20 GB (SATA oder SCSI, /dev/sda) für LFS

  • Netzwerkkarte: Intel e1000

Unbedingt darauf achten, VirtIO für die LFS-Disk und die Netzwerkkarte zu vermeiden, da die Anleitung keinen VirtIO-Support in den Kernel eincompiliert. LFS freut sich über eine virtuelle SATA- oder SCSI-Disk, die als /dev/sda erkannt wird, sowie eine klassische Intel e1000-Netzwerkkarte mit 1 Gbps. Die Disk-Bezeichnung wird wichtig, wenn es darum geht, LFS bootfähig zu machen. Der Name der Netzwerkkarte (beispielsweise enp1s0) spielt eine Rolle, falls Predictable Network Interface Names verwendet werden sollen.

Nach der CentOS-Installation müssen die für die ersten Build-Prozesse notwendigen Pakete installiert werden. Das benötigte makeinfo aus dem texinfo-Paket erhält man ab CentOS 8.3 aus dem „PowerTools“-Repo.

Die für den Build benötigten Pakete sind schnell installiert.
dnf -y install yum-utils
yum config-manager --set-enabled powertools
dnf -y install bison byacc bzip2 gcc-c++ patch perl python3 tar texinfo wget

Die von CentOS installierten Versionen sollten anschliessend mit Hilfe eines kleinen Skriptes geprüft werden: LFS v10.0 verlangt einen GCC ab Version 6.2 sowie GNU Make ab Version 4.0, die beispielsweise durch ein CentOS 7 nicht bereitgestellt werden.

Ist hier alles in Ordnung, wird die zweite Disk des Build-Hosts in die Partitionen /, swap und /home aufgeteilt, das Dateisystem mit ext4 erstellt und die für alle nachfolgenden Shell-Aufrufe essentielle Umgebungsvariable $LFS definiert, die den root-Mountpoint auflöst. Die Variable muss daher unter allen Umständen funktionieren. Das Setzen der Locale in CentOS 8 sollte noch erledigt und die zweite Disk gemountet werden.

/dev/sda wird per BIOS/MBR bootfähig gemacht und mit diversen Partitionen ausgestattet. Um der GRUB-eigenen core.img genügend Platz einzuräumen, startet die erste Partition für / mit 10 GB Grösse erst ab 1 MiB. Danach wird /swap mit 2 GB Grösse angelegt, der Rest der Disk ist für /home reserviert.

/boot benötigt in diesem Setup keine eigene Partition, sondern enthält als gewöhnliches Verzeichnis den Kernel sowie die Bootloader-Konfiguration. Eine eigene Partition wird erst dann nötig, falls ein Multiboot mit anderen Distributionen unterstützt werden soll, oder der Bootloader nicht mehr auf das root-Dateisystem zugreifen kann, was an fehlenden Treibern, an Disk-Encryption, an einem Software-RAID oder LVM liegen kann.

Hier geht’s zum CodeChapter02.

Pakete und Patches laden

Kapitel 3 der Dokumentation ist der Abschnitt, der LFS in seiner späteren Ausstattung definiert: neben den Build-Tools lädt man die gewünschten Quellen ausgewählter Software-Pakete herunter, die das System charakterisieren. Die Macher von LSF haben sich die Mühe gemacht, eine Vorauswahl zu treffen, deren Versionsabhängigkeiten aufzulösen und als Liste in einer Textdatei zusammenzufassen, die man herunterladen und ganz bequem wget übergeben kann. Damit nicht genug: das LFS-Team liefert sogar eine Reihe an Patches, mit denen Fehler gefixt oder die Pakete in ihrer Ausprägung an das zukünftige Zielsystem angepasst werden. Darüber hinaus erklären sie alle Optionen der jeweiligen configure-Aufrufe.

Die Software-Ausstattung inkl. Patches für LFS wird bequem per wget gezogen.
wget http://lfs.linux-sysadmin.com/lfs/downloads/stable-systemd/wget-list
wget --input-file=wget-list --continue --directory-prefix=$LFS/sources

Um die Checksummen der am Ende knapp 90 heruntergeladenen Pakete zu prüfen, hilft eine ebenfalls bereitgestellte md5sum-Checksummen-Liste.

Hier geht’s zum CodeChapter03.

Abschlussarbeiten vornehmen

In Kapitel 4 erstellt der Benutzer root die für den Build notwendigen Verzeichnisstrukturen $LFS/{bin,etc,lib,lib64,sbin,tools,usr,var} sowie den Benutzer lfs. Dieser wird Eigentümer der Build-Verzeichnisse. Anschliessend wird in den Benutzer lfs gewechselt und dessen Shell-Environment geleert und optimiert. Da das neue Environment eine non-login-Shell ist, muss mit einer .bashrc-Datei gearbeitet werden, um die Shell-Umgebung zu erweitern und anzupassen, zum Beispiel um Umgebungsvariablen wie $LFS, LC_ALL oder PATH.

Das Verzeichnis $LFS/tools wird den Cross-Compiler enthalten.

Ist hier alles getan, ist ein Neustart des Build-Hosts anzuraten, um sicherzugehen, dass der Build-Host ohne Altlasten daherkommt und funktioniert. Spätestens jetzt empfiehlt es sich, einen VM-Snapshot anzulegen.

Hier geht’s zum CodeChapter04.

LFS Cross-Toolchain und temporäre Tools bauen

Cross-Toolchain compilieren

In Kapitel 5 bleibt man mit dem Benutzer lfs angemeldet, für den die eigentliche Arbeit beginnt: das Bauen des Cross-Compilers und seiner Tools. Der Cross-Compiler und seine Tools landen temporär in $LFS/tools, die Bibliotheken werden bereits in ihren zukünftigen Orten installiert.

Der Ablauf zum Bau der Software-Pakete ist dann bis zum Schluss fast immer gleich:

  • Wechsel ins sources-Verzeichnis

  • Auspacken der Quell-Dateien mit Hilfe von tar xf

  • Wechsel ins erstellte Verzeichnis

  • bei Bedarf build-Verzeichnis erstellen

  • Paket compilieren

  • Paket installieren

  • das Source-Code-Verzeichnis löschen

Angewendet wird dies auf:

  • Linker und Assembler (erster Durchlauf)

  • Cross-Compiler (erster Durchlauf)

  • Linux API Headers

  • glibc

  • libstdc++, erster Durchlauf

Essentiell: Dieser Code testet den cross-compilierten GCC.
echo 'int main(){}' > dummy.c
$LFS_TGT-gcc dummy.c

# Displays the information contained in the file's segment headers, if it has any:
readelf -l a.out | grep '/ld-linux'
# should return something like
# [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

Hier geht’s zum CodeChapter05.

Nur temporär benötigte Tools bauen

Immer noch unter dem Benutzer lfs: Mit der vorher erzeugten Cross-Toolchain wird in Kapitel 6 unter anderem Bash, grep und der native LFS-GCC compiliert. Die Applikationen werden im bereits rudimentär erstellten LFS-Dateisystem installiert, sind aber noch nicht einsatzbereit, für bestimmte Aufgaben wird also immer noch das Host-System benötigt. Immerhin werden die in LFS installierten Bibliotheken bereits zum Linken verwendet. Wirklich genutzt werden die Applikationen erst im kommenden Abschnitt in der Chroot-Umgebung.

Temporär benötigt und compiliert werden

  • ein Macro-Prozessor

  • Linker und Assembler (zweiter Durchlauf)

  • der native GCC-Compiler (zweiter Durchlauf)

  • eine TUI-Bibliothek

  • Bash

  • Tools, die das System ändern, wie chmod, cp, dd etc.

  • file awk, grep, sed

  • gzip, tar, xz

  • make, diff, patch

Hier geht’s zum CodeChapter06.

Zusätzliche temporäre Tools bauen

Bis hierhin ist der Benutzer lfs Eigentümer des LFS-Dateisystems, was in Abschnitt 7 der LFS-Doku auf root geändert wird. Anschliessend werden die Devices console und null auf der Platte erzeugt, die ein Kernel beim Boot-Vorgang erwartet.

Durch die aufgelösten zirkularen Abhängigkeiten kann der Benutzer root zum ersten Mal in eine Chroot-Umgebung wechseln, die das Betriebssystem des Build-Hosts für weitere Aufgaben beinahe komplett aussperrt. Eine Ausnahme bildet der laufende Kernel: Damit die Chroot-Umgebung funktioniert, wird die Kommunikation mit diesem über Virtual Kernel File Systeme (VFS) konfiguriert. VFS sind Dateisysteme wie beispielsweise tmpfs, die keinen Plattenplatz beanspruchen und komplett im Hauptspeicher liegen. Normalerweise werden Geräte unterhalb von /dev als virtuelles Dateisystem gemountet und bei Erkennung oder beim ersten Zugriff während des Boot-Vorgangs durch Udev erstellt. Zu diesem Zeitpunkt fehlt Udev noch, also werden die benötigten Geräte manuell angelegt und per Bind-Mount eingehängt. Stolperfalle: Wer den LFS Build-Host später neustartet, muss auch die Mount-Befehle für die virtuellen Devices vor den weiteren Arbeiten erneut ausführen.

Normal: Beim ersten Wechsel in die Chroot meldet sich ein ungewöhnlicher Bash-Prompt - hier fehlt noch eine /etc/passwd.
(lfs chroot) I have no name!:/#

Die endgültige Verzeichnisstrukur inklusive korrekt gesetzter Berechtigungen plus einiger Log-Dateien wird angelegt. Die Verzeichnisstruktur verwendet den Filesystem Hierarchy Standard (FHS) und legt unter anderem die Verzeichnisse {boot,home,mnt,opt,srv} an, lässt unnötiges wie /usr/local/games aber weg.

Fehlen noch Standard-Benutzer und -Gruppen. Da es hier keine einheitlichen Vorgaben gibt, orientiert sich LFS an Udev und anderen Distributionen.

Compiliert und installiert werden anschliessend noch Programme, um andere Programme zu testen (diese werden unter einem temporär angelegten Benutzer tester ausgeführt), sowie fehlende Bausteine der Toolchain:

  • als erstes libstdc++ (zweiter Durchlauf)

  • ein Paket für Internationalisierungs- und Lokalisierungs-Support

  • ein Parser-Generator

  • Perl und Python

  • Tools für Info-Pages

  • kleinere Utilities wie blkid, dmesg u.a.

Die Toolchain ist jetzt komplett und unabhängig vom Build-Host.

Am Ende des Abschnitts kümmert sich die LFS-Doku noch um Stripping, Backups und Restore, worauf hier im Code aber verzichtet wird.

Hier geht’s zum CodeChapter07.

LFS bauen

Basis-Software installieren

../_images/lfs4.png

Die Build-Scripte bei der Arbeit: kilometerlange Textwüsten wabern über den Screen.

In diesem Abschnitt der LFS-Dokumentation wird zunächst ein Ausblick auf das Thema Paket-Management gegeben und begründet, warum das Projekt keinen dokumentiert - es würde schlicht den Rahmen sprengen und nicht zur Ausrichtung von LFS passen. Anschliessend ist hier Fleissarbeit angesagt. So kümmert man sich in Kapitel 8 per configure/make/make install darum, dass neben wichtigen Bibliotheken eine ganze Reihe an Applikationen auf der Platte landen, unter anderem:

  • die Bash

  • Text-Prozessoren wie awk, grep, sed

  • Packer und Archiv-Programme wie bzip, gzip, tar und xz

  • GCC

  • der Bootloader GRUB

  • Man und ManDB

  • OpenSSL

  • Perl und Python

  • der Text-Editor Vim

  • Udev, welches sich um Geräte kümmert

Die Übersetzung des GCC in diesem Abschnitt ist der mit Abstand zeitintensivste Task im gesamten Projekt - fast die Hälfte der gesamten Compile-Time wird für diesen Schritt benötigt, was an der Ausführung der Test-Suites liegt. Jede Menge FAILED-Meldungen sind hier normal, solange ein grep auf die von der Testsuite erzeugten Log-Dateien die erwarteten Ergebnisse liefert.

Tipp

Die Unit-Tests werden durch verschiedene Variationen des Befehls make check oder make test ausgeführt, teils unter dem Benutzer „tester“ (per su tester -c) - wer diese überspringt, spart (erheblich) Zeit, riskiert aber auch, das ein oder andere Problem im Build-Prozess zu übersehen.

Nach der ganzen Arbeit wird aufgeräumt: nicht mehr benötigte Bibliotheken und Tools werden genau so entfernt wie der temporäre Benutzer tester. Ist der Nutzer des kommenden LFS kein Programmierer und/oder wird keine Debugging-Funktionalität benötigt, kann 2 GB Platz durch Bereinigung von Debugging-Symbolen eingespart werden (was im Code-Abschnitt berücksichtigt wird). Die Chroot-Umgebung wird verlassen, um sie gleich danach mit eingeschaltetem Bash Path-Hashing (und von dort an immer mit dieser Konfiguration) zu betreten.

Während der Compile-Vorgänge auftretende Warnungen in Bezug auf C-Syntax können übrigens ignoriert werden.

Hier geht’s zum CodeChapter08.

System konfigurieren

In Kapitel 9 konfiguriert man den Netzwerk-Stack: Hier lässt sich auf Wunsch die Verwendung der sogenannten „Predictable Network Interface Device Names“ abschalten, was wir tun. Die erste Netzwerkkarte im System wird von LFS somit später immer klassisch als eth0 erkannt. Die IP-Adresse wird per DHCP bezogen. Anschliessend wird die Namensauflösung konfiguriert und ein Hostname vergeben. Kleinere Konfigurationsarbeiten an der Systemuhr, der Linux-Konsole und der System Locale runden das System ab (im Listing wird ein Schweizerdeutsches Tastaturlayout eingestellt). Wer sich unsicher ist, was passende Locales sein könnten, sucht sich in LFS aus /usr/share/keymaps und /usr/share/consolefonts das passende heraus.

Ein Weg, um auf klassische Interface-Namen umzuschalten.
ln -s /dev/null /etc/systemd/network/99-default.link

Hier geht’s zum CodeChapter09.

System bootfähig machen

Es wird Zeit, LFS bootfähig einzurichten. Abschnitt 10 startet mit dem Anlegen einer /etc/fstab, die auf die LFS-Partitionen sda1 (System) und sda2 (Swap) verweist. Anschliessend (und erst jetzt) wird der Linux-Kernel gebaut und installiert. Da bei späteren Erweiterungen wie beispielsweise in BLFS immer mal wieder Umkonfigurationen am Kernel notwendig sind, wird dessen Source Code nach dem Build nicht gelöscht. Mit Hilfe von grub-install findet der Boot-Loader seinen Weg auf die Platte, der anschliessend noch per grub-mkconfig konfiguriert wird.

Der Kernel wird im Code-Abschnitt per make defconfig ohne Interaktion mit sinnvollen Default-Werten konfiguriert.

Wer mag, ändert das und nutzt die TUI-Variante per make menuconfig, um die unzähligen Parameter des Kernels manuell zu setzen. Wichtig: IPv6 wird von den Machern von Systemd unbedingt empfohlen. Dann sollten diese Kernel-Features ein- bzw. abgeschaltet sein:

General setup -->
   [ ] Auditing Support [CONFIG_AUDIT]
   [*] Control Group support [CONFIG_CGROUPS]
   [ ] Enable deprecated sysfs features to support old userspace tools [CONFIG_SYSFS_DEPRECATED]
   [*] Configure standard kernel features (expert users) [CONFIG_EXPERT] --->
      [*] open by fhandle syscalls [CONFIG_FHANDLE]
Processor type and features  --->
   [*] Enable seccomp to safely compute untrusted bytecode [CONFIG_SECCOMP]
Firmware Drivers  --->
   [*] Export DMI identification via sysfs to userspace [CONFIG_DMIID]
Networking support  --->
  Networking options  --->
   <*> The IPv6 protocol [CONFIG_IPV6]
Device Drivers  --->
  Generic Driver Options  --->
   [ ] Support for uevent helper [CONFIG_UEVENT_HELPER]
   [*] Maintain a devtmpfs filesystem to mount at /dev [CONFIG_DEVTMPFS]
   Firmware Loader --->
      [ ] Enable the firmware sysfs fallback mechanism [CONFIG_FW_LOADER_USER_HELPER]
File systems  --->
   [*] Inotify support for userspace [CONFIG_INOTIFY_USER]
  Pseudo filesystems  --->
   [*] Tmpfs POSIX Access Control Lists [CONFIG_TMPFS_POSIX_ACL]

Die erhabensten Momente im Build-Prozess:

cp -iv arch/x86/boot/bzImage /boot/vmlinuz-5.10.17-lfs-10.1-systemd
cp -iv System.map /boot/System.map-5.10.17
cp -iv .config /boot/config-5.10.17

# ...

grub-install /dev/sda
grub-mkconfig --output=/boot/grub/grub.cfg

Hier geht’s zum CodeChapter10.

Abschluss und Reboot

LFS ist nun vollständig installiert. Stolz darf man sich in den beiden Dateien /etc/lsb-release und /etc/os-release verewigen. Ein Logout aus der Chroot, Setzen eines Root-Passwortes, Unmounting von $LFS - und einem Reboot steht nichts mehr im Weg. Ist die LFS-Disk als primäres Bootmedium in der Build-VM ausgewählt, meldet sich nach kurzer Zeit LFS.

Hier geht’s zum CodeChapter11.

../_images/lfs2.png

LFS während des Boot-Vorgangs

../_images/lfs1.png

Das LFS GRUB-Bootmenü

../_images/lfs0.png

Boot-Device (2) im KVM BIOS-Bootmenü auswählen

Cross-Compiler erklärt

Um den Einfluss des Betriebssystems des Build-Hosts auf LFS zu minimieren und unabhängig von diesem zu werden, erstellen Abschnitt 5 und 6 einen eigenen Cross-Compiler plus Tools, mit deren Hilfe LFS gebaut wird. Deren Lebenszeit ist begrenzt, die Tools werden nur für diesen Zweck in einer isolierten Chroot eingesetzt und anschliessend entfernt.

Der Build-Prozess basiert auf dem Prinzip der Cross-Compilation: Ein Cross-Compiler produziert Code für andere Maschinentypen, wird also normalerweise dazu verwendet, Compiler für andere System-Architekturen zu übersetzen. Auf unserer Build-Maschine ist das theoretisch nicht nötig, da mit hoher Wahrscheinlichkeit auf x86_64 für x86_64 gebaut wird. LFS soll aber auf jeden Fall frei von hineingelinkter Software des Build-Hosts sein, was cross-compilierte Software garantiert - daher der Aufwand.

Um die Vorgehensweise zu verdeutlichen, nimmt die LFS-Dokumentation drei Hosts mit jeweils unterschiedlichen Architekturen an.

  • Host A besitzt einen Compiler compilerA für die eigene Architektur. Der Host ist langsam und seine Kapazitäten begrenzt.

  • Host B besitzt keinen Compiler, ist aber schnell und gut ausgestattet. Dieser soll Software für Host C produzieren.

  • Host C mit nochmals anderer Architektur besitzt ebenfalls keinen Compiler und ist klein und langsam.

Es werden zwei Cross-Compiler cross-compilerA und cross-compilerB benötigt. Das Vorgehen ist wie folgt:

  1. Auf Host A: compilerA baut cross-compilerA.

  2. Auf Host A: cross-compilerA baut cross-compilerB.

  3. Auf Host B: cross-compilerB baut compilerC plus alle Programme für Host C, kann diese aber nicht testen.

  4. Auf Host C: compilerC rebuilded und testet sich selbst.

Damit für LFS auf dem gleichen Host Cross-Compilation funktioniert, muss das bekannte Vendor-Triplet x86_64-pc-linux-gnu (was heutzutage immer vier Komponenten enthält) in LFS_TGT behutsam angepasst werden, um verschiedene Architekturen vorzugaukeln. Der Ablauf sieht dann so aus:

  1. Auf dem Build-Host: compilerBuildHost baut cross-compilerBuildHost

  2. Auf dem Build-Host: cross-compilerBuildHost baut compilerLFS

  3. in LFS Chroot: compilerLFS rebuilded und testet sich selbst.

Für LFS muss mit Hilfe des Cross-Compilers nicht nur der C-Compiler, sondern auch glibc und libstdc++ gebaut werden. Das Problem dabei: der zu erstellende C-Compiler baut intern auf libgcc, welche wiederum gegen glibc gelinkt sein muss - die es noch nicht gibt.

Um diese zirkulären Abhängigkeiten - oder das Henne-Ei-Problem - zu umgehen, wird zunächst eine Minimalversion des cross-compilerBuildHost erstellt, die gerade gut genug ist, um eine vollwertige glibc sowie eine minimal funktionsfähige libstdc++ zu bauen. libstdc++ wird später in Chroot nochmals gebaut, diesesmal komplett. Weitere Details bietet die Dokumentation.

Troubleshooting

Der Build-Vorgang meldet „libtool: warning: remember to run ‚libtool –finish /usr/lib‘“ (File-5.39)

Liegt am prefix-Parameter. Man muss nichts tun, also nicht ausführen und einfach ignorieren.

The system has no more ptys. Ask your system administrator to create more.

Möglicherweise wurde der Build-Host nach Schritt 7.3 neu gestartet, und vergessen, die Device-Nodes vor dem Chroot erneut zu mounten (also Code-Abschnitt 7.3 und 7.4 nochmals auszuführen).

LFS bleibt beim Boot einfach mit der Meldung „GRUB“ stehen

Die LFS-Disk wurde mit BIOS/GPT eingerichtet. /boot muss dann auf eine eigene Partition ausgelagert werden.

LFS zeigt den GRUB Boot Loader. Will man in LFS booten, erhält man die Meldung „error: hd1 cannot get C/H/S values. „

Tritt gern bei manuell erstellter /boot/grub/grub.cfg auf. Wird die LFS-Disk als zweite Disk im System als erstes Boot-Medium spezifiziert, muss die /boot/grub/grub.cfg den Eintrag set root=(hd0,1) aufweisen. Ist sie das zweite Boot-Medium, auf set root=(hd1,1) setzen, usw.

„Kernel Panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)“

Es fehlen ziemlich sicher Treiber für das verwendete Medium. Falls VirtIO-Disks verwendet wurden, auf SATA-Disks umsteigen, oder die Treiber hinzufügen.

Have fun :-)

Wer jetzt einfach mal Bauen möchte: Die nachfolgenden Code-Abschnitte sind 1:1 der LFS-Doku entnommen, enthalten aber keinen Fliesstext mehr und sind soweit wie möglich per Copy & Paste in ein Terminal auf einem CentOS 8 Minimal lauffähig. Auf das manuelle Prüfen mancher Ausgaben wird bewusst verzichtet.

Copy & Paste Shell-Commands

Systemd-Version von LFS v10.1 mit BIOS/MBR-Boot, SATA-Disk, Intel e1000-Netzwerkkarte, auf CentOS 8 Minimal.

Copyright © 1999-2021, Gerard Beekmans

# Chapter 2. Preparing the Host System

dnf -y install yum-utils
yum config-manager --set-enabled powertools
dnf -y install bison byacc bzip2 gcc-c++ patch perl python3 tar texinfo wget

cat > version-check.sh << "EOF"
#!/bin/bash
# Simple script to list version numbers of critical development tools
export LC_ALL=C
bash --version | head -n1 | cut -d" " -f2-4
MYSH=$(readlink -f /bin/sh)
echo "/bin/sh -> $MYSH"
echo $MYSH | grep -q bash || echo "ERROR: /bin/sh does not point to bash"
unset MYSH

echo -n "Binutils: "; ld --version | head -n1 | cut -d" " -f3-
bison --version | head -n1

if [ -h /usr/bin/yacc ]; then
  echo "/usr/bin/yacc -> $(readlink -f /usr/bin/yacc)";
elif [ -x /usr/bin/yacc ]; then
  echo yacc is $(/usr/bin/yacc -V | head -n1)
else
  echo "yacc not found"
fi

bzip2 --version 2>&1 < /dev/null | head -n1 | cut -d" " -f1,6-
echo -n "Coreutils: "; chown --version | head -n1 | cut -d")" -f2
diff --version | head -n1
find --version | head -n1
gawk --version | head -n1

if [ -h /usr/bin/awk ]; then
  echo "/usr/bin/awk -> `readlink -f /usr/bin/awk`";
elif [ -x /usr/bin/awk ]; then
  echo awk is `/usr/bin/awk --version | head -n1`
else
  echo "awk not found"
fi

gcc --version | head -n1
g++ --version | head -n1
ldd --version | head -n1 | cut -d" " -f2-  # glibc version
grep --version | head -n1
gzip --version | head -n1
cat /proc/version
m4 --version | head -n1
make --version | head -n1
patch --version | head -n1
echo Perl `perl -V:version`
python3 --version
sed --version | head -n1
tar --version | head -n1
makeinfo --version | head -n1  # texinfo version
xz --version | head -n1

echo 'int main(){}' > dummy.c && g++ -o dummy dummy.c
if [ -x dummy ]
  then echo "g++ compilation OK";
  else echo "g++ compilation failed"; fi
rm -f dummy.c dummy
EOF

bash version-check.sh
# init the SECOND disk (SATA / SCSI)
parted /dev/sda mklabel msdos

# becomes /, leaving space for the MBR
parted /dev/sda mkpart primary 1MiB 10G

# sda1 will be a bootable BIOS/MBR partition
parted /dev/sda set 1 boot on

# becomes swap
parted /dev/sda mkpart primary 10G 12G

# becomes /home
parted /dev/sda mkpart primary 12G 100%

partprobe
sync

mkfs --verbose --type ext4 /dev/sda1

mkswap --check /dev/sda2
swapon /dev/sda2

mkfs --verbose --type ext4 /dev/sda3

export LFS=/mnt/lfs
echo 'export LFS=/mnt/lfs' >> /root/.bash_profile

export LC_CTYPE=POSIX
echo 'export LC_CTYPE=POSIX' > /etc/profile.d/locale.sh

mkdir -pv $LFS
echo '/dev/sda1 /mnt/lfs      ext4 defaults 0 0' >> /etc/fstab
echo '/dev/sda2 swap          swap defaults 0 0' >> /etc/fstab
mount --all

mkdir -pv $LFS/home
echo '/dev/sda3 /mnt/lfs/home ext4 defaults 0 0' >> /etc/fstab
mount --all
# takes round about 10 minutes or more

# Chapter 3. Packages and Patches
# try to use a mirror like http://lfs.linux-sysadmin.com instead of http://www.linuxfromscratch.org

mkdir -v $LFS/sources
chmod -v a+wt $LFS/sources

wget http://lfs.linux-sysadmin.com/lfs/downloads/stable-systemd/wget-list

# sequential downloading
# might take some minutes
wget --input-file=wget-list --continue --directory-prefix=$LFS/sources

wget http://lfs.linux-sysadmin.com/lfs/downloads/stable-systemd/md5sums --directory-prefix=$LFS/sources

pushd $LFS/sources
  md5sum -c md5sums 1> /dev/null
popd
# Chapter 4. Final Preparations

mkdir -pv $LFS/{bin,etc,lib,sbin,usr,var}
case $(uname -m) in
  x86_64) mkdir -pv $LFS/lib64 ;;
esac

# this is for the cross-compiler
mkdir -pv $LFS/tools

groupadd lfs
useradd --shell /bin/bash --gid lfs --create-home --skel /dev/null lfs

chown -v lfs $LFS/{usr,lib,var,etc,bin,sbin,tools}
case $(uname -m) in
  x86_64) chown -v lfs $LFS/lib64 ;;
esac

chown -v lfs $LFS/sources
su - lfs
cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF

cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/usr/bin
if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
PATH=$LFS/tools/bin:$PATH
CONFIG_SITE=$LFS/usr/share/config.site
export LFS LC_ALL LFS_TGT PATH CONFIG_SITE
EOF
logout
su - lfs
# takes round about 35 minutes or more, without tests

# Chapter 5 Compiling a Cross-Toolchain
# 5.1 Introduction
# 5.2 Binutils-2.36.1 - Pass 1
# 5.2.1. Installation of Cross Binutils

cd $LFS/sources
tar xf binutils-2.36.1.tar.xz
cd binutils-2.36.1

mkdir -v build
cd       build
../configure --prefix=$LFS/tools       \
             --with-sysroot=$LFS        \
             --target=$LFS_TGT          \
             --disable-nls              \
             --disable-werror
make
make install

cd $LFS/sources
rm -rf binutils-2.36.1


# 5.3 GCC-10.2.0 - Pass 1
# 5.3.1. Installation of Cross GCC

cd $LFS/sources
tar xf gcc-10.2.0.tar.xz
cd gcc-10.2.0

tar -xf ../mpfr-4.1.0.tar.xz
mv -v mpfr-4.1.0 mpfr
tar -xf ../gmp-6.2.1.tar.xz
mv -v gmp-6.2.1 gmp
tar -xf ../mpc-1.2.1.tar.gz
mv -v mpc-1.2.1 mpc
case $(uname -m) in
  x86_64)
    sed -e '/m64=/s/lib64/lib/' \
        -i.orig gcc/config/i386/t-linux64
 ;;
esac

mkdir -v build
cd       build

../configure                                       \
    --target=$LFS_TGT                              \
    --prefix=$LFS/tools                            \
    --with-glibc-version=2.11                      \
    --with-sysroot=$LFS                            \
    --with-newlib                                  \
    --without-headers                              \
    --enable-initfini-array                        \
    --disable-nls                                  \
    --disable-shared                               \
    --disable-multilib                             \
    --disable-decimal-float                        \
    --disable-threads                              \
    --disable-libatomic                            \
    --disable-libgomp                              \
    --disable-libquadmath                          \
    --disable-libssp                               \
    --disable-libvtv                               \
    --disable-libstdcxx                            \
    --enable-languages=c,c++
make
make install
cd ..
cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \
  `dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/install-tools/include/limits.h

cd $LFS/sources
rm -rf gcc-10.2.0


# 5.4 Linux-5.10.17 API Headers
# 5.4.1. Installation of Linux API Headers

cd $LFS/sources
tar xf linux-5.10.17.tar.xz
cd linux-5.10.17

make mrproper
make headers
find usr/include -name '.*' -delete
rm usr/include/Makefile

cp -rv usr/include $LFS/usr

cd $LFS/sources
rm -rf linux-5.10.17


# 5.5 Glibc-2.33
# 5.5.1. Installation of Glibc

cd $LFS/sources
tar xf glibc-2.33.tar.xz
cd glibc-2.33

case $(uname -m) in
    i?86)   ln -sfv ld-linux.so.2 $LFS/lib/ld-lsb.so.3
    ;;
    x86_64) ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64
            ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64/ld-lsb-x86-64.so.3
    ;;
esac

patch -Np1 -i ../glibc-2.33-fhs-1.patch

mkdir -v build
cd       build
../configure                             \
      --prefix=/usr                      \
      --host=$LFS_TGT                    \
      --build=$(../scripts/config.guess) \
      --enable-kernel=3.2                \
      --with-headers=$LFS/usr/include    \
      libc_cv_slibdir=/lib
make
make DESTDIR=$LFS install
# NORMALLY STOP HERE AND DO THE TEST BELOW
echo 'int main(){}' > dummy.c
$LFS_TGT-gcc dummy.c
readelf -l a.out | grep '/ld-linux'
rm -v dummy.c a.out
# OUTPUT LIKE "[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]"?
# THEN GO ON
# ELSE STOP AND FIX
# takes round about 1 minute or more, without tests

$LFS/tools/libexec/gcc/$LFS_TGT/10.2.0/install-tools/mkheaders

cd $LFS/sources
rm -rf glibc-2.33


# 5.6 Libstdc++ from GCC-10.2.0, Pass 1
# 5.6.1. Installation of Target Libstdc++

cd $LFS/sources
tar xf gcc-10.2.0.tar.xz
cd gcc-10.2.0

mkdir -v build
cd       build

../libstdc++-v3/configure           \
    --host=$LFS_TGT                 \
    --build=$(../config.guess)      \
    --prefix=/usr                   \
    --disable-multilib              \
    --disable-nls                   \
    --disable-libstdcxx-pch         \
    --with-gxx-include-dir=/tools/$LFS_TGT/include/c++/10.2.0
make
make DESTDIR=$LFS install

cd $LFS/sources
rm -rf gcc-10.2.0
# takes round about 35 minutes or more, without tests

# Chapter 6 Cross Compiling Temporary Tools
# 6.1 Introduction
# 6.2 M4-1.4.18
# 6.2.1. Installation of M4

cd $LFS/sources
tar xf m4-1.4.18.tar.xz
cd m4-1.4.18

sed -i 's/IO_ftrylockfile/IO_EOF_SEEN/' lib/*.c
echo "#define _IO_IN_BACKUP 0x100" >> lib/stdio-impl.h

./configure --prefix=/usr   \
            --host=$LFS_TGT \
            --build=$(build-aux/config.guess)
make
make DESTDIR=$LFS install

cd $LFS/sources
rm -rf m4-1.4.18


# 6.3 Ncurses-6.2
# 6.3.1. Installation of Ncurses

cd $LFS/sources
tar xf ncurses-6.2.tar.gz
cd ncurses-6.2

sed -i s/mawk// configure
mkdir build
pushd build
  ../configure
  make -C include
  make -C progs tic
popd

./configure --prefix=/usr                \
            --host=$LFS_TGT              \
            --build=$(./config.guess)    \
            --mandir=/usr/share/man      \
            --with-manpage-format=normal \
            --with-shared                \
            --without-debug              \
            --without-ada                \
            --without-normal             \
            --enable-widec
make
make DESTDIR=$LFS TIC_PATH=$(pwd)/build/progs/tic install

echo "INPUT(-lncursesw)" > $LFS/usr/lib/libncurses.so
mv -v $LFS/usr/lib/libncursesw.so.6* $LFS/lib
ln -sfv ../../lib/$(readlink $LFS/usr/lib/libncursesw.so) $LFS/usr/lib/libncursesw.so

cd $LFS/sources
rm -rf ncurses-6.2


# 6.4 Bash-5.1
# 6.4.1. Installation of Bash

cd $LFS/sources
tar xf bash-5.1.tar.gz
cd bash-5.1

./configure --prefix=/usr                   \
            --build=$(support/config.guess) \
            --host=$LFS_TGT                 \
            --without-bash-malloc
make
make DESTDIR=$LFS install

mv $LFS/usr/bin/bash $LFS/bin/bash
ln -sv bash $LFS/bin/sh

cd $LFS/sources
rm -rf bash-5.1


# 6.5 Coreutils-8.32
# 6.5.1. Installation of Coreutils

cd $LFS/sources
tar xf coreutils-8.32.tar.xz
cd coreutils-8.32

./configure --prefix=/usr                     \
            --host=$LFS_TGT                   \
            --build=$(build-aux/config.guess) \
            --enable-install-program=hostname \
            --enable-no-install-program=kill,uptime
make
make DESTDIR=$LFS install

mv -v $LFS/usr/bin/{cat,chgrp,chmod,chown,cp,date,dd,df,echo} $LFS/bin
mv -v $LFS/usr/bin/{false,ln,ls,mkdir,mknod,mv,pwd,rm}        $LFS/bin
mv -v $LFS/usr/bin/{rmdir,stty,sync,true,uname}               $LFS/bin
mv -v $LFS/usr/bin/{head,nice,sleep,touch}                    $LFS/bin
mv -v $LFS/usr/bin/chroot                                     $LFS/usr/sbin

mkdir -pv $LFS/usr/share/man/man8
mv -v $LFS/usr/share/man/man1/chroot.1                        $LFS/usr/share/man/man8/chroot.8
sed -i 's/"1"/"8"/'                                           $LFS/usr/share/man/man8/chroot.8

cd $LFS/sources
rm -rf coreutils-8.32


# 6.6 Diffutils-3.7
# 6.6.1. Installation of Diffutils

cd $LFS/sources
tar xf diffutils-3.7.tar.xz
cd diffutils-3.7

./configure --prefix=/usr --host=$LFS_TGT
make
make DESTDIR=$LFS install

cd $LFS/sources
rm -rf diffutils-3.7


# 6.7 File-5.39
# 6.7.1. Installation of File

cd $LFS/sources
tar xf file-5.39.tar.gz
cd file-5.39

mkdir build
pushd build
  ../configure --disable-bzlib      \
               --disable-libseccomp \
               --disable-xzlib      \
               --disable-zlib
  make
popd

./configure --prefix=/usr --host=$LFS_TGT --build=$(./config.guess)
make FILE_COMPILE=$(pwd)/build/src/file
make DESTDIR=$LFS install

cd $LFS/sources
rm -rf file-5.39


# 6.8 Findutils-4.8.0
# 6.8.1. Installation of Findutils

cd $LFS/sources
tar xf findutils-4.8.0.tar.xz
cd findutils-4.8.0

./configure --prefix=/usr   \
            --host=$LFS_TGT \
            --build=$(build-aux/config.guess)
make
make DESTDIR=$LFS install

mv -v $LFS/usr/bin/find $LFS/bin
sed -i 's|find:=${BINDIR}|find:=/bin|' $LFS/usr/bin/updatedb

cd $LFS/sources
rm -rf findutils-4.8.0


# 6.9 Gawk-5.1.0
# 6.9.1. Installation of Gawk

cd $LFS/sources
tar xf gawk-5.1.0.tar.xz
cd gawk-5.1.0

sed -i 's/extras//' Makefile.in

./configure --prefix=/usr   \
            --host=$LFS_TGT \
            --build=$(./config.guess)
make
make DESTDIR=$LFS install

cd $LFS/sources
rm -rf gawk-5.1.0


# 6.10 Grep-3.6
# 6.10.1. Installation of Grep

cd $LFS/sources
tar xf grep-3.6.tar.xz
cd grep-3.6

./configure --prefix=/usr   \
            --host=$LFS_TGT \
            --bindir=/bin
make
make DESTDIR=$LFS install

cd $LFS/sources
rm -rf grep-3.6


# 6.11 Gzip-1.10
# 6.11.1. Installation of Gzip

cd $LFS/sources
tar xf gzip-1.10.tar.xz
cd gzip-1.10

./configure --prefix=/usr --host=$LFS_TGT
make
make DESTDIR=$LFS install
mv -v $LFS/usr/bin/gzip $LFS/bin

cd $LFS/sources
rm -rf gzip-1.10


# 6.12 Make-4.3
# 6.12.1. Installation of Make

cd $LFS/sources
tar xf make-4.3.tar.gz
cd make-4.3

./configure --prefix=/usr   \
            --without-guile \
            --host=$LFS_TGT \
            --build=$(build-aux/config.guess)
make
make DESTDIR=$LFS install

cd $LFS/sources
rm -rf make-4.3


# 6.13 Patch-2.7.6
# 6.13.1. Installation of Patch

cd $LFS/sources
tar xf patch-2.7.6.tar.xz
cd patch-2.7.6

./configure --prefix=/usr   \
            --host=$LFS_TGT \
            --build=$(build-aux/config.guess)
make
make DESTDIR=$LFS install

cd $LFS/sources
rm -rf patch-2.7.6


# 6.14 Sed-4.8
# 6.14.1. Installation of Sed

cd $LFS/sources
tar xf sed-4.8.tar.xz
cd sed-4.8

./configure --prefix=/usr   \
            --host=$LFS_TGT \
            --bindir=/bin
make
make DESTDIR=$LFS install

cd $LFS/sources
rm -rf sed-4.8


# 6.15 Tar-1.34
# 6.15.1. Installation of Tar

cd $LFS/sources
tar xf tar-1.34.tar.xz
cd tar-1.34

./configure --prefix=/usr                     \
            --host=$LFS_TGT                   \
            --build=$(build-aux/config.guess) \
            --bindir=/bin
make
make DESTDIR=$LFS install

cd $LFS/sources
rm -rf tar-1.34


# 6.16 Xz-5.2.5
# 6.16.1. Installation of Xz

cd $LFS/sources
tar xf xz-5.2.5.tar.xz
cd xz-5.2.5

./configure --prefix=/usr                     \
            --host=$LFS_TGT                   \
            --build=$(build-aux/config.guess) \
            --disable-static                  \
            --docdir=/usr/share/doc/xz-5.2.5
make
make DESTDIR=$LFS install

mv -v $LFS/usr/bin/{lzma,unlzma,lzcat,xz,unxz,xzcat}  $LFS/bin
mv -v $LFS/usr/lib/liblzma.so.*                       $LFS/lib
ln -svf ../../lib/$(readlink $LFS/usr/lib/liblzma.so) $LFS/usr/lib/liblzma.so

cd $LFS/sources
rm -rf xz-5.2.5


# 6.17 Binutils-2.36.1 - Pass 2
# 6.17.1. Installation of Binutils

cd $LFS/sources
tar xf binutils-2.36.1.tar.xz
cd binutils-2.36.1

mkdir -v build
cd       build

../configure                   \
    --prefix=/usr              \
    --build=$(../config.guess) \
    --host=$LFS_TGT            \
    --disable-nls              \
    --enable-shared            \
    --disable-werror           \
    --enable-64-bit-bfd
make
make DESTDIR=$LFS install
install -vm755 libctf/.libs/libctf.so.0.0.0 $LFS/usr/lib

cd $LFS/sources
rm -rf binutils-2.36.1


# 6.18 GCC-10.2.0 - Pass 2
# 6.18.1. Installation of GCC

cd $LFS/sources
tar xf gcc-10.2.0.tar.xz
cd gcc-10.2.0

tar -xf ../mpfr-4.1.0.tar.xz
mv -v mpfr-4.1.0 mpfr
tar -xf ../gmp-6.2.1.tar.xz
mv -v gmp-6.2.1 gmp
tar -xf ../mpc-1.2.1.tar.gz
mv -v mpc-1.2.1 mpc
case $(uname -m) in
  x86_64)
    sed -e '/m64=/s/lib64/lib/' -i.orig gcc/config/i386/t-linux64
  ;;
esac

mkdir -v build
cd       build
mkdir -pv $LFS_TGT/libgcc
ln -s ../../../libgcc/gthr-posix.h $LFS_TGT/libgcc/gthr-default.h

../configure                                       \
    --build=$(../config.guess)                     \
    --host=$LFS_TGT                                \
    --prefix=/usr                                  \
    CC_FOR_TARGET=$LFS_TGT-gcc                     \
    --with-build-sysroot=$LFS                      \
    --enable-initfini-array                        \
    --disable-nls                                  \
    --disable-multilib                             \
    --disable-decimal-float                        \
    --disable-libatomic                            \
    --disable-libgomp                              \
    --disable-libquadmath                          \
    --disable-libssp                               \
    --disable-libvtv                               \
    --disable-libstdcxx                            \
    --enable-languages=c,c++
make
make DESTDIR=$LFS install

ln -sv gcc $LFS/usr/bin/cc

cd $LFS/sources
rm -rf gcc-10.2.0
# Chapter 7 Entering Chroot and Building Additional Temporary Tools
# 7.1 Introduction
# 7.2 Changing Ownership

# switch to user "root" again
exit
chown -R root:root $LFS/{usr,lib,var,etc,bin,sbin,tools}
case $(uname -m) in
  x86_64) chown -R root:root $LFS/lib64 ;;
esac


# 7.3 Preparing Virtual Kernel File Systems

mkdir -pv $LFS/{dev,proc,sys,run}


# 7.3.1. Creating Initial Device Nodes

mknod -m 600 $LFS/dev/console c 5 1
mknod -m 666 $LFS/dev/null c 1 3

mount -v --bind /dev $LFS/dev
mount -v --bind /dev/pts $LFS/dev/pts
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
mount -vt tmpfs tmpfs $LFS/run
if [ -h $LFS/dev/shm ]; then
  mkdir -pv $LFS/$(readlink $LFS/dev/shm)
fi
# 7.4 Entering the Chroot Environment

chroot "$LFS" /usr/bin/env -i   \
    HOME=/root                  \
    TERM="$TERM"                \
    PS1='(lfs chroot) \u:\w\$ ' \
    PATH=/bin:/usr/bin:/sbin:/usr/sbin \
    /bin/bash --login +h
# 7.5 Creating Directories

mkdir -pv /{boot,home,mnt,opt,srv}
mkdir -pv /etc/{opt,sysconfig}
mkdir -pv /lib/firmware
mkdir -pv /media/{floppy,cdrom}
mkdir -pv /usr/{,local/}{bin,include,lib,sbin,src}
mkdir -pv /usr/{,local/}share/{color,dict,doc,info,locale,man}
mkdir -pv /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -pv /usr/{,local/}share/man/man{1..8}
mkdir -pv /var/{cache,local,log,mail,opt,spool}
mkdir -pv /var/lib/{color,misc,locate}

ln -sfv /run /var/run
ln -sfv /run/lock /var/lock

install -dv -m 0750 /root
install -dv -m 1777 /tmp /var/tmp


# 7.6 Creating Essential Files and Symlinks

ln -sv /proc/self/mounts /etc/mtab
echo "127.0.0.1 localhost $(hostname)" > /etc/hosts

cat > /etc/passwd << "EOF"
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/dev/null:/bin/false
daemon:x:6:6:Daemon User:/dev/null:/bin/false
messagebus:x:18:18:D-Bus Message Daemon User:/run/dbus:/bin/false
systemd-bus-proxy:x:72:72:systemd Bus Proxy:/:/bin/false
systemd-journal-gateway:x:73:73:systemd Journal Gateway:/:/bin/false
systemd-journal-remote:x:74:74:systemd Journal Remote:/:/bin/false
systemd-journal-upload:x:75:75:systemd Journal Upload:/:/bin/false
systemd-network:x:76:76:systemd Network Management:/:/bin/false
systemd-resolve:x:77:77:systemd Resolver:/:/bin/false
systemd-timesync:x:78:78:systemd Time Synchronization:/:/bin/false
systemd-coredump:x:79:79:systemd Core Dumper:/:/bin/false
uuidd:x:80:80:UUID Generation Daemon User:/dev/null:/bin/false
nobody:x:99:99:Unprivileged User:/dev/null:/bin/false
EOF

cat > /etc/group << "EOF"
root:x:0:
bin:x:1:daemon
sys:x:2:
kmem:x:3:
tape:x:4:
tty:x:5:
daemon:x:6:
floppy:x:7:
disk:x:8:
lp:x:9:
dialout:x:10:
audio:x:11:
video:x:12:
utmp:x:13:
usb:x:14:
cdrom:x:15:
adm:x:16:
messagebus:x:18:
systemd-journal:x:23:
input:x:24:
mail:x:34:
kvm:x:61:
systemd-bus-proxy:x:72:
systemd-journal-gateway:x:73:
systemd-journal-remote:x:74:
systemd-journal-upload:x:75:
systemd-network:x:76:
systemd-resolve:x:77:
systemd-timesync:x:78:
systemd-coredump:x:79:
uuidd:x:80:
wheel:x:97:
nogroup:x:99:
users:x:999:
EOF

echo "tester:x:$(ls -n $(tty) | cut -d" " -f3):101::/home/tester:/bin/bash" >> /etc/passwd
echo "tester:x:101:" >> /etc/group
install -o tester -d /home/tester
exec /bin/bash --login +h
# takes round about 15 minutes or more, without tests

touch /var/log/{btmp,lastlog,faillog,wtmp}
chgrp -v utmp /var/log/lastlog
chmod -v 664  /var/log/lastlog
chmod -v 600  /var/log/btmp


# 7.7 Libstdc++ from GCC-10.2.0, Pass 2
# 7.7.1. Installation of Target Libstdc++

cd $LFS/sources
tar xf gcc-10.2.0.tar.xz
cd gcc-10.2.0

ln -s gthr-posix.h libgcc/gthr-default.h
mkdir -v build
cd       build

../libstdc++-v3/configure            \
    CXXFLAGS="-g -O2 -D_GNU_SOURCE"  \
    --prefix=/usr                    \
    --disable-multilib               \
    --disable-nls                    \
    --host=$(uname -m)-lfs-linux-gnu \
    --disable-libstdcxx-pch
make
make install

cd $LFS/sources
rm -rf gcc-10.2.0


# 7.8 Gettext-0.21
# 7.8.1. Installation of Gettext

cd /sources
tar xf gettext-0.21.tar.xz
cd gettext-0.21

./configure --disable-shared
make

cp -v gettext-tools/src/{msgfmt,msgmerge,xgettext} /usr/bin

cd /sources
rm -rf gettext-0.21


# 7.9 Bison-3.7.5
# 7.9.1. Installation of Bison

cd /sources
tar xf bison-3.7.5.tar.xz
cd bison-3.7.5

./configure --prefix=/usr \
            --docdir=/usr/share/doc/bison-3.7.5
make
make install

cd /sources
rm -rf bison-3.7.5


# 7.10 Perl-5.32.1
# 7.10.1. Installation of Perl

cd /sources/
tar xf perl-5.32.1.tar.xz
cd perl-5.32.1

sh Configure -des                                        \
             -Dprefix=/usr                               \
             -Dvendorprefix=/usr                         \
             -Dprivlib=/usr/lib/perl5/5.32/core_perl     \
             -Darchlib=/usr/lib/perl5/5.32/core_perl     \
             -Dsitelib=/usr/lib/perl5/5.32/site_perl     \
             -Dsitearch=/usr/lib/perl5/5.32/site_perl    \
             -Dvendorlib=/usr/lib/perl5/5.32/vendor_perl \
             -Dvendorarch=/usr/lib/perl5/5.32/vendor_perl
make
make install

cd /sources/
rm -rf perl-5.32.1


# 7.11 Python-3.9.2
# 7.11.1. Installation of Python

cd /sources
tar xf Python-3.9.2.tar.xz
cd Python-3.9.2

./configure --prefix=/usr   \
            --enable-shared \
            --without-ensurepip
make
make install

cd /sources
rm -rf Python-3.9.2


# 7.12 Texinfo-6.7
# 7.12.1. Installation of Texinfo

cd /sources
tar xf texinfo-6.7.tar.xz
cd texinfo-6.7

./configure --prefix=/usr
make
make install

cd /sources
rm -rf texinfo-6.7


# 7.13 Util-linux-2.36.2
# 7.13.1. Installation of Util-linux

cd /sources
tar xf util-linux-2.36.2.tar.xz
cd util-linux-2.36.2

mkdir -pv /var/lib/hwclock

./configure ADJTIME_PATH=/var/lib/hwclock/adjtime    \
            --docdir=/usr/share/doc/util-linux-2.36.2 \
            --disable-chfn-chsh  \
            --disable-login      \
            --disable-nologin    \
            --disable-su         \
            --disable-setpriv    \
            --disable-runuser    \
            --disable-pylibmount \
            --disable-static     \
            --without-python     \
            runstatedir=/run
make
make install

cd /sources
rm -rf util-linux-2.36.2


# 7.14 Cleaning up and Saving the Temporary System

find /usr/{lib,libexec} -name \*.la -delete
rm -rf /usr/share/{info,man,doc}/*
# takes round about 25 minutes or more, without tests

# Chapter 8 Installing Basic System Software
# 8.3 Man-pages-5.10
# 8.3.1. Installation of Man-pages

cd /sources
tar xf man-pages-5.10.tar.xz
cd man-pages-5.10

make install

cd /sources
rm -rf man-pages-5.10


# 8.4 Iana-Etc-20210202
# 8.4.1. Installation of Iana-Etc

cd /sources
tar xf iana-etc-20210202.tar.gz
cd iana-etc-20210202

cp services protocols /etc

cd /sources
rm -rf iana-etc-20210202


# 8.5 Glibc-2.33
# 8.5.1. Installation of Glibc

cd /sources
tar xf glibc-2.33.tar.xz
cd glibc-2.33

patch -Np1 -i ../glibc-2.33-fhs-1.patch
sed -e '402a\      *result = local->data.services[database_index];' \
    -i nss/nss_database.c

mkdir -v build
cd       build

../configure --prefix=/usr                            \
             --disable-werror                         \
             --enable-kernel=3.2                      \
             --enable-stack-protector=strong          \
             --with-headers=/usr/include              \
             libc_cv_slibdir=/lib

make
#make check

touch /etc/ld.so.conf
sed '/test-installation/s@$(PERL)@echo not running@' -i ../Makefile

make install

cp -v ../nscd/nscd.conf /etc/nscd.conf
mkdir -pv /var/cache/nscd

install -v -Dm644 ../nscd/nscd.tmpfiles /usr/lib/tmpfiles.d/nscd.conf
install -v -Dm644 ../nscd/nscd.service /lib/systemd/system/nscd.service

mkdir -pv /usr/lib/locale
localedef -i POSIX -f UTF-8 C.UTF-8 2> /dev/null || true
localedef -i cs_CZ -f UTF-8 cs_CZ.UTF-8
localedef -i de_DE -f ISO-8859-1 de_DE
localedef -i de_DE@euro -f ISO-8859-15 de_DE@euro
localedef -i de_DE -f UTF-8 de_DE.UTF-8
localedef -i el_GR -f ISO-8859-7 el_GR
localedef -i en_GB -f UTF-8 en_GB.UTF-8
localedef -i en_HK -f ISO-8859-1 en_HK
localedef -i en_PH -f ISO-8859-1 en_PH
localedef -i en_US -f ISO-8859-1 en_US
localedef -i en_US -f UTF-8 en_US.UTF-8
localedef -i es_MX -f ISO-8859-1 es_MX
localedef -i fa_IR -f UTF-8 fa_IR
localedef -i fr_FR -f ISO-8859-1 fr_FR
localedef -i fr_FR@euro -f ISO-8859-15 fr_FR@euro
localedef -i fr_FR -f UTF-8 fr_FR.UTF-8
localedef -i it_IT -f ISO-8859-1 it_IT
localedef -i it_IT -f UTF-8 it_IT.UTF-8
localedef -i ja_JP -f EUC-JP ja_JP
localedef -i ja_JP -f SHIFT_JIS ja_JP.SIJS 2> /dev/null || true
localedef -i ja_JP -f UTF-8 ja_JP.UTF-8
localedef -i ru_RU -f KOI8-R ru_RU.KOI8-R
localedef -i ru_RU -f UTF-8 ru_RU.UTF-8
localedef -i tr_TR -f UTF-8 tr_TR.UTF-8
localedef -i zh_CN -f GB18030 zh_CN.GB18030
localedef -i zh_HK -f BIG5-HKSCS zh_HK.BIG5-HKSCS

make localedata/install-locales

cat > /etc/nsswitch.conf << "EOF"
# Begin /etc/nsswitch.conf

passwd: files
group: files
shadow: files

hosts: files dns
networks: files

protocols: files
services: files
ethers: files
rpc: files

# End /etc/nsswitch.conf
EOF

tar -xf ../../tzdata2021a.tar.gz

ZONEINFO=/usr/share/zoneinfo
mkdir -pv $ZONEINFO/{posix,right}

for tz in etcetera southamerica northamerica europe africa antarctica  \
          asia australasia backward; do
    zic -L /dev/null   -d $ZONEINFO       ${tz}
    zic -L /dev/null   -d $ZONEINFO/posix ${tz}
    zic -L leapseconds -d $ZONEINFO/right ${tz}
done

cp -v zone.tab zone1970.tab iso3166.tab $ZONEINFO
zic -d $ZONEINFO -p America/New_York
unset ZONEINFO
#tzselect
ln -sfv /usr/share/zoneinfo/Europe/Zurich /etc/localtime

cat > /etc/ld.so.conf << "EOF"
# Begin /etc/ld.so.conf
/usr/local/lib
/opt/lib
EOF

cat >> /etc/ld.so.conf << "EOF"
# Add an include directory
include /etc/ld.so.conf.d/*.conf
EOF

mkdir -pv /etc/ld.so.conf.d

cd /sources
rm -rf glibc-2.33


# 8.6 Zlib-1.2.11
# 8.6.1. Installation of Zlib

cd /sources
tar xf zlib-1.2.11.tar.xz
cd zlib-1.2.11

./configure --prefix=/usr
make
#make check
make install

mv -v /usr/lib/libz.so.* /lib
ln -sfv ../../lib/$(readlink /usr/lib/libz.so) /usr/lib/libz.so
rm -fv /usr/lib/libz.a

cd /sources
rm -rf zlib-1.2.11


# 8.7 Bzip2-1.0.8
# 8.7.1. Installation of Bzip2

cd /sources
tar xf bzip2-1.0.8.tar.gz
cd bzip2-1.0.8

patch -Np1 -i ../bzip2-1.0.8-install_docs-1.patch
sed -i 's@\(ln -s -f \)$(PREFIX)/bin/@\1@' Makefile
sed -i "s@(PREFIX)/man@(PREFIX)/share/man@g" Makefile

make -f Makefile-libbz2_so
make clean
make
make PREFIX=/usr install

cp -v bzip2-shared /bin/bzip2
cp -av libbz2.so* /lib
ln -sv ../../lib/libbz2.so.1.0 /usr/lib/libbz2.so
rm -v /usr/bin/{bunzip2,bzcat,bzip2}
ln -sv bzip2 /bin/bunzip2
ln -sv bzip2 /bin/bzcat
rm -fv /usr/lib/libbz2.a

cd /sources
rm -rf bzip2-1.0.8


# 8.8 Xz-5.2.5
# 8.8.1. Installation of Xz

cd /sources
tar xf xz-5.2.5.tar.xz
cd xz-5.2.5

./configure --prefix=/usr    \
            --disable-static \
            --docdir=/usr/share/doc/xz-5.2.5
make
#make check
make install

mv -v   /usr/bin/{lzma,unlzma,lzcat,xz,unxz,xzcat} /bin
mv -v /usr/lib/liblzma.so.* /lib
ln -svf ../../lib/$(readlink /usr/lib/liblzma.so) /usr/lib/liblzma.so

cd /sources
rm -rf xz-5.2.5


# 8.9 Zstd-1.4.8
# 8.9.1. Installation of Zstd

cd /sources/
tar xf zstd-1.4.8.tar.gz
cd zstd-1.4.8

make
#make check
make prefix=/usr install

rm -v /usr/lib/libzstd.a
mv -v /usr/lib/libzstd.so.* /lib
ln -sfv ../../lib/$(readlink /usr/lib/libzstd.so) /usr/lib/libzstd.so

cd /sources
rm -rf zstd-1.4.8


# 8.13 File-5.39
# 8.13.1. Installation of File

cd /sources
tar xf file-5.39.tar.gz
cd file-5.39

./configure --prefix=/usr
make
#make check
make install

cd /sources
rm -rf file-5.39


# 8.11 Readline-8.1
# 8.11.1. Installation of Readline

cd /sources
tar xf readline-8.1.tar.gz
cd readline-8.1

sed -i '/MV.*old/d' Makefile.in
sed -i '/{OLDSUFF}/c:' support/shlib-install

./configure --prefix=/usr    \
            --disable-static \
            --with-curses    \
            --docdir=/usr/share/doc/readline-8.1
make SHLIB_LIBS="-lncursesw"
make SHLIB_LIBS="-lncursesw" install

mv -v /usr/lib/lib{readline,history}.so.* /lib
ln -sfv ../../lib/$(readlink /usr/lib/libreadline.so) /usr/lib/libreadline.so
ln -sfv ../../lib/$(readlink /usr/lib/libhistory.so ) /usr/lib/libhistory.so
install -v -m644 doc/*.{ps,pdf,html,dvi} /usr/share/doc/readline-8.1

cd /sources
rm -rf readline-8.1


# 8.12 M4-1.4.18
# 8.12.1. Installation of M4

cd /sources
tar xf m4-1.4.18.tar.xz
cd m4-1.4.18

sed -i 's/IO_ftrylockfile/IO_EOF_SEEN/' lib/*.c
echo "#define _IO_IN_BACKUP 0x100" >> lib/stdio-impl.h

./configure --prefix=/usr
make
#make check
make install

cd /sources
rm -rf m4-1.4.18


# 8.13 Bc-3.3.0
# 8.13.1. Installation of Bc

cd /sources
tar xf bc-3.3.0.tar.xz
cd bc-3.3.0

PREFIX=/usr CC=gcc ./configure.sh -G -O3

make
#make test
make install

cd /sources
rm -rf bc-3.3.0


# 8.14 Flex-2.6.4
# 8.14.1. Installation of Flex

cd /sources
tar xf flex-2.6.4.tar.gz
cd flex-2.6.4

./configure --prefix=/usr \
            --docdir=/usr/share/doc/flex-2.6.4 \
            --disable-static
make
#make check
make install

ln -sv flex /usr/bin/lex

cd /sources
rm -rf flex-2.6.4


# 8.15 Tcl-8.6.11
# 8.15.1. Installation of Tcl

cd /sources
tar xf tcl8.6.11-src.tar.gz
cd tcl8.6.11

tar -xf ../tcl8.6.11-html.tar.gz --strip-components=1
SRCDIR=$(pwd)
cd unix

./configure --prefix=/usr           \
            --mandir=/usr/share/man \
            $([ "$(uname -m)" = x86_64 ] && echo --enable-64bit)
make

sed -e "s|$SRCDIR/unix|/usr/lib|" \
    -e "s|$SRCDIR|/usr/include|"  \
    -i tclConfig.sh

sed -e "s|$SRCDIR/unix/pkgs/tdbc1.1.2|/usr/lib/tdbc1.1.2|" \
    -e "s|$SRCDIR/pkgs/tdbc1.1.2/generic|/usr/include|"    \
    -e "s|$SRCDIR/pkgs/tdbc1.1.2/library|/usr/lib/tcl8.6|" \
    -e "s|$SRCDIR/pkgs/tdbc1.1.2|/usr/include|"            \
    -i pkgs/tdbc1.1.2/tdbcConfig.sh

sed -e "s|$SRCDIR/unix/pkgs/itcl4.2.1|/usr/lib/itcl4.2.1|" \
    -e "s|$SRCDIR/pkgs/itcl4.2.1/generic|/usr/include|"    \
    -e "s|$SRCDIR/pkgs/itcl4.2.1|/usr/include|"            \
    -i pkgs/itcl4.2.1/itclConfig.sh

unset SRCDIR

#make test
make install
chmod -v u+w /usr/lib/libtcl8.6.so
make install-private-headers

ln -sfv tclsh8.6 /usr/bin/tclsh
mv /usr/share/man/man3/{Thread,Tcl_Thread}.3

cd /sources
rm -rf tcl8.6.11


# 8.16 Expect-5.45.4
# 8.16.1. Installation of Expect

cd /sources
tar xf expect5.45.4.tar.gz
cd expect5.45.4

./configure --prefix=/usr           \
            --with-tcl=/usr/lib     \
            --enable-shared         \
            --mandir=/usr/share/man \
            --with-tclinclude=/usr/include
make
#make test
make install

ln -svf expect5.45.4/libexpect5.45.4.so /usr/lib

cd /sources
rm -rf expect5.45.4


# 8.17 DejaGNU-1.6.2
# 8.17.1. Installation of DejaGNU

cd /sources
tar xf dejagnu-1.6.2.tar.gz
cd dejagnu-1.6.2

./configure --prefix=/usr
makeinfo --html --no-split -o doc/dejagnu.html doc/dejagnu.texi
makeinfo --plaintext       -o doc/dejagnu.txt  doc/dejagnu.texi

make install
install -v -dm755  /usr/share/doc/dejagnu-1.6.2
install -v -m644   doc/dejagnu.{html,txt} /usr/share/doc/dejagnu-1.6.2

#make check

cd /sources
rm -rf dejagnu-1.6.2


# 8.18 Binutils-2.36.1
# 8.18.1. Installation of Binutils

cd /sources
tar xf binutils-2.36.1.tar.xz
cd binutils-2.36.1
expect -c "spawn ls"
# This command should only output the following (and nothing more):
# spawn ls
# takes round about 40 minutes or more, without tests

sed -i '/@\tincremental_copy/d' gold/testsuite/Makefile.in
mkdir -v build
cd       build

../configure --prefix=/usr       \
             --enable-gold       \
             --enable-ld=default \
             --enable-plugins    \
             --enable-shared     \
             --disable-werror    \
             --enable-64-bit-bfd \
             --with-system-zlib
make tooldir=/usr
#make -k check
make tooldir=/usr install
rm -fv /usr/lib/lib{bfd,ctf,ctf-nobfd,opcodes}.a

cd /sources
rm -rf binutils-2.36.1


# 8.19 GMP-6.2.1
# 8.19.1. Installation of GMP

cd /sources
tar xf gmp-6.2.1.tar.xz
cd gmp-6.2.1

ABI=32
 ./configure ...
cp -v configfsf.guess config.guess
cp -v configfsf.sub   config.sub
./configure --prefix=/usr    \
            --enable-cxx     \
            --disable-static \
            --docdir=/usr/share/doc/gmp-6.2.1
make
make html
#make check 2>&1 | tee gmp-check-log
awk '/# PASS:/{total+=$3} ; END{print total}' gmp-check-log
make install
make install-html

cd /sources
rm -rf gmp-6.2.1


# 8.20 MPFR-4.1.0
# 8.20.1. Installation of MPFR

cd /sources/
tar xf mpfr-4.1.0.tar.xz
cd mpfr-4.1.0

./configure --prefix=/usr        \
            --disable-static     \
            --enable-thread-safe \
            --docdir=/usr/share/doc/mpfr-4.1.0
make
make html
#make check
make install
make install-html

cd /sources
rm -rf mpfr-4.1.0


# 8.21 MPC-1.2.1
# 8.21.1. Installation of MPC

cd /sources
tar xf mpc-1.2.1.tar.gz
cd mpc-1.2.1

./configure --prefix=/usr    \
            --disable-static \
            --docdir=/usr/share/doc/mpc-1.2.1
make
make html
#make check
make install
make install-html

cd /sources
rm -rf mpc-1.2.1


# 8.22 Attr-2.4.48
# 8.22.1. Installation of Attr

cd /sources
tar xf attr-2.4.48.tar.gz
cd attr-2.4.48

./configure --prefix=/usr     \
            --disable-static  \
            --sysconfdir=/etc \
            --docdir=/usr/share/doc/attr-2.4.48
make
#make check
make install

mv -v /usr/lib/libattr.so.* /lib
ln -sfv ../../lib/$(readlink /usr/lib/libattr.so) /usr/lib/libattr.so

cd /sources
rm -rf attr-2.4.48


# 8.23 Acl-2.2.53
# 8.23.1. Installation of Acl

cd /sources
tar xf acl-2.2.53.tar.gz
cd acl-2.2.53

./configure --prefix=/usr         \
            --disable-static      \
            --libexecdir=/usr/lib \
            --docdir=/usr/share/doc/acl-2.2.53
make
make install

mv -v /usr/lib/libacl.so.* /lib
ln -sfv ../../lib/$(readlink /usr/lib/libacl.so) /usr/lib/libacl.so

cd /sources
rm -rf acl-2.2.53


# 8.24 Libcap-2.48
# 8.24.1. Installation of Libcap

cd /sources
tar xf libcap-2.48.tar.xz
cd libcap-2.48

sed -i '/install -m.*STA/d' libcap/Makefile
make prefix=/usr lib=lib
#make test
make prefix=/usr lib=lib install

for libname in cap psx; do
    mv -v /usr/lib/lib${libname}.so.* /lib
    ln -sfv ../../lib/lib${libname}.so.2 /usr/lib/lib${libname}.so
    chmod -v 755 /lib/lib${libname}.so.2.48
done

cd /sources/
rm -rf libcap-2.48


# 8.25 Shadow-4.8.1
# 8.25.1. Installation of Shadow

cd /sources
tar xf shadow-4.8.1.tar.xz
cd shadow-4.8.1

sed -i 's/groups$(EXEEXT) //' src/Makefile.in
find man -name Makefile.in -exec sed -i 's/groups\.1 / /'   {} \;
find man -name Makefile.in -exec sed -i 's/getspnam\.3 / /' {} \;
find man -name Makefile.in -exec sed -i 's/passwd\.5 / /'   {} \;
sed -e 's:#ENCRYPT_METHOD DES:ENCRYPT_METHOD SHA512:' \
    -e 's:/var/spool/mail:/var/mail:'                 \
    -i etc/login.defs
sed -i 's:DICTPATH.*:DICTPATH\t/lib/cracklib/pw_dict:' etc/login.defs
sed -i 's/1000/999/' etc/useradd
touch /usr/bin/passwd

./configure --sysconfdir=/etc \
            --with-group-name-max-length=32
make
make install

pwconv
grpconv
sed -i 's/yes/no/' /etc/default/useradd

cd /sources
rm -rf shadow-4.8.1


# 8.25.3. Setting the root password

# I Would do that later
# passwd root


# 8.26 GCC-10.2.0
# 8.26.1. Installation of GCC

cd /sources
tar xf gcc-10.2.0.tar.xz
cd gcc-10.2.0

case $(uname -m) in
  x86_64)
    sed -e '/m64=/s/lib64/lib/' \
        -i.orig gcc/config/i386/t-linux64
  ;;
esac
mkdir -v build
cd       build

../configure --prefix=/usr            \
             LD=ld                    \
             --enable-languages=c,c++ \
             --disable-multilib       \
             --disable-bootstrap      \
             --with-system-zlib
make
# takes minimum 120 minutes

# In this section, the test suite for GCC is considered critical. Do not skip it under any circumstance.
ulimit -s 32768
chown -Rv tester .
su tester -c "PATH=$PATH make -k check"
../contrib/test_summary | grep -A7 Summ
make install

rm -rf /usr/lib/gcc/$(gcc -dumpmachine)/10.2.0/include-fixed/bits/
chown -v -R root:root \
    /usr/lib/gcc/*linux-gnu/10.2.0/include{,-fixed}
ln -sv ../usr/bin/cpp /lib
ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/10.2.0/liblto_plugin.so \
        /usr/lib/bfd-plugins/
echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
# [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
#/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../lib/crt1.o succeeded
#/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../lib/crti.o succeeded
#/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../lib/crtn.o succeeded
grep -B4 '^ /usr/include' dummy.log
##include <...> search starts here:
# /usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include
# /usr/local/include
# /usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include-fixed
# /usr/include
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
#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");
grep "/lib.*/libc.so.6 " dummy.log
#attempt to open /lib/libc.so.6 succeeded
grep found dummy.log
#found ld-linux-x86-64.so.2 at /lib/ld-linux-x86-64.so.2

rm -v dummy.c a.out dummy.log
# takes round about 10 minutes or more, without tests

mkdir -pv /usr/share/gdb/auto-load/usr/lib
mv -v /usr/lib/*gdb.py /usr/share/gdb/auto-load/usr/lib

cd /sources
rm -rf gcc-10.2.0


# 8.27 Pkg-config-0.29.2
# 8.27.1. Installation of Pkg-config

cd /sources
tar xf pkg-config-0.29.2.tar.gz
cd pkg-config-0.29.2

./configure --prefix=/usr              \
            --with-internal-glib       \
            --disable-host-tool        \
            --docdir=/usr/share/doc/pkg-config-0.29.2
make
#make check
make install

cd /sources
rm -rf pkg-config-0.29.2


# 8.28 Ncurses-6.2
# 8.28.1. Installation of Ncurses

cd /sources
tar xf ncurses-6.2.tar.gz
cd ncurses-6.2

./configure --prefix=/usr           \
            --mandir=/usr/share/man \
            --with-shared           \
            --without-debug         \
            --without-normal        \
            --enable-pc-files       \
            --enable-widec
make
make install

mv -v /usr/lib/libncursesw.so.6* /lib
ln -sfv ../../lib/$(readlink /usr/lib/libncursesw.so) /usr/lib/libncursesw.so
for lib in ncurses form panel menu ; do
    rm -vf                    /usr/lib/lib${lib}.so
    echo "INPUT(-l${lib}w)" > /usr/lib/lib${lib}.so
    ln -sfv ${lib}w.pc        /usr/lib/pkgconfig/${lib}.pc
done
rm -vf                     /usr/lib/libcursesw.so
echo "INPUT(-lncursesw)" > /usr/lib/libcursesw.so
ln -sfv libncurses.so      /usr/lib/libcurses.so
rm -fv /usr/lib/libncurses++w.a
mkdir -v       /usr/share/doc/ncurses-6.2
cp -v -R doc/* /usr/share/doc/ncurses-6.2

make distclean

./configure --prefix=/usr    \
            --with-shared    \
            --without-normal \
            --without-debug  \
            --without-cxx-binding \
            --with-abi-version=5
make sources libs

cp -av lib/lib*.so.5* /usr/lib

cd /sources
rm -rf ncurses-6.2


# 8.29 Sed-4.8
# 8.29.1. Installation of Sed

cd /sources
tar xf sed-4.8.tar.xz
cd sed-4.8

./configure --prefix=/usr --bindir=/bin
make
make html

chown -Rv tester .
#su tester -c "PATH=$PATH make check"

make install

install -d -m755           /usr/share/doc/sed-4.8
install -m644 doc/sed.html /usr/share/doc/sed-4.8

cd /sources
rm -rf sed-4.8


# 8.30 Psmisc-23.4
# 8.30.1. Installation of Psmisc

cd /sources
tar xf psmisc-23.4.tar.xz
cd psmisc-23.4

./configure --prefix=/usr
make
make install

mv -v /usr/bin/fuser   /bin
mv -v /usr/bin/killall /bin

cd /sources
rm -rf psmisc-23.4


# 8.31 Gettext-0.21
# 8.31.1. Installation of Gettext

cd /sources
tar xf gettext-0.21.tar.xz
cd gettext-0.21

./configure --prefix=/usr    \
            --disable-static \
            --docdir=/usr/share/doc/gettext-0.21
make
#make check
make install

chmod -v 0755 /usr/lib/preloadable_libintl.so

cd /sources
rm -rf gettext-0.21


# 8.32 Bison-3.7.5
# 8.32.1. Installation of Bison

cd /sources
tar xf bison-3.7.5.tar.xz
cd bison-3.7.5

./configure --prefix=/usr --docdir=/usr/share/doc/bison-3.7.5
make
#make check
make install

cd /sources
rm -rf bison-3.7.5


# 8.33 Grep-3.6
# 8.33.1. Installation of Grep

cd /sources
tar xf grep-3.6.tar.xz
cd grep-3.6

./configure --prefix=/usr --bindir=/bin
make
#make check
make install

cd /sources
rm -rf grep-3.6


# 8.34 Bash-5.1
# 8.34.1. Installation of Bash

cd /sources
tar xf bash-5.1.tar.gz
cd bash-5.1

sed -i  '/^bashline.o:.*shmbchar.h/a bashline.o: ${DEFDIR}/builtext.h' Makefile.in
./configure --prefix=/usr                    \
            --docdir=/usr/share/doc/bash-5.1 \
            --without-bash-malloc            \
            --with-installed-readline
make

chown -Rv tester .
#su tester << EOF
#PATH=$PATH make tests < $(tty)
#EOF

make install
mv -vf /usr/bin/bash /bin
exec /bin/bash --login +h
# takes round about 30 minutes or more, without tests

cd /sources
rm -rf bash-5.1


# 8.35 Libtool-2.4.6
# 8.35.1. Installation of Libtool

cd /sources
tar xf libtool-2.4.6.tar.xz
cd libtool-2.4.6

./configure --prefix=/usr
make
#make check
make install
rm -fv /usr/lib/libltdl.a

cd /sources
rm -rf libtool-2.4.6


# 8.36 GDBM-1.19
# 8.36.1. Installation of GDBM

cd /sources
tar xf gdbm-1.19.tar.gz
cd gdbm-1.19

./configure --prefix=/usr    \
            --disable-static \
            --enable-libgdbm-compat
make
#make check
make install

cd /sources
rm -rf gdbm-1.19


# 8.37 Gperf-3.1
# 8.37.1. Installation of Gperf

cd /sources/
tar xf gperf-3.1.tar.gz
cd gperf-3.1

./configure --prefix=/usr --docdir=/usr/share/doc/gperf-3.1
make
#make -j1 check
make install

cd /sources/
rm -rf gperf-3.1


# 8.38 Expat-2.2.10
# 8.38.1. Installation of Expat

cd /sources
tar xf expat-2.2.10.tar.xz
cd expat-2.2.10

./configure --prefix=/usr    \
            --disable-static \
            --docdir=/usr/share/doc/expat-2.2.10
make
#make check
make install

install -v -m644 doc/*.{html,png,css} /usr/share/doc/expat-2.2.10

cd /sources
rm -rf expat-2.2.10


# 8.39 Inetutils-2.0
# 8.39.1. Installation of Inetutils

cd /sources
tar xf inetutils-2.0.tar.xz
cd inetutils-2.0

./configure --prefix=/usr        \
            --localstatedir=/var \
            --disable-logger     \
            --disable-whois      \
            --disable-rcp        \
            --disable-rexec      \
            --disable-rlogin     \
            --disable-rsh        \
            --disable-servers
make
#make check
make install

mv -v /usr/bin/{hostname,ping,ping6,traceroute} /bin
mv -v /usr/bin/ifconfig /sbin

cd /sources
rm -rf inetutils-2.0


# 8.40 Perl-5.32.1
# 8.40.1. Installation of Perl

cd /sources
tar xf perl-5.32.1.tar.xz
cd perl-5.32.1

export BUILD_ZLIB=False
export BUILD_BZIP2=0

sh Configure -des                                         \
             -Dprefix=/usr                                \
             -Dvendorprefix=/usr                          \
             -Dprivlib=/usr/lib/perl5/5.32/core_perl      \
             -Darchlib=/usr/lib/perl5/5.32/core_perl      \
             -Dsitelib=/usr/lib/perl5/5.32/site_perl      \
             -Dsitearch=/usr/lib/perl5/5.32/site_perl     \
             -Dvendorlib=/usr/lib/perl5/5.32/vendor_perl  \
             -Dvendorarch=/usr/lib/perl5/5.32/vendor_perl \
             -Dman1dir=/usr/share/man/man1                \
             -Dman3dir=/usr/share/man/man3                \
             -Dpager="/usr/bin/less -isR"                 \
             -Duseshrplib                                 \
             -Dusethreads
make
#make test
make install

unset BUILD_ZLIB BUILD_BZIP2

cd /sources
rm -rf perl-5.32.1


# 8.41 XML::Parser-2.46
# 8.41.1. Installation of XML::Parser

cd /sources
tar xf XML-Parser-2.46.tar.gz
cd XML-Parser-2.46

perl Makefile.PL

make
#make test
make install

cd /sources
rm -rf XML-Parser-2.46


# 8.42 Intltool-0.51.0
# 8.42.1. Installation of Intltool

cd /sources
tar xf intltool-0.51.0.tar.gz
cd intltool-0.51.0

sed -i 's:\\\${:\\\$\\{:' intltool-update.in

./configure --prefix=/usr
make
#make check
make install

install -v -Dm644 doc/I18N-HOWTO /usr/share/doc/intltool-0.51.0/I18N-HOWTO

cd /sources
rm -rf intltool-0.51.0


# 8.43 Autoconf-2.71
# 8.43.1. Installation of Autoconf

cd /sources
tar xf autoconf-2.71.tar.xz
cd autoconf-2.71

./configure --prefix=/usr
make
#make check
make install

cd /sources
rm -rf autoconf-2.71


# 8.44 Automake-1.16.3
# 8.44.1. Installation of Automake

cd /sources
tar xf automake-1.16.3.tar.xz
cd automake-1.16.3

sed -i "s/''/etags/" t/tags-lisp-space.sh
./configure --prefix=/usr --docdir=/usr/share/doc/automake-1.16.3

make
#make -j4 check
make install

cd /sources
rm -rf automake-1.16.3


# 8.45 Kmod-28
# 8.45.1. Installation of Kmod

cd /sources/
tar xf kmod-28.tar.xz
cd kmod-28

./configure --prefix=/usr          \
            --bindir=/bin          \
            --sysconfdir=/etc      \
            --with-rootlibdir=/lib \
            --with-xz              \
            --with-zstd            \
            --with-zlib
make
make install

for target in depmod insmod lsmod modinfo modprobe rmmod; do
  ln -sfv ../bin/kmod /sbin/$target
done

ln -sfv kmod /bin/lsmod

cd /sources/
rm -rf kmod-28


# 8.46 Libelf from Elfutils-0.183
# 8.46.1. Installation of Libelf

cd /sources
tar xf elfutils-0.183.tar.bz2
cd elfutils-0.183

./configure --prefix=/usr                \
            --disable-debuginfod         \
            --enable-libdebuginfod=dummy \
            --libdir=/lib
make
#make check
make -C libelf install
install -vm644 config/libelf.pc /usr/lib/pkgconfig
rm /lib/libelf.a

cd /sources
rm -rf elfutils-0.183


# 8.47 Libffi-3.3
# 8.47.1. Installation of Libffi

cd /sources
tar xf libffi-3.3.tar.gz
cd libffi-3.3

./configure --prefix=/usr --disable-static --with-gcc-arch=native
make
#make check
make install

cd /sources
rm -rf libffi-3.3


# 8.48 OpenSSL-1.1.1j
# 8.48.1. Installation of OpenSSL

cd /sources
tar xf openssl-1.1.1j.tar.gz
cd openssl-1.1.1j

./config --prefix=/usr         \
         --openssldir=/etc/ssl \
         --libdir=lib          \
         shared                \
         zlib-dynamic
make
#make test

sed -i '/INSTALL_LIBS/s/libcrypto.a libssl.a//' Makefile
make MANSUFFIX=ssl install
mv -v /usr/share/doc/openssl /usr/share/doc/openssl-1.1.1j
cp -vfr doc/* /usr/share/doc/openssl-1.1.1j

cd /sources
rm -rf openssl-1.1.1j


# 8.49 Python-3.9.2
# 8.49.1. Installation of Python 3

cd /sources
tar xf Python-3.9.2.tar.xz
cd Python-3.9.2

./configure --prefix=/usr       \
            --enable-shared     \
            --with-system-expat \
            --with-system-ffi   \
            --with-ensurepip=yes
make
#make test
make install
install -v -dm755 /usr/share/doc/python-3.9.2/html

tar --strip-components=1  \
    --no-same-owner       \
    --no-same-permissions \
    -C /usr/share/doc/python-3.9.2/html \
    -xvf ../python-3.9.2-docs-html.tar.bz2

cd /sources
rm -rf Python-3.9.2


# 8.50 Ninja-1.10.2
# 8.50.1. Installation of Ninja

cd /sources
tar xf ninja-1.10.2.tar.gz
cd ninja-1.10.2

sed -i '/int Guess/a \
  int   j = 0;\
  char* jobs = getenv( "NINJAJOBS" );\
  if ( jobs != NULL ) j = atoi( jobs );\
  if ( j > 0 ) return j;\
' src/ninja.cc

python3 configure.py --bootstrap
#./ninja ninja_test
#./ninja_test --gtest_filter=-SubprocessTest.SetWithLots
install -vm755 ninja /usr/bin/
install -vDm644 misc/bash-completion /usr/share/bash-completion/completions/ninja
install -vDm644 misc/zsh-completion  /usr/share/zsh/site-functions/_ninja

cd /sources
rm -rf ninja-1.10.2


# 8.51 Meson-0.57.1
# 8.51.1. Installation of Meson

cd /sources
tar xf meson-0.57.1.tar.gz
cd meson-0.57.1

python3 setup.py build
python3 setup.py install --root=dest
cp -rv dest/* /

cd /sources
rm -rf meson-0.57.1


# 8.52 Coreutils-8.32
# 8.52.1. Installation of Coreutils

cd /sources
tar xf coreutils-8.32.tar.xz
cd coreutils-8.32

patch -Np1 -i ../coreutils-8.32-i18n-1.patch
sed -i '/test.lock/s/^/#/' gnulib-tests/gnulib.mk
autoreconf -fiv

FORCE_UNSAFE_CONFIGURE=1 ./configure \
            --prefix=/usr            \
            --enable-no-install-program=kill,uptime
make
make NON_ROOT_USERNAME=tester check-root

echo "dummy:x:102:tester" >> /etc/group
chown -Rv tester .
#su tester -c "PATH=$PATH make RUN_EXPENSIVE_TESTS=yes check"
sed -i '/dummy/d' /etc/group

make install

mv -v /usr/bin/{cat,chgrp,chmod,chown,cp,date,dd,df,echo} /bin
mv -v /usr/bin/{false,ln,ls,mkdir,mknod,mv,pwd,rm} /bin
mv -v /usr/bin/{rmdir,stty,sync,true,uname} /bin
mv -v /usr/bin/chroot /usr/sbin
mv -v /usr/share/man/man1/chroot.1 /usr/share/man/man8/chroot.8
sed -i 's/"1"/"8"/' /usr/share/man/man8/chroot.8
mv -v /usr/bin/{head,nice,sleep,touch} /bin

cd /sources
rm -rf coreutils-8.32


# 8.53 Check-0.15.2
# 8.53.1. Installation of Check

cd /sources
tar xf check-0.15.2.tar.gz
cd check-0.15.2

./configure --prefix=/usr --disable-static
make
#make check
make docdir=/usr/share/doc/check-0.15.2 install

cd /sources
rm -rf check-0.15.2


# 8.54 Diffutils-3.7
# 8.54.1. Installation of Diffutils

cd /sources
tar xf diffutils-3.7.tar.xz
cd diffutils-3.7

./configure --prefix=/usr
make
#make check
make install

cd /sources
rm -rf diffutils-3.7


# 8.55 Gawk-5.1.0
# 8.55.1. Installation of Gawk

cd /sources
tar xf gawk-5.1.0.tar.xz
cd gawk-5.1.0

sed -i 's/extras//' Makefile.in

./configure --prefix=/usr
make
#make check
make install

mkdir -v /usr/share/doc/gawk-5.1.0
cp    -v doc/{awkforai.txt,*.{eps,pdf,jpg}} /usr/share/doc/gawk-5.1.0

cd /sources
rm -rf gawk-5.1.0


# 8.56 Findutils-4.8.0
# 8.56.1. Installation of Findutils

cd /sources
tar xf findutils-4.8.0.tar.xz
cd findutils-4.8.0

./configure --prefix=/usr --localstatedir=/var/lib/locate
make

chown -Rv tester .
#su tester -c "PATH=$PATH make check"

make install

mv -v /usr/bin/find /bin
sed -i 's|find:=${BINDIR}|find:=/bin|' /usr/bin/updatedb

cd /sources
rm -rf findutils-4.8.0


# 8.57 Groff-1.22.4
# 8.57.1. Installation of Groff

cd /sources
tar xf groff-1.22.4.tar.gz
cd groff-1.22.4

PAGE=A4

./configure --prefix=/usr
make -j1
make install

cd /sources
rm -rf groff-1.22.4


# 8.58 GRUB-2.04
# 8.58.1. Installation of GRUB

cd /sources
tar xf grub-2.04.tar.xz
cd grub-2.04

sed "s/gold-version/& -R .note.gnu.property/" \
    -i Makefile.in grub-core/Makefile.in
./configure --prefix=/usr          \
            --sbindir=/sbin        \
            --sysconfdir=/etc      \
            --disable-efiemu       \
            --disable-werror
make
make install

mv -v /etc/bash_completion.d/grub /usr/share/bash-completion/completions

cd /sources
rm -rf grub-2.04


# 8.59 Less-563
# 8.59.1. Installation of Less

cd /sources/
tar xf less-563.tar.gz
cd less-563

./configure --prefix=/usr --sysconfdir=/etc
make
make install

cd /sources/
rm -rf less-563


# 8.60 Gzip-1.10
# 8.60.1. Installation of Gzip

cd /sources
tar xf gzip-1.10.tar.xz
cd gzip-1.10

./configure --prefix=/usr
make
#make check
make install

mv -v /usr/bin/gzip /bin

cd /sources
rm -rf gzip-1.10


# 8.61 IPRoute2-5.10.0
# 8.61.1. Installation of IPRoute2

cd /sources
tar xf iproute2-5.10.0.tar.xz
cd iproute2-5.10.0

sed -i /ARPD/d Makefile
rm -fv man/man8/arpd.8
sed -i 's/.m_ipt.o//' tc/Makefile

make
make DOCDIR=/usr/share/doc/iproute2-5.10.0 install

cd /sources
rm -rf iproute2-5.10.0


# 8.62 Kbd-2.4.0
# 8.62.1. Installation of Kbd

cd /sources
tar xf kbd-2.4.0.tar.xz
cd kbd-2.4.0

patch -Np1 -i ../kbd-2.4.0-backspace-1.patch
sed -i '/RESIZECONS_PROGS=/s/yes/no/' configure
sed -i 's/resizecons.8 //' docs/man/man8/Makefile.in
./configure --prefix=/usr --disable-vlock

make
#make check
make install

mkdir -v            /usr/share/doc/kbd-2.4.0
cp -R -v docs/doc/* /usr/share/doc/kbd-2.4.0

cd /sources
rm -rf kbd-2.4.0


# 8.63 Libpipeline-1.5.3
# 8.63.1. Installation of Libpipeline

cd /sources
tar xf libpipeline-1.5.3.tar.gz
cd libpipeline-1.5.3

./configure --prefix=/usr
make
#make check
make install

cd /sources
rm -rf libpipeline-1.5.3


# 8.64 Make-4.3
# 8.64.1. Installation of Make

cd /sources
tar xf make-4.3.tar.gz
cd make-4.3

./configure --prefix=/usr
make
#make check
make install

cd /sources
rm -rf make-4.3


# 8.65 Patch-2.7.6
# 8.65.1. Installation of Patch

cd /sources
tar xf patch-2.7.6.tar.xz
cd patch-2.7.6

./configure --prefix=/usr
make
#make check
make install

cd /sources
rm -rf patch-2.7.6


# 8.66 Man-DB-2.9.4
# 8.66.1. Installation of Man-DB

cd /sources
tar xf man-db-2.9.4.tar.xz
cd man-db-2.9.4

sed -i '/find/s@/usr@@' init/systemd/man-db.service.in

./configure --prefix=/usr                        \
            --docdir=/usr/share/doc/man-db-2.9.4 \
            --sysconfdir=/etc                    \
            --disable-setuid                     \
            --enable-cache-owner=bin             \
            --with-browser=/usr/bin/lynx         \
            --with-vgrind=/usr/bin/vgrind        \
            --with-grap=/usr/bin/grap
make
#make check
make install

cd /sources
rm -rf man-db-2.9.4


# 8.66.2. Non-English Manual Pages in LFS


# 8.67 Tar-1.34
# 8.67.1. Installation of Tar

cd /sources
tar xf tar-1.34.tar.xz
cd tar-1.34

FORCE_UNSAFE_CONFIGURE=1  \
./configure --prefix=/usr \
            --bindir=/bin
make
#make check
make install
make -C doc install-html docdir=/usr/share/doc/tar-1.34

cd /sources
rm -rf tar-1.34


# 8.68 Texinfo-6.7
# 8.68.1. Installation of Texinfo

cd /sources
tar xf texinfo-6.7.tar.xz
cd texinfo-6.7

./configure --prefix=/usr
make
#make check
make install
make TEXMF=/usr/share/texmf install-tex

pushd /usr/share/info
  rm -v dir
  for f in *
    do install-info $f dir 2>/dev/null
  done
popd

cd /sources
rm -rf texinfo-6.7


# 8.69 Vim-8.2.2433
# 8.69.1. Installation of Vim

cd /sources
tar xf vim-8.2.2433.tar.gz
cd vim-8.2.2433

echo '#define SYS_VIMRC_FILE "/etc/vimrc"' >> src/feature.h

./configure --prefix=/usr
make

chown -Rv tester .
#su tester -c "LANG=en_US.UTF-8 make -j1 test" &> vim-test.log

make install

ln -sv vim /usr/bin/vi
for L in  /usr/share/man/{,*/}man1/vim.1; do
    ln -sv vim.1 $(dirname $L)/vi.1
done
ln -sv ../vim/vim82/doc /usr/share/doc/vim-8.2.2433

cat > /etc/vimrc << "EOF"
" Begin /etc/vimrc

" Ensure defaults are set before customizing settings, not after
source $VIMRUNTIME/defaults.vim
let skip_defaults_vim=1

set nocompatible
set backspace=2
set mouse=
syntax on
if (&term == "xterm") || (&term == "putty")
  set background=dark
endif

" End /etc/vimrc
EOF

# vim -c ':options'

cd /sources
rm -rf vim-8.2.2433


# 8.70 Systemd-247
# 8.70.1. Installation of systemd

cd /sources
tar xf systemd-247.tar.gz
cd systemd-247

patch -Np1 -i ../systemd-247-upstream_fixes-1.patch
ln -sf /bin/true /usr/bin/xsltproc
tar -xf ../systemd-man-pages-247.tar.xz
sed '181,$ d' -i src/resolve/meson.build
sed -i 's/GROUP="render"/GROUP="video"/' rules.d/50-udev-default.rules.in
mkdir -p build
cd       build

LANG=en_US.UTF-8                    \
meson --prefix=/usr                 \
      --sysconfdir=/etc             \
      --localstatedir=/var          \
      -Dblkid=true                  \
      -Dbuildtype=release           \
      -Ddefault-dnssec=no           \
      -Dfirstboot=false             \
      -Dinstall-tests=false         \
      -Dkmod-path=/bin/kmod         \
      -Dldconfig=false              \
      -Dmount-path=/bin/mount       \
      -Drootprefix=                 \
      -Drootlibdir=/lib             \
      -Dsplit-usr=true              \
      -Dsulogin-path=/sbin/sulogin  \
      -Dsysusers=false              \
      -Dumount-path=/bin/umount     \
      -Db_lto=false                 \
      -Drpmmacrosdir=no             \
      -Dhomed=false                 \
      -Duserdb=false                \
      -Dman=true                    \
      -Dmode=release                \
      -Ddocdir=/usr/share/doc/systemd-247 \
      ..
LANG=en_US.UTF-8 ninja
LANG=en_US.UTF-8 ninja install
rm -f /usr/bin/xsltproc
rm -rf /usr/lib/pam.d
systemd-machine-id-setup
systemctl preset-all
systemctl disable systemd-time-wait-sync.service

cd /sources
rm -rf systemd-247


# 8.71 D-Bus-1.12.20
# 8.71.1. Installation of D-Bus

cd /sources
tar xf dbus-1.12.20.tar.gz
cd dbus-1.12.20

./configure --prefix=/usr                        \
            --sysconfdir=/etc                    \
            --localstatedir=/var                 \
            --disable-static                     \
            --disable-doxygen-docs               \
            --disable-xml-docs                   \
            --docdir=/usr/share/doc/dbus-1.12.20 \
            --with-console-auth-dir=/run/console \
            --with-system-pid-file=/run/dbus/pid \
            --with-system-socket=/run/dbus/system_bus_socket
make
make install
mv -v /usr/lib/libdbus-1.so.* /lib
ln -sfv ../../lib/$(readlink /usr/lib/libdbus-1.so) /usr/lib/libdbus-1.so
ln -sfv /etc/machine-id /var/lib/dbus

cd /sources
rm -rf dbus-1.12.20


# 8.72 Procps-ng-3.3.17
# 8.72.1. Installation of Procps-ng

cd /sources
tar xf procps-ng-3.3.17.tar.xz
cd procps-ng-3.3.17

./configure --prefix=/usr                            \
            --exec-prefix=                           \
            --libdir=/usr/lib                        \
            --docdir=/usr/share/doc/procps-ng-3.3.17 \
            --disable-static                         \
            --disable-kill                           \
            --with-systemd
make
#make check
make install

mv -v /usr/lib/libprocps.so.* /lib
ln -sfv ../../lib/$(readlink /usr/lib/libprocps.so) /usr/lib/libprocps.so

cd /sources
rm -rf procps-ng-3.3.17


# 8.73 Util-linux-2.36.2
# 8.73.1. Installation of Util-linux

cd /sources
tar xf util-linux-2.36.2.tar.xz
cd util-linux-2.36.2

./configure ADJTIME_PATH=/var/lib/hwclock/adjtime    \
            --docdir=/usr/share/doc/util-linux-2.36.2 \
            --disable-chfn-chsh  \
            --disable-login      \
            --disable-nologin    \
            --disable-su         \
            --disable-setpriv    \
            --disable-runuser    \
            --disable-pylibmount \
            --disable-static     \
            --without-python     \
            runstatedir=/run
make

bash tests/run.sh --srcdir=$PWD --builddir=$PWD
chown -Rv tester .
#su tester -c "make -k check"

make install

cd /sources
rm -rf util-linux-2.36.2


# 8.74 E2fsprogs-1.46.1
# 8.74.1. Installation of E2fsprogs

cd /sources
tar xf e2fsprogs-1.46.1.tar.gz
cd e2fsprogs-1.46.1

mkdir -v build
cd       build

../configure --prefix=/usr           \
             --bindir=/bin           \
             --with-root-prefix=""   \
             --enable-elf-shlibs     \
             --disable-libblkid      \
             --disable-libuuid       \
             --disable-uuidd         \
             --disable-fsck
make
#make check
make install

rm -fv /usr/lib/{libcom_err,libe2p,libext2fs,libss}.a
gunzip -v /usr/share/info/libext2fs.info.gz
install-info --dir-file=/usr/share/info/dir /usr/share/info/libext2fs.info
makeinfo -o      doc/com_err.info ../lib/et/com_err.texinfo
install -v -m644 doc/com_err.info /usr/share/info
install-info --dir-file=/usr/share/info/dir /usr/share/info/com_err.info

cd /sources
rm -rf e2fsprogs-1.46.1


# 8.75 About Debugging Symbols


# 8.76 Stripping Again
save_lib="ld-2.33.so libc-2.33.so libpthread-2.33.so libthread_db-1.0.so"

cd /lib

for LIB in $save_lib; do
    objcopy --only-keep-debug $LIB $LIB.dbg
    strip --strip-unneeded $LIB
    objcopy --add-gnu-debuglink=$LIB.dbg $LIB
done

save_usrlib="libquadmath.so.0.0.0 libstdc++.so.6.0.28
             libitm.so.1.0.0 libatomic.so.1.2.0"

cd /usr/lib

for LIB in $save_usrlib; do
    objcopy --only-keep-debug $LIB $LIB.dbg
    strip --strip-unneeded $LIB
    objcopy --add-gnu-debuglink=$LIB.dbg $LIB
done

unset LIB save_lib save_usrlib
find /usr/lib -type f -name \*.a \
   -exec strip --strip-debug {} ';'

find /lib /usr/lib -type f -name \*.so* ! -name \*dbg \
   -exec strip --strip-unneeded {} ';'

find /{bin,sbin} /usr/{bin,sbin,libexec} -type f \
    -exec strip --strip-all {} ';'


# 8.77 Cleaning Up
rm -rf /tmp/*
logout
chroot "$LFS" /usr/bin/env -i          \
    HOME=/root TERM="$TERM"            \
    PS1='(lfs chroot) \u:\w\$ '        \
    PATH=/bin:/usr/bin:/sbin:/usr/sbin \
    /bin/bash --login
find /usr/lib /usr/libexec -name \*.la -delete
find /usr -depth -name $(uname -m)-lfs-linux-gnu\* | xargs rm -rf
rm -rf /tools
userdel -r tester

Ab hier gibt es kein simples Copy & Paste mehr. Die Netzwerkkonfiguration sowie Angaben zu den Disks müssen auf die eigene Umgebung angepasst werden.

# Chapter 9 System Configuration
# 9.1 Introduction

# 9.2 General Network Configuration
# 9.2.1. Network Interface Configuration Files

ln -s /dev/null /etc/systemd/network/99-default.link

cat > /etc/systemd/network/10-eth-dhcp.network << "EOF"
[Match]
Name=eth0

[Network]
DHCP=ipv4

[DHCP]
UseDomains=true
EOF

cat > /etc/resolv.conf << "EOF"
# Begin /etc/resolv.conf
domain linuxfabrik.loc
nameserver 192.168.122.1
# End /etc/resolv.conf
EOF

echo "lfs.linuxfabrik.loc" > /etc/hostname
cat > /etc/hosts << "EOF"
# Begin /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
127.0.0.1   lfs.linuxfabrik.loc
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
ff02::1     ip6-allnodes
ff02::2     ip6-allrouters
# End /etc/hosts
EOF
# 9.5. Configuring the system clock

cat > /etc/adjtime << "EOF"
0.0 0 0.0
0
LOCAL
EOF

timedatectl set-timezone Europe/Zurich
# 9.6. Configuring the Linux Console

cat > /etc/vconsole.conf << "EOF"
KEYMAP="de_CH-latin1"
FONT="eurlatgr"
EOF
# 9.7. Configuring the System Locale

localectl set-locale LANG="en_US.UTF-8"
# 9.8. Creating the /etc/inputrc File

cat > /etc/inputrc << "EOF"
# Begin /etc/inputrc
# Modified by Chris Lynn <roryo@roryo.dynup.net>

# Allow the command prompt to wrap to the next line
set horizontal-scroll-mode Off

# Enable 8bit input
set meta-flag On
set input-meta On

# Turns off 8th bit stripping
set convert-meta Off

# Keep the 8th bit for display
set output-meta On

# none, visible or audible
set bell-style none

# All of the following map the escape sequence of the value
# contained in the 1st argument to the readline specific functions
"\eOd": backward-word
"\eOc": forward-word

# for linux console
"\e[1~": beginning-of-line
"\e[4~": end-of-line
"\e[5~": beginning-of-history
"\e[6~": end-of-history
"\e[3~": delete-char
"\e[2~": quoted-insert

# for xterm
"\eOH": beginning-of-line
"\eOF": end-of-line

# for Konsole
"\e[H": beginning-of-line
"\e[F": end-of-line

# End /etc/inputrc
EOF
# 9.9. Creating the /etc/shells File

cat > /etc/shells << "EOF"
# Begin /etc/shells

/bin/sh
/bin/bash

# End /etc/shells
EOF
# Chapter 10 Making the LFS System Bootable
# 10.1 Introduction
# 10.2 Creating the /etc/fstab File

blkid

cat > /etc/fstab << "EOF"
# Begin /etc/fstab

UUID=85c0c6dc-9eec-4f1e-b56e-0437d3a0aeac  /        ext4     defaults            0 0
UUID=cfcf2c48-405c-4411-beec-1e530af48a90  swap     swap     pri=1               0 0
UUID=c9c9a304-9a88-4278-8b68-61c7f182fa2b  /home    ext4     defaults            0 0
proc                                       /proc    proc     nosuid,noexec,nodev 0 0
sysfs                                      /sys     sysfs    nosuid,noexec,nodev 0 0
devpts                                     /dev/pts devpts   gid=5,mode=620      0 0
tmpfs                                      /run     tmpfs    defaults            0 0
devtmpfs                                   /dev     devtmpfs mode=0755,nosuid    0 0

# End /etc/fstab
EOF
# 10.3. Linux-5.10.17

# 10.3.1. Installation of the kernel

cd /sources
tar xf linux-5.10.17.tar.xz
cd linux-5.10.17

make mrproper
make defconfig
#make menuconfig

Diese Features sollten ein- bzw. abgeschaltet sein:

General setup -->
   [ ] Auditing Support [CONFIG_AUDIT]
   [*] Control Group support [CONFIG_CGROUPS]
   [ ] Enable deprecated sysfs features to support old userspace tools [CONFIG_SYSFS_DEPRECATED]
   [*] Configure standard kernel features (expert users) [CONFIG_EXPERT] --->
      [*] open by fhandle syscalls [CONFIG_FHANDLE]
Processor type and features  --->
   [*] Enable seccomp to safely compute untrusted bytecode [CONFIG_SECCOMP]
Firmware Drivers  --->
   [*] Export DMI identification via sysfs to userspace [CONFIG_DMIID]
Networking support  --->
  Networking options  --->
   <*> The IPv6 protocol [CONFIG_IPV6]
Device Drivers  --->
  Generic Driver Options  --->
   [ ] Support for uevent helper [CONFIG_UEVENT_HELPER]
   [*] Maintain a devtmpfs filesystem to mount at /dev [CONFIG_DEVTMPFS]
   Firmware Loader --->
      [ ] Enable the firmware sysfs fallback mechanism [CONFIG_FW_LOADER_USER_HELPER]
File systems  --->
   [*] Inotify support for userspace [CONFIG_INOTIFY_USER]
  Pseudo filesystems  --->
   [*] Tmpfs POSIX Access Control Lists [CONFIG_TMPFS_POSIX_ACL]
# takes round about 20 minutes or more

make
make modules_install

cp -iv arch/x86/boot/bzImage /boot/vmlinuz-5.10.17-lfs-10.1-systemd
cp -iv System.map /boot/System.map-5.10.17
cp -iv .config /boot/config-5.10.17
install -d /usr/share/doc/linux-5.10.17
cp -r Documentation/* /usr/share/doc/linux-5.10.17


# 10.3.2. Configuring Linux Module Load Order

install -v -m755 -d /etc/modprobe.d
cat > /etc/modprobe.d/usb.conf << "EOF"
# Begin /etc/modprobe.d/usb.conf

install ohci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i ohci_hcd ; true
install uhci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i uhci_hcd ; true

# End /etc/modprobe.d/usb.conf
EOF


# 10.4 Using GRUB to Set Up the Boot Process
# 10.4.1. Introduction


# 10.4.2. GRUB Naming Conventions
# 10.4.3. Setting Up the Configuration

grub-install /dev/sda
grub-mkconfig --output=/boot/grub/grub.cfg
# Chapter 11 The End
# 11.1 The End

echo 10.1-systemd > /etc/lfs-release

cat > /etc/lsb-release << "EOF"
DISTRIB_ID="Linux From Scratch"
DISTRIB_RELEASE="10.1-systemd"
DISTRIB_CODENAME="built with love by Linuxfabrik"
DISTRIB_DESCRIPTION="Linux From Scratch"
EOF

cat > /etc/os-release << "EOF"
NAME="Linux From Scratch"
VERSION="10.1-systemd"
ID=lfs
PRETTY_NAME="Linux From Scratch 10.1-systemd"
VERSION_CODENAME="built with love by Linuxfabrik"
EOF
passwd root
# 11.2 Get Counted
# 11.3 Rebooting the System

logout
umount -Rv $LFS
shutdown now

Built on 2024-04-18