Einführung
In dieser Artikelreihe möchte ich das Buildroot-Betriebssystem und meine Erfahrungen mit seiner Anpassung vorstellen. Es wird praktische Erfahrungen bei der Erstellung eines kleinen Betriebssystems mit grafischer Benutzeroberfläche und minimaler Funktionalität geben.
Zunächst sollte man das Build-System nicht mit einer Distribution verwechseln. Buildroot kann ein System aus einem Satz von Paketen erstellen, die ihm angeboten werden. Es basiert auf Makefiles und bietet daher umfangreiche Anpassungsmöglichkeiten. Ein Paket durch eine andere Version ersetzen, eigenes Paket hinzufügen, die Build-Regeln ändern oder das Dateisystem nach der Installation aller Pakete anpassen? All das kann Buildroot.
In Russland wird Buildroot verwendet, aber meiner Meinung nach gibt es wenig russischsprachige Informationen für Anfänger.
Ziel der Arbeit ist es, eine Distribution mit Live-Start, einer IceWM-Oberfläche und einem Browser zu erstellen. Die Zielplattform ist VirtualBox.
Warum sollte man seine eigene Distribution erstellen? Oft benötigt man eine eingeschränkte Funktionalität bei begrenzten Ressourcen. Noch häufiger müssen im Automatisierungsprozess Firmware erstellt werden. Eine allgemeine Distribution anzupassen, indem überflüssige Pakete entfernt werden und sie in eine Firmware umgewandelt wird, ist weitaus mühsamer, als eine neue Distribution zu erstellen. Auch die Verwendung von Gentoo hat ihre eigenen Einschränkungen.
Buildroot ist ein sehr leistungsfähiges System, aber es tut nichts für Sie. Es bietet lediglich Möglichkeiten und automatisiert den Build-Prozess.
Alternative Build-Systeme (Yocto, Open Build System und andere) werden nicht betrachtet und nicht verglichen.
Wo man es finden kann und wie man anfängt
Die Projektwebsite ist — . Hier kann man die aktuelle Version herunterladen und die Anleitung lesen. Dort kann man auch die Community ansprechen, es gibt einen Bugtracker, Mailinglisten und einen IRC-Kanal.
Buildroot arbeitet mit Defconfigs für die Zielplatine. Defconfig ist eine Konfigurationsdatei, die nur Optionen enthält, die keine Standardwerte haben. Sie bestimmt, was und wie gebaut wird. Dabei können die Konfigurationen von Busybox, Linux-Kernel, uClibc sowie die Bootloader u-boot und barebox separat eingestellt werden, aber alle werden an die Zielplatine gebunden sein.
Nach dem Entpacken des heruntergeladenen Archivs oder dem Klonen aus Git erhalten wir ein betriebsbereites Buildroot. Detaillierte Informationen zur Verzeichnisstruktur finden Sie im Handbuch, ich werde die wichtigsten Punkte erläutern:
board — Verzeichnis mit platzierten spezifischen Dateien für jede Platine. Dazu gehören Skripte zur Erstellung von System-Images (ISO, SDCart, CPIO usw.), das Overlay-Verzeichnis, Kernel-Konfigurationen und weitere Dateien.
configs — tatsächlich die defconfig der Platine. Defconfig ist eine unvollständige Konfiguration der Platine. Sie enthält nur die Parameter, die von den standardmäßigen Einstellungen abweichen.
dl — Verzeichnis mit heruntergeladenen Quellcodes/Dateien für den Build.
output/target — das erstellte Dateisystem des erhaltenen Betriebssystems. Daraus werden später Images für das Booten/Installieren erstellt.
output/host — Host-Utilities für den Build.
output/build — erstellte Pakete.
Die Konfiguration des Builds erfolgt über KConfig. Dasselbe System wird für den Bau des Linux-Kernels verwendet. Hier ist eine Liste der am häufigsten verwendeten Befehle (auszuführen im Verzeichnis Buildroot):
- make menuconfig — um die Build-Konfiguration aufzurufen. Es besteht auch die Möglichkeit, eine grafische Benutzeroberfläche zu nutzen (make nconfig, make xconfig, make gconfig).
- make linux-menuconfig — um die Kernel-Konfiguration aufzurufen.
- make clean — bereinigen Sie die Build-Ergebnisse (alle Inhalte im output)
- make — das System zusammenstellen. Dabei werden bereits kompilierte Prozesse nicht erneut gebaut.
- make defconfig_name — die Konfiguration auf einen bestimmten defconfig umschalten
- make list-defconfigs — eine Liste der defconfig anzeigen
- make source — nur die Installationsdateien herunterladen, ohne zu bauen.
- make help — eine Liste der verfügbaren Befehle ausgeben
Wichtige Hinweise und nützliche Tipps
Buildroot rekonstruiert keine bereits erstellten Pakete! Daher kann die Notwendigkeit entstehen, eine vollständige Neukompilierung durchzuführen.
Ein einzelnes Paket kann mit dem Befehl rekonstruiert werden make packagename-rebuild. Zum Beispiel kann der Linux-Kernel rekonstruiert werden:
make linux-rebuildBuildroot speichert den Zustand eines Pakets durch die Erstellung von .stamp-Dateien im Verzeichnis output/build/$packagename:

Daher können root-fs und Images ohne Neukompilierung der Pakete rekonstruiert werden:
rm output/build/host-gcc-final-*/.stamp_host_installed; rm -rf output/target; find output/ -name ".stamp_target_installed" | xargs rm -rf ; makeNützliche Variablen
Im Buildroot gibt es eine Reihe von Variablen für eine bequeme Konfiguration
- $TOPDIR — Stammverzeichnis von Buildroot
- $BASEDIR — Verzeichnis OUTPUT
- $HOST_DIR, $STAGING_DIR, $TARGET_DIR — Verzeichnisse für die Erstellung von Host-FS, Staging-FS, Ziel-FS.
- $BUILD_DIR — Verzeichnis mit entpackten und zusammengesetzten Paketen
Visualisierung
In Buildroot gibt es die Möglichkeit zur Visualisierung. Sie können ein Abhängigkeitsdiagramm, ein Diagramm der Build-Zeit und ein Diagramm der Paketgrößen im Endsystem erstellen. Die Ergebnisse liegen in Form von PDF-Dateien vor (auf Wunsch auch als SVN, PNG) im Verzeichnis output/graph.
Beispiele für Visualisierungsbefehle:
make graph-dependsAbhängigkeitsbaum erstellenmake -graph-dependsAbhängigkeitsbaum eines bestimmten Pakets erstellenBR2_GRAPH_OUT=png make graph-buildBuild-Zeit-Diagramm im PNG-Format erstellenmake graph-sizeDiagramm der Paketgrößen erstellen
Nützliche Skripte
Im Buildroot-Verzeichnis gibt es ein Unterverzeichnis utils mit nützlichen Skripten. Zum Beispiel gibt es ein Skript, das die Richtigkeit der Paketbeschreibungen überprüft. Dies kann hilfreich sein, wenn Sie eigene Pakete hinzufügen (ich werde dies später tun). Im Datei utils/readme.txt gibt es eine Beschreibung dieser Skripte.
Wir erstellen ein Standard-Distribution
Es ist wichtig zu beachten, dass alle Operationen im Namen eines normalen Benutzers und nicht von root durchgeführt werden.
Alle Befehle werden im Stammverzeichnis von Buildroot ausgeführt. In der Buildroot-Lieferung gibt es bereits eine Reihe von Konfigurationen für viele gängige Platinen und Virtualisierung.
Lassen Sie uns die Konfigurationen anzeigen:

Wir wechseln zu der Konfiguration qemu_x86_64_defconfig
make qemu_x86_64_defconfigUnd starten den Build
makeDer Bau wurde erfolgreich abgeschlossen, schauen wir uns die Ergebnisse an:
![]()
Buildroot hat Images erstellt, die in Qemu gestartet werden können, um sicherzustellen, dass sie funktionieren.
qemu-system-x86_64 -kernel output/images/bzImage -hda output/images/rootfs.ext2 -append "root=/dev/sda rw" -s -SDas Ergebnis – ein in Qemu gestartetes System:

Erstellung der Konfiguration für die eigene Platine
Hinzufügen der Dateien für die Platine
Lassen Sie uns die Konfigurationen anzeigen:

Im Menü sehen wir pc_x86_64_efi_defconfig. Wir werden unsere Platine erstellen, indem wir sie von dieser Konfiguration kopieren:
cp configs/pc_x86_64_bios_defconfig configs/my_x86_board_defconfigLassen Sie uns sofort ein Verzeichnis für die Platine erstellen, um unsere Skripte, rootfs-overlay und andere benötigte Dateien zu speichern:
mkdir board/my_x86_boardWir wechseln zu diesem defconfig:
make my_x86_board_defconfigSo entspricht die Build-Konfiguration jetzt (gespeichert in .config im Hauptverzeichnis von Buildroot) der Zielmaschine x86-64 Legacy (BIOS) Boot.
Kopieren Sie die Konfiguration des Linux-Kernels (nützlich für die Zukunft):
cp board/pc/linux.config board/my_x86_board/Konfiguration der Build-Parameter über KConfig
Starten Sie die Konfiguration:
make menuconfig Das KConfig-Fenster wird geöffnet. Es gibt die Möglichkeit, mit einer grafischen Benutzeroberfläche zu konfigurieren (make nconfig, make xconfig, make gconfig):

Gehen Sie in den ersten Abschnitt Target Options. Hier kann die Zielarchitektur ausgewählt werden, für die der Build durchgeführt wird.

Build-Optionen – hier finden Sie verschiedene Einstellungen für den Build-Prozess. Sie können Verzeichnisse mit Quellcodes, die Anzahl der Build-Threads, Mirrors zum Herunterladen der Quellcodes und andere Einstellungen angeben. Lassen Sie die Standardkonfigurationen unverändert.
Toolchain – hier wird das eigentliche Build-Toolset konfiguriert. Weitere Informationen dazu folgen.

Toolchain-Typ – der verwendete Toolchain-Typ. Dies kann entweder der in Buildroot integrierte oder ein externer Toolchain sein (Sie können ein Verzeichnis mit bereits erstellten Dateien oder eine URL zum Herunterladen angeben). Für verschiedene Architekturen gibt es zusätzliche Optionen. Beispielsweise kann für ARM einfach die Version des externen Linaro-Toolchains ausgewählt werden.
C-Bibliothek – die Wahl der C-Bibliothek, die für die gesamte Systemfunktionalität entscheidend ist. In der Regel wird glibc verwendet, die alle möglichen Funktionen unterstützt. Diese kann jedoch zu umfangreich für ein Embedded-System sein, weshalb oft uglibc oder musl gewählt werden. Wir wählen glibc (dies ist später erforderlich, um systemd verwenden zu können).
Kernel-Header und benutzerdefinierte Kernel-Header-Serie – müssen mit der Version des Kernels übereinstimmen, die im zu erstellenden System verwendet wird. Für Kernel-Header können Sie auch den Pfad zu einem Tarball oder ein Git-Repository angeben.
GCC-KOMPILER VERSIONEN – Wählen Sie die Version des Compilers aus, die für den Build verwendet werden soll.
C++-Unterstützung aktivieren – Wir wählen für den Build die Unterstützung von C++-Bibliotheken im System. Dies wird uns später nützlich sein.
Zusätzliche gcc-Optionen – Hier können zusätzliche Compiler-Optionen angegeben werden. Momentan benötigen wir das nicht.
Die Systemkonfiguration ermöglicht es, zukünftige Parameter des erstellten Systems festzulegen:

Die meisten Punkte sind aus dem Titel klar. Beachten Sie insbesondere die folgenden Punkte:
Pfad zu den Benutzertabellen – Tabelle mit den zu erstellenden Benutzern ().
Beispiel einer Datei. Es wird ein Benutzer mit dem Namen user und dem Passwort admin erstellt, automatisch gid/uid, mit /bin/sh als Shell, der Standardgruppe user zugeordnet und Mitglied der Gruppe root, Kommentar Foo user.
[alexey@alexey-pc buildroot]$ cat board/my_x86_board/users.txt
user -1 user -1 =admin /home/user /bin/sh root Foo userRoot-Dateisystem-Overlay-Verzeichnisse – Verzeichnis, das über das erstellte target-fs gelegt wird. Fügt neue Dateien hinzu und ersetzt vorhandene.
Benutzerdefinierte Skripte, die vor der Erstellung von Dateisystembildern ausgeführt werden – Skripte, die direkt vor dem Packen des Dateisystems in Abbildern ausgeführt werden. Das Skript lassen wir zunächst leer.
Gehen wir zum Abschnitt Kernel

Hier werden die Kernel-Einstellungen festgelegt. Der Kernel wird über make linux-menuconfig konfiguriert.
Die Kernelversion kann auf verschiedene Arten festgelegt werden: entweder aus den vorgeschlagenen auswählen, die Version manuell eingeben, ein Repository angeben oder ein fertiges Tarball verwenden.
Die Kernelkonfiguration ist der Pfad zur Kernelkonfiguration. Es kann die Standardkonfiguration für die gewählte Architektur oder ein defconfig aus Linux ausgewählt werden. In den Linux-Quellen gibt es eine Reihe von defconfigs für verschiedene Zielsysteme. Die benötigte Konfiguration kann Zum Beispiel kann für das BeagleBone Black .
Der Abschnitt Zielpakete ermöglicht es, auszuwählen, welche Pakete im zu erstellenden System installiert werden. Wir lassen das vorerst unverändert. Später fügen wir unsere Pakete zu dieser Liste hinzu.
Dateisystem-Images sind eine Liste von Dateisystemabbildern, die erstellt werden. Wir fügen ein ISO-Image hinzu.

Bootloader — die Auswahl der zu erstellenden Bootloader. Wir wählen isolinix aus.

Konfiguration von Systemd.
Systemd wird zu einer der Säulen von Linux, neben Kernel und glibc. Deshalb habe ich seine Konfiguration in einen eigenen Punkt ausgegliedert.
Die Konfiguration erfolgt über make menuconfig, dann Zielpakete → Systemtools → systemd. Hier kann angegeben werden, welche Systemd-Dienste installiert und beim Systemstart aktiviert werden.

Speicherung der Systemkonfiguration.
Wir speichern diese Konfiguration über KConfig.
Anschließend speichern wir unser defconfig:
make savedefconfigKonfiguration des Linux-Kernels
Die Konfiguration des Linux-Kernels erfolgt mit folgendem Befehl:
make linux-menuconfigFügen wir die Unterstützung für die VirtualBox-Grafikkarte hinzu.

Fügen wir die Unterstützung für die VirtualBox-Gastintegration hinzu.

Speichern und beenden. WICHTIG: die Konfiguration wird in output/build/linux-$version/config gespeichert, jedoch nicht in board/my_x86_board/linux.config.

Sie müssen daher die Konfiguration manuell an den Speicherort kopieren:
cp output/build/linux-4.19.25/.config board/my_x86_board/linux.configAnschließend führen wir eine vollständige Neubau der gesamten Systemumgebung durch. Da Buildroot bereits erstellte Pakete nicht neu erstellt, müssen die Pakete manuell zur Neubearbeitung angegeben werden. Um Zeit und Nerven zu sparen, ist es einfacher, ein kleines System vollständig neu zu erstellen:
make clean; makeNach Abschluss des Baus starten wir VirtualBox (getestet mit Version 5.2 und 6.0) und booten von der CD. Systemeinstellungen:

Start mit dem erstellten ISO:

Liste der verwendeten Materialien
- Buildroot-Handbuch
Quelle: habr.com
