Linux embarqué avec Yocto (étape III.3)


Christophe BLAESS – Juillet 2019

III.3 – Code métier dans la production de Yocto

Pour le moment, nous avons compilé notre code métier à l’extérieur de Yocto, en utilisant la toolchain extraite (et installée éventuellement sur une autre machine de développement). Dans cette séquence nous allons voir comment écrire une recette simple afin d’intégrer directement notre code applicatif dans l’image produite par bitbake.

Recette utilisant les Autotools

Les recettes les plus simples à écrire sont celles qui font appel aux méthodes des outils de construction standards comme les Autotools. En effet, Yocto contient déjà des classes (des fichiers .bbclass situés dans poky/meta/classes/) capables de compiler ce type de projet. Il suffit que notre recette demande à hériter des méthodes de la classe.

Je commence par créer un répertoire hello-autotools dans mon layer.

[build-qemu]$ mkdir  ../meta-my-own-layer/recipes-custom/hello-autotools/

Puis j’y écris un fichier de recette.

[build-qemu]$ nano  ../meta-my-own-layer/recipes-custom/hello-autotools/hello-autotools_1.0.bb 

Le contenu de la recette est le suivant :

DESCRIPTION = "A simple hello world application built with autotools."
SECTION = "Custom"

LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"

SRC_URI="https://www.logilin.fr/files/yocto-lab/${PN}-${PV}.tar.bz2"
SRC_URI[md5sum] = "c13438cdc1dfb5580bf79b24cf0c7992"

S = "${WORKDIR}/${PN}"

