Experience Embedded

Professionelle Schulungen, Beratung und Projektunterstützung

Yocto: Das geht auch automatisch!

Autor: Simon Egli, bbv Software Services

Beitrag - Embedded Software Engineering Kongress 2015

 

Das Yocto-Buildsystem ist ein großes und mächtiges Werkzeug. Für den Einsteiger ist es oftmals schwierig, die Zusammenhänge des Buildsystems 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 Beispielsdistribution gebildet werden. [1]

Alle hier erstellten Dateien können auch von GitHub heruntergeladen werden; siehe weiterführende Links.

Initialisieren eines Yocto-Projekts

Mit folgenden Kommandos wird ein neues Yocto-Projekt angelegt und das Terminal für die nachfolgenden Befehle vorbereitet. [2]

~/ $ git clone git://git.yoctoproject.org/poky.git ~/yocto/poky

~/ $ source ~/yocto/poky/oe-init-build-env

 

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 Beispiels-Layer dieses Beitrags wird «ese» benannt.

~/yocto/build$ ../poky/scripts/yocto-layer create ese -o ../poky/meta-ese

Please enter the layer priority you'd like to use for the layer: [default: 6]

Would you like to have an example recipe created? (y/n) [default: n]

Would you like to have an example bbappend file created? (y/n) [default: n]

New layer created in meta-ese.

 

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.

~/yocto/build $ vi ./conf/bblayers.conf

BBLAYERS ?= " \

  /home/dead/yocto/poky/meta \

  /home/dead/yocto/poky/meta-yocto \

  /home/dead/yocto/poky/meta-yocto-bsp \

  /home/dead/yocto/poky/meta-ese \

  "

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/bin[3] 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 (siehe auch Abbildung 1, PDF).

#include <stdio.h>


int main(int argc, char **argv)

{

    printf("Hello World! ");

    return 0;

}

 

Entgegen diesem Beispiel wird der Sourcecode oft auch mithilfe 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 fr diese relativ einfache Aufgabe mehrere Zeilen.

SUMMARY = "Simple helloworld application"

SECTION = "examples"

LICENSE = "MIT"

LIC_FILES_CHKSUM = "file:///MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

 

SRC_URI = "file://helloworld.c"

 

S = ""

 

do_compile() {

             helloworld.c -o helloworld

}

 

do_install() {

             install -d

             install -m 0755 helloworld

}

 

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, sog. 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".

~/yocto/build$ bitbake hello-world

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 beliegenden Tool erledigt werden.

~/yocto/build$ recipetool newappend ../poky/meta-ese cronie

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 heisst somit neu cronie_%.bbappend.

Der Inhalt der Datei ist sehr kurz:

FILESEXTRAPATHS_prepend := "/files:"

SRC_URI += "file://crontab

 

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.

# /etc/crontab: system-wide crontab

# Example crontab-File for the meta-ese layer

 

SHELL=/bin/sh

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

 

#  m  h  dom mon dow user       command

*/5 * * * * root echo "Hello world" > /var/log/syslog &

 

Damit kann auch dieses Rezept gebacken werden:
 
~/yocto/build $ bitbake cronie
 

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.

# Base this image on core-image-minimal

include recipes-core/images/core-image-base.bb

IMAGE_INSTALL += "hello-world cronie"

 

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.

~/yocto/poky$ bitbake ese-image

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 aussen vor gelassen (siehe Abbildung 2, PDF).

Der Leser wird dazu ermutigt, die weiterführende Dokumentation von Bitbake und Yocto durchzulesen und sein Wissen zu vertiefen.  

Weiterführende Links


[1] Alle im Dokument enthaltenen Terminal-Befehle verwenden die Struktur «Ort $ Befehl Parameter
[2] Für die Beispiele wird eine Linux-Umgebung verwendet.
[3] Dem Programmpfad unter Linux

 

Beitrag als PDF downloaden


Open Source - unsere Trainings & Coachings

Wollen Sie sich auf den aktuellen Stand der Technik bringen?

Dann informieren Sie sich hier zu Schulungen/ Seminaren/ Trainings/ Workshops und individuellen Coachings von MircoConsult zum Thema Open Source / Embedded Software Engineering.

 

Training & Coaching zu den weiteren Themen unseren Portfolios finden Sie hier.


Open Source - Fachwissen

Wertvolles Fachwissen zum Thema Open Source / Embedded Software Engineering steht hier für Sie zum kostenfreien Download bereit.

Zu den Fachinformationen

 
Fachwissen zu weiteren Themen unseren Portfolios finden Sie hier.