Open Source Yocto: Das geht auch automatisch!
Anbieter zum Thema
Das Yocto-Build-System ist ein großes und mächtiges Werkzeug. Für den Einsteiger ist es oftmals schwierig, die Zusammenhänge des Build-Systems zu sehen, und der Start eines eigenen Projektes gestaltet sich entsprechend schwierig. Dieser Beitrag zeigt Schritt für Schritt den Bau einer einfachen Distribution mit eigenen Rezepten. Der Leser dieses Artikels ist dafür gerüstet, weiterführende Themen auf eigene Faust zu meistern.

Das Yocto-Projekt stellt Herstellern von Embedded-Produkten Tools und Metadaten zur Verfügung, um eigene Linux-basierte Distributionen hardwareunabhängig zu entwickeln. Mit Yocto lassen sich alle Eigenschaften und Eigenheiten eines Systems schon von vornherein bestimmen, testen und gegebenenfalls auf einem virtuellen System simulieren. Typischerweise sollen selbst entwickelte Programme, zusammen mit eigenen Konfigurationsfiles und den üblichen Standardprogrammen (SSH, vim o.ä.), in das fertige Image eingebunden werden.
Einzelne Einheiten werden in sogenannte Rezepte unterteilt, diese beschreiben die Schritte, um eine Programmeinheit mit Hilfe des Bitbake-Programms zu «backen». Die Rezepte sind wiederum in sogenannte Schichten (engl. «Layer») zusammengefasst, welche helfen, die Komplexität der vielen Rezepte zu unterteilen. Nachfolgend soll eine kleine Beispieldistribution gebildet werden.1 Alle hier erstellten Dateien können auch von GitHub heruntergeladen werden; siehe weiterführende Links.
Initialisieren eines Yocto-Projekts
Mit den Kommandos aus Quellcode 1 wird ein neues Yocto-Projekt angelegt und das Terminal für die nachfolgenden Befehle vorbereitet.2 Der Source-Befehl initialisiert das Terminal und wechselt in das zum Builden automatisch generierte Verzeichnis. Die nachfolgenden Schritte nehmen an, dass diese Befehle vorgängig ausgeführt worden sind und dieses initialisierte Terminal verwendet wird.
Einen eigenen Layer erstellen
Ein eigener Layer wird am einfachsten mit einem zur Verfügung gestellten Script erstellt. Jeder Layer besitzt eine anpassbare Priorität und kann so Rezepte von weniger hoch eingestuften Sammlungen erweitern oder überschreiben. Der Beispiel-Layer dieses Beitrags wird «ese» benannt (Quellcode 2). Nach der Beantwortung der benötigten Angaben des Skripts werden die Verzeichnisstruktur und die benötigten Konfigurationsdateien Yocto-konform angelegt. Damit der neu angelegte Layer mit in das System eingebunden wird, muss er in der Datei «conf/bblayers.conf» eingetragen werden (Quellcode 3). Durch diesen Eintrag ist der neue Layer eingebunden und wird beim nächsten Bauen der Distribution mit einbezogen.
Ein eigenes Rezept
Mit dem neu erstellten Layer lässt sich jetzt ein Rezept für ein eigenes Programm hinzufügen. Im Verzeichnis «meta-ese» wird ein Verzeichnis «recipes-example» angelegt und darin ein weiterer Unterordner Namens «hello-world». Dies ist der Hauptordner für das selbst erstellte Rezept.
Es handelt sich hierbei um ein kleines hello-world-Programm (in C geschrieben), welches unter /usr/bin3 installiert werden soll. Rezepte in einem Layer sind stets unter einem Begriff zusammengefasst. Bitbake sucht Rezepte standardmässig nur in solchen Kollektionen. Im hello-world-Verzeichniss wird ein Ordner mit dem Namen «hello-world-0.1» für den Sourcecode des Rezepts erstellt. Darin wird das zu kompilierende C-File «helloworld.c» kreiert (Bild 1 und Quellcode 4).
Entgegen diesem Beispiel wird der Sourcecode oft auch mit Hilfe des dazugehörigen Rezepts automatisch aus dem Internet heruntergeladen. Den Sourcecode-Unterordner findet Bitbake automatisch und verwendet die darin enthaltenen Dateien für die Abarbeitung der im Rezept enthaltenen Schritte. Im Verzeichnis «meta-ese/recipes-example/hello-world» wird das eigentliche Rezept «hello-world_0.1.bb» angelegt. Die Zahlen nach dem Unterstrich stehen für die Versionsnummer und werden für jedes Rezept benötigt.
Der Inhalt des Rezepts umfasst schon für diese relativ einfache Aufgabe mehrere Zeilen (Quellcode 5). Ein Rezept benötigt jeweils eine Lizenzbeschreibung. Hier wird die MIT-Lizenz aus dem Standard-Lizenzen-Verzeichnis verwendet. Jedes Rezept besteht aus mehreren erweiterbaren Standardschritten, sogenannten «Tasks», welche mit «do_» bezeichnet sind. In den wenigsten Fällen müssen die einzelnen Schritte von Hand geschrieben werden: viele Programme benutzen automatisierte Build-Prozesse, etwa cmake oder qmake. Bitbake kann die Kompilierschritte für diese automatisch erkennen und ausführen. Die Schritte des Beispiel-Rezepts kompilieren den Quellcode im «compile»-Task. In «do_install» wird die entstandene ausführbare Datei im «bindir» des «D» – also im /usr/bin-Verzeichnis des fertigen Images – installiert und mit den benötigten Rechten ausgestattet. Wenn das Rezept fertig erstellt ist, kann diese Kompilierung gestartet werden. Im Yocto-Umfeld nennt man das «ein Rezept backen» (Quellcode 6).
Je nach Rezept kann die Abarbeitung einige Zeit in Anspruch nehmen, da alle abhängigen Rezepte auch verarbeitet werden müssen. Der Output des Rezepts kann unter ~/yocto/build/tmp/work/i586-poky-linux/hello-world/0.1-r0/image/ eingesehen werden.
Patchen fremder Rezepte
Oftmals müssen die Rezepte fremder Layer modifiziert werden. Typischerweise soll zum Beispiel ein anderes Konfigurationsfile benutzt oder ein paar Zeilen eines Standardprogramms für die eigene Distribution modifiziert werden. Im folgenden Beispiel soll das Konfigurationsfile des Linux-Schedulers «cron» durch eine eigene Datei ersetzt werden. Das Rezept, in dem Cron enthalten ist, heisst unter Yocto «Cronie» und ist unter meta/recipes-extended/cronie zu finden. Um es zu erweitern, wird ein neues «bbappend»-File erstellt. Dateien mit dieser Endung werden automatisch dazu verwendet, ein gleichnamiges Rezept zu patchen. Die Erstellung dieser Datei und der dazugehörigen Rezeptstruktur soll diesmal von einem Yocto beiliegenden Tool erledigt werden (Quellcode 7).
Das Skript durchsucht die Rezepte und erstellt automatisch eine neue bbappend-Datei am richtigen Ort und mit der aktuellen Version des cronie-Rezepts: /home/dead/yocto/poky/meta-ese/recipes-extended/cronie/cronie_1.5.0.bbappend. Um das Rezept für alle zukünftigen Versionen zu rüsten, wird die Versionsnummer (1.5.0) noch manuell mit «%» – einem Wildcard-Charakter, der alle Versionen zulässt – ersetzt. Die Datei heißt somit neu cronie_%.bbappend. Der Inhalt der Datei des Quellcodes 8 ist sehr kurz.
Die Zeilen weisen Bitbake lediglich an, den Ordner zu berücksichtigen und das darin enthaltene File in das Build-Verzeichnis zu kopieren; dort überschreibt es das Standard-File des Cronie-Rezepts. Das eigentliche, im externen Layer liegende Rezept erledigt die Kompilierung und alle anderen benötigten Schritte. Um das Konfigurationsfile vom Rezept zu trennen, werden ein neuer Unterordner in ~/yocto/poky/meta-ese/recipes-extended/cronie namens «files» und darin ein modifiziertes crontab-File erstellt (Quellcode 9).
Damit kann auch dieses Rezept gebacken werden (Quellcode 10). Dies kann wiederum eine Weile dauern – da nicht nur cronie, sondern auch alle Rezepte, von denen Cronie abhängt, gebuildet werden müssen. Das Ergebnis kann schliesslich unter ~/yocto/build/tmp/work/i586-poky-linux/cronie/1.5.0-r0/image inspiziert werden – das Crontab-File sollte korrekt unter /etc/crontab abgelegt sein und wird auf dem fertigen Image mit ausgeliefert werden.
Builden eines Images
Es soll ein Image mit dem eigenen und dem gepatchten Rezept erstellt werden. Als Basis wird ein Beispiel-Image des Standard-poky-Layers «core-image-base» verwendet. Es gibt mehrere Wege, um das Ziel – die Rezepte an dieses Image-Rezept anzuhängen – zu erreichen. Hier wird das Erstellen einer eigenen Rezeptdatei gewählt. Das Rezept wird in ~/yocto/poky/meta-ese/recipes-core/images/ese-image.bb mit folgendem Inhalt erstellt (Quellcode 11).
Die Rezeptekollektion «recipes-core» beinhaltet normalerweise die für das System essenziellen Rezepte, das ist passend für dieses Haupt-Rezept. Die Anweisungen des Image-Rezepts instruieren Bitbake, «hello-world» und das modifizierte cronie zu installieren. Darüber hinaus soll es aber die Anweisungen des «core-image-base»-Images befolgen. Das Image kann nun gebuildet werden (Bild 2 und Quellcode 12).
Der Build-Vorgang dauert längere Zeit, da alle Werkzeuge, Programme und Komponenten für das fertige System gebaut werden müssen. Danach kann das Image beispielsweise auf einer virtuellen Maschine gestartet werden. Um die Rezepte produktiv zu verwenden, müsste ein Hersteller-Layer heruntergeladen und eingebunden werden. Am einfachsten würde daraufhin das ese-image so umgeschrieben werden, dass es, statt des core-image-base, ein vom Hersteller bereitgestelltes Image inkludiert.
Schlussfolgerung
In diesem Beitrag wird die Erstellung einer eigenen Distribution mit Hilfe von Yocto dargestellt. Innert kurzer Zeit kann so ein funktionsfähiges Image generiert werden. Schritt für Schritt kann der Leser dies nachvollziehen und so einen Einblick in das Arbeiten mit Yocto gewinnen. Es wird nur ein kleiner Teil des Funktionsumfangs von Yocto gezeigt, und viele Möglichkeiten und Themen werden außen vor gelassen. Der Leser wird dazu ermutigt, die weiterführende Dokumentation von Bitbake und Yocto durchzulesen und sein Wissen zu vertiefen.
1Für die Beispiele wird eine Linux-Umgebung verwendet.
2Alle im Dokument enthaltenen Terminal-Befehle verwenden die Struktur «Ort $ Befehl Parameter»
3Dem Programmpfad unter Linux
Weiterführende Links
Meta-ese zum Herunterladen – https://github.com/Deadolus/meta-ese
Yocto-Developer-Manual – http://www.yoctoproject.org/docs/current/dev-manual/dev-manual.html
Bitbake-Manual – http://www.yoctoproject.org/docs/current/bitbake-user-manual/bitbake-user-manual.html
Bitbake-Cheatsheet – https://community.freescale.com/docs/DOC-94953
Dieser Beitrag ist ursprünglich auf unserem Schwesterportal Elektronikpraxis.de erschienen.
* Simon Egli ist Embedded-Software-Ingenieur bei der BBV Software Services AG.
(ID:44417787)