inherit autotools
  • Nous avons déjà parlé des variables DESCRIPTION, SECTION, LICENSE et LIC_FILES_CHKSUM dans la séquence III.1.
  • La variable SRC_URI contient le lien pour télécharger l’archive du projet. Le nom du fichier est composé du nom du package (contenu dans la variable PN) suivi d’un tiret puis du numéro de version (dans PV) puis de l’extension. Les variables PN et PV sont remplies par Yocto à partir du nom du fichier de recette (ici hello-auto_1.0.bb). Le caractère underscore sert séparer le nom du numéro de version. Yocto connaît les types d’URL courant (http://, https://, ftp://, git://, svn://, etc.) ainsi que les principales extensions de compression (.tar.gz, .zip, .tar.bz2, etc.). Il s’occupe donc de télécharger et d’extraire les fichiers source.
  • Lorsque les fichiers sources ne sont pas fournis avec la recette (dans un répertoire files/ par exemple), et qu’ils sont téléchargés, il est nécessaire de vérifier l’intégrité du package, pour cela la variable SRC_URI[md5sum] fournit une somme de contrôle MD5 (obtenue avec l’utilitaire md5sum).
  • La variable S (comme Sources) indique l’emplacement où bitbake doit se placer pour réaliser les étapes de la compilation. Le package a été décompressé à l’intérieur du répertoire $WORKDIR, mais suivant les projets l’emplacement des sources peut varier. Parfois il y aura un simple répertoire avec le nom du projet (c’est le cas ici, avec hello-autotools/), parfois ce nom sera complété d’un numéro de version (du type hello-autotools-1.0/), parfois il y aura un sous-répertoire supplémentaire (par exemple hello-autotools/src/) ou encore le package sera directement déployé dans $WORKDIR… Quelque soit la situation, on remplit la variable S en conséquence.
  • La ligne inherit autotools enfin indique que la recette doit hériter des méthodes de la classe autotools pour les étapes do_compile(), do_install(), etc.

Il nous suffit à présent d’ajouter la ligne suivante dans notre fichier image.

IMAGE_INSTALL += "hello-autotools"

Après re-compilation, notre projet est bien installé :

Poky (Yocto Project Reference Distro) 2.7 mybox ttyAMA0
mybox login: root
Password: (linux)
root@mybox:~# hello-autotools
Hello from mybox (built with autools)
root@mybox:~# 

Recette utilisant CMake

Les projets que l’on compile avec l’environnement CMake peuvent facilement être incorporés à Yocto, car il existe une classe cmake prenant en charge ce type de production. Je crée le répertoire et la recette suivante :

[build-qemu]$ mkdir ../meta-my-own-layer/recipes-custom/hello-cmake
[build-qemu]$ nano  ../meta-my-own-layer/recipes-custom/hello-cmake/hello-cmake_1.0.bb
DESCRIPTION = "A simple hello world application built with cmake."
SECTION = "Custom"

LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"

SRC_URI="https://www.logilin.fr/files/yocto-lab/${PN}-${PV}.tar.bz2"
SRC_URI[md5sum] = "4b14d7f3080ae933f0791f2cc1f987c5"

S = "${WORKDIR}/${PN}"

inherit cmake

La principale différence (hormis la description et la somme de contrôle du package) est la dernière ligne. Bien sûr, on ajoute dans le fichier d’image la ligne suivante :

IMAGE_INSTALL += "hello-cmake"

Et après compilation et boot, on observe :

Poky (Yocto Project Reference Distro) 2.7 mybox ttyAMA0
mybox login: root
Password: (linux)
root@mybox:~# hello-cmake 
Hello from mybox (built with CMake)
root@mybox:~# 

Recette pour projet avec Makefile personnalisé

Il arrive fréquemment qu’un projet dispose d’un Makefile spécifique, directement livré avec les sources, sans passer par la phase de configuration des Autotools ou de CMake.

Recette pour compilation sans Makefile

Finalement, les recettes les plus complexes sont celles qui doivent compiler des packages ne comportant aucun Makefile (ou un Makefile mal fichu, qui ne permet pas la cross-compilation). Pour nous placer dans la situation la plus défavorable, imaginons un projet ne comportant qu’un fichier source à télécharger depuis un site web.

Je crée un répertoire hello-simple dans mon layer, et j’ajoute la recette hello-simple_1.0.bb suivante, dans laquelle la compilation est explicitement réalisée par le script do_install().

DESCRIPTION = "A simple hello world application built without Makefile."
SECTION = "Custom"

LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"

SRC_URI="https://www.logilin.fr/files/yocto-lab/${PN}.c"
SRC_URI[md5sum] = "ac02346e365c2030fd9acee21023028a"

S = "${WORKDIR}/"

TARGET_CFLAGS += " -DNDEBUG -DMY_OPTION"

do_compile() {
         ${CC} ${CFLAGS} ${LDFLAGS} ${S}/${PN}.c -o ${WORKDIR}/${PN}
 }

do_install() {
         install -m 0755 -d ${D}${bindir}
         install -m 0755 ${WORKDIR}/${PN} ${D}${bindir}
 }

Comme on le voit, la fonction do_compile fait directement appel au compilateur C, avec les options nécessaires pour la compilation et l’édition des liens. La variable CFLAGS est automatiquement renseignée avec le contenu de la variable TARGET_CFLAGS pendant la cross-compilation pour la cible. Nous y avons ajouté deux options qui définissent des constantes symboliques : NDEBUG qui, par convention, indique que le code n’est plus en mode “débogage” et MY_OPTION qui nous permet de vérifier le comportement en affichant un message spécifique. Le code source du programme a été légèrement modifié pour appeler fprintf() en fonction de la présence de ces options. Bien entendu, pour des projets réels, on est amené à définir des options plus complètes dans TARGET_CFLAGS, et éventuellement TARGET_LDFLAGS.

// hello-simple.c
[...]
int main(void)
 {
    char hostname[MAXHOSTNAMELEN];
    gethostname(hostname, MAXHOSTNAMELEN);
    hostname[MAXHOSTNAMELEN - 1] = '\0';
    fprintf(stdout, "Simple hello from %s (built without Makefile)\n", hostname);
#ifndef NDEBUG
    fprintf(stdout,"  [DEBUG MODE]\n");
#endif
#ifdef MY_OPTION
    fprintf(stdout, "  [MY OPTION]\n");
#endif
    return EXIT_SUCCESS;
 }

La recette ci-dessus ne fait pas référence au nom du fichier source, elle utilise seulement le nom du package à travers la variable ${PN}, elle pourrait donc être adaptée facilement (à la somme de contrôle MD5 près) pour n’importe quel fichier à compiler de cette manière. Après compilation, nous pouvons vérifier que les deux options ont bien été passées au compilateur. Le premier message ne s’affiche que si l’option n’est pas définie, il est donc normal qu’il ne soit pas présent ici.

Poky (Yocto Project Reference Distro) 2.7 mybox ttyAMA0
mybox login: root
Password: (linux)
root@mybox:~# hello-simple 
Simple hello from mybox (built without Makefile)
  [MY OPTION]
root@mybox:~# 

Conclusion

Nous avons vu dans cette séquence différentes manières d’intégrer dans le build de Yocto des applications externes, qu’il s’agisse de projets développés spécifiquement ou des utilitaires libres glanés sur Internet (dans ce cas, il est toutefois préférable de s’assurer que la recette ne soit pas déjà disponible quelque part). Cette intégration de code personnalisé dans l’image produite par Yocto est généralement réalisée en fin de projet, car il est plus simple pendant la phase de mise au point de réaliser la compilation indépendamment du BSP, comme nous l’avons vu dans la séquence précédente.

Ainsi s’achève la troisième partie de ce cours en ligne, après le développement du code métier, nous allons nous intéresser à l’ajustement du BSP à une cible spécifique.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *