Les variables principales de Bitbake – 1 – Les variables globales

Publié par cpb
Sep 17 2024
Variables de Bitbake

Lorsqu’on effectue un build pour Yocto Project, l’outil bitbake parcourt des fichiers de configuration que nous avons pu examiner dans l’article précédent. Pendant ce parcours, un nombre important de variables sont remplies.

Il est facile de retrouver dans la documentation de Yocto Project la signification d’une variable, mais l’opération inverse n’est pas toujours facile : trouver quelle variable remplir pour répondre à un problème donné.

C’est la question à laquelle j’ai essayé de répondre dans cette série d’articles, en commençant par les variables globales, dont le contenu est disponible durant tout le build. Le prochain article traitera des variables définies dans les contextes de recette.

Sommaire

J’ai limité ma liste aux variables les plus courantes. J’ai pris comme référence celles que je me souviens avoir configuré à plusieurs reprises durant les derniers mois.

J’ai classé arbitrairement les variables en fonction des usages suivants :

  1. Performances pendant le build
  2. Erreurs et incompatibilités de recettes
  3. Spécificités du build
  4. Toolchain et SDK
  5. Support matériel
  6. Image binaire et partitionnement
  7. Distro, choix et fonctionnalités
  8. Image et fonctionnalités d’image
  9. Caractéristiques des layers

La plupart des variables globales de Yocto peuvent être renseignées indifféremment dans plusieurs fichiers. J’ai indiqué entre parenthèses les fichiers dans lesquels leurs configurations me semblaient avoir le plus de sens. Quand je mentionne « site.conf ou local.conf » la variable peut éventuellement être définie dans les deux fichiers, l’un ayant précédence sur l’autre par le jeu des opérateurs = et ?=.

Petit rappel de l’article précédent concernant les fichiers ${BUILDDIR}/conf/site.conf et ${BUILDDIR}/conf/local.conf que nous rencontrerons dans la description de nombreuses variables :

  • site.conf n’existe pas par défaut, c’est à nous de le créer. Il est lu en premier et sert à configurer des éléments concernant la machine sur laquelle on fait le build. Il est propre au développeur et à son poste de travail.
  • local.conf fournit les informations principales sur le build à réaliser. Contrairement à site.conf, ce fichier est habituellement partagé entre les développeurs qui souhaitent reproduire le build sur leurs différentes machines.



1 – Performances pendant le build

Limitation de la consommation de ressources

Durant la production d’un build, bitbake est assez gourmand en ressources. Si l’ordinateur utilisé pour cette production est utilisé simultanément pour d’autres tâches (développement, visioconférence, navigation web, lecture de vidéos, etc.) il peut être utile de limiter la charge CPU par exemple de bitbake.

  • BB_NUMBER_THREADS (site.conf ou local.conf) : nombre de jobs simultanés lancés par bitbake pendant le build. Par défaut bitbake lance simultanément autant de jobs — do_fetch(), do_unpack(), do_configure(), do_compile(), do_install(), do_package(), etc — qu’il y a de cœurs de CPU disponibles. Diminuer un peu cette valeur pour garder quelques cœurs en réserve peut être souhaitable pour conserver une certaine fluidité du système.
  • PARALLEL_MAKE (site.conf ou local.conf) : lors des étapes do_compile(), bitbake appelle la commande make avec l’option -j <n> pour lui indiquer de paralléliser la compilation, n étant égal au nombre de cœurs de CPU. Ceci signifie qu’on risque de se retrouver avec n jobs de compilation (si on n’a pas modifié BB_NUMBER_THREADS), chacun lançant n tâches. Soit compilations simultanées. Outre le ralentissement du système, le risque est alors le manque de mémoire et l’échec du build. Ne pas hésiter à limiter PARALLEL_MAKE si on a beaucoup de cœurs de CPU et une quantité de RAM pas très élevée.
  • BB_NUMBER_PARSE_THREADS (site.conf ou local.conf) : avant de commencer les compilations, bitbake passe du temps à parcourir et charger en mémoire tous les fichiers de configuration que nous avons vus dans l’article précédent, toutes les recettes, tous les fichiers .bbappend, etc. Cette étape est également assez gourmande en ressources, et il peut être intéressant de réduire un peu le nombre de threads actifs (donc la charge CPU et les accès disques simultanés).

Les tâches lancées par bitbake étant en concurrence avec les autres tâches du système, on peut aussi jouer sur leurs priorités :

  • BB_TASK_NICE_LEVEL et BB_TASK_IONICE_LEVEL (site.conf ou local.conf) : Les valeurs de nice et d’ionice correspondent à des niveaux de priorités inversés respectivement pour l’accès au CPU et pour les accès au système de fichier. Plus la valeur est basse, plus la priorité est élevée. Les valeurs de nice évoluent entre 0 (par défaut) et +19. Pour ionice l’intervalle est de 0 (défaut) à 7 ; je n’ai toutefois jamais remarqué d’effet sensible pour ce dernier paramètre.

Lorsqu’on souhaite limiter l’impact du build sur le système hôte, il est possible de jouer aussi sur d’autres paramètres, de niveaux plus élevés :

  • BB_PRESSURE_MAX_CPU, BB_PRESSURE_MAX_IO et BB_PRESSURE_MAX_MEMORY (site.conf ou local.conf) : le noyau Linux fournit dans ses fichiers /proc/pressure/cpu, /proc/pressure/io et /proc/pressure/memory une appréciation de la charge moyenne qu’il a subi durant les 10 dernières secondes, la dernière minute et les 5 dernières minutes. On peut indiquer dans ces variables, les seuils au-delà desquels bitbake cesse temporairement de lancer de nouvelles tâches. Les valeurs sont dans l’intervalle 0 – 1.000.000 mais il n’est pas simple d’estimer leurs niveaux de charge effective. À titre d’exemple voici les trois valeurs pendant un build Yocto :
[~]$ cat  /proc/pressure/cpu 
some avg10=80.54 avg60=70.09 avg300=70.38 total=677633725
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

[~]$ cat  /proc/pressure/io 
some avg10=0.00 avg60=0.00 avg300=0.28 total=31380922
full avg10=0.00 avg60=0.00 avg300=0.12 total=24911970

[~]$ cat  /proc/pressure/memory 
some avg10=0.00 avg60=0.00 avg300=0.00 total=251014
full avg10=0.00 avg60=0.00 avg300=0.00 total=215441

Pour en savoir plus, voir l’article « Pressure Stall Information » dans la documentation du kernel.

Accélération du build

À l’inverse de la problématique précédente, on peut vouloir accélérer autant que possible le build pour attendre moins longtemps la disponibilité de l’image produite. Pour cela, un moyen très efficace est de partager entre les différents builds que l’on peut réaliser sur notre système le maximum de résultats intermédiaires. Nous pouvons jouer facilement sur l’emplacement de deux répertoires :

  • DL_DIR (site.conf ou local.conf) : cette variable contient le chemin où les fichiers sources des packages sont stockés après téléchargement – étape do_fetch() – et avant décompression – étape do_unpack(). Les noms des fichiers incluant bien les numéros de version voire les niveaux de révision, il est tout à fait possible de partager ce répertoire entre différents builds pour accélérer sensiblement le téléchargement des packages sources.
  • SSTATE_DIR (site.conf ou local.conf) : le répertoire shared state cache contient des fichiers intermédiaires de la compilation (par exemple fichiers objets ou exécutables pas encore installés). Le partage est également possible entre différents builds, ce qui permet d’éviter de répéter plusieurs fois les mêmes opérations.

À titre d’exemple, pour mes formations « Linux embarqué avec Yocto Project » et « Yocto Project avancé« , je réalise un build complet la veille de la session (ce qui dure plusieurs heures), je sauvegarde les répertoires dowloads/ et sstate-cache/ et j’efface toute le reste. Puis le jour de la formation je les copie sur les répertoires de travail des participants, ce qui fait qu’après configuration correcte (en jouant sur DL_DIR et SSTATE_CACHE) notre premier build dure 5 à 10 minutes au lieu de plusieurs heures.

Une autre solution pour accélérer le build est de partager ces répertoires entre plusieurs machines du même sous-réseau.

  • PREMIRRORS et MIRRORS (site.conf ou local.conf) : contiennent des chemins de recherche supplémentaires pour les packages sources. Dans l’ordre bitbake consulte :
    • le chemin mentionné dans DL_DIR,
    • les emplacements dans PREMIRRORS,
    • les URL indiquées dans SRC_URI,
    • les emplacements indiqués dans MIRRORS.
  • SSTATE_MIRRORS (site.conf et local.conf) joue pour le shared state cache le même rôle que MIRRORS. Cette mise en œuvre est un petit peu plus compliquée car différentes machines peuvent utiliser différentes versions de Yocto Project, et différentes versions du compilateur ou de la LibC.
  • BB_NO_NETWORK (site.conf et local.conf) interdit l’usage du réseau pour télécharger les sources. Cette approche est un peu drastique, on lui préfère souvent l’option suivante :
  • BB_ALLOWED_NETWORKS (site.conf et local.conf) contient la liste des réseaux autorisés. C’est un moyen efficace de forcer l’utilisation d’un miroir par exemple.

Une dernière approche – beaucoup plus limitée dans ses effets – est de réduire la quantité de compilations nécessaires :

  • ASSUME_PROVIDED (site.conf et local.conf) contient une liste de packages qu’il n’est pas nécessaire de recompiler et qu’on peut considérer comme déjà présents sur la machine hôte. Cela représente surtout des outils du SDK et influe donc sur le temps de la première compilation.



2 – Erreurs et incompatibilités de recettes

Déclenchement des erreurs

  • BB_DANGLINGAPPENDS_WARNONLY (local.conf) est une variable que je mets souvent à « 1 » durant mes builds. Elle indique que si un fichier .bbappend est trouvé lors du parsing initial des recettes, mais qu’il ne s’applique sur aucun fichier .bb présent, bitbake doit simplement afficher un avertissement et non déclencher une erreur de compilation. C’est une situation courante, du moins pendant la phase de mise au point où l’on hérite de fichiers .bbappend d’un projet précédent, qui ne s’appliquent pas sur les recettes des layers actuellement présents.
  • ALLOW_EMPTY:<recipe-name> (local.conf ou <recipe-name>.bb) en mettant cette variable à « 1 » on demande à bitbake de créer un package vide même si la recette ne produit pas de fichiers. C’est un moyen d’éviter des erreurs si une recette (hors de notre contrôle) a une dépendance runtime vers <recipe-name>.
  • BB_DISKMON_DIRS et BB_DISKMON_WARNINTERVAL (site.conf ou local.conf) : cette variable contient une liste de comportements à adopter quand la place disponible sur un disque de stockage diminue. Un comportement est une suite de trois ou quatre éléments séparés par des virgules : le type d’action à effectuer (par ordre croissant de criticité : WARN, STOPTASKS ou HALT), le répertoire concerné par le monitoring (notamment ${TMPDIR} qui est la base de l’arborescence des fichiers de sortie de bitbake), la place libre minimale et éventuellement le nombre minimum d’i-nodes disponibles suffixés par les multiplicateurs K, M ou G.

Filtrage des recettes

  • BBMASK (local.conf) décrit une liste de recettes dont bitbake ne doit pas tenir compte. C’est comme si l’on supprimait les fichiers .bb et .bbappend correspondant (alors qu’ils sont bien présents dans un layer qu’on a téléchargé).
  • BAD_RECOMMENDATIONS (local.conf) : liste de recettes à ne pas installer sur la cible si elles sont seulement mentionnées dans la liste RRECOMMENDS d’une autre recette. Si une recette est explicitement indiquée dans IMAGE_INSTALL ou dans une RDEPENDS, elle sera installée normalement même si elle est indiquée dans cette variable.
  • SKIP_RECIPE (local.conf ou ${DISTRO}.conf) : table de recettes à ne pas compiler accompagnées des raisons justifiant ce choix. Le format est SKIP_RECIPE[<recipe-name>]="<reason>".
  • INCOMPATIBLE_LICENSE (local.conf) : liste de noms de licences incompatibles avec le build que nous souhaitons réaliser. Il s’agit souvent d’exclure les packages sous licence GPLv3 et dérivées quand on prépare un système doté de fonctionnalités de type secure boot où l’utilisateur ne peut pas remplacer les packages par des versions modifiées, même s’il a bien accès aux sources. Les licences concernées sont généralement : GPL-3.0*, LGPL-3.0* et AGPL-3.0*.
  • INCOMPATIBLE_LICENSE_EXCEPTIONS (local.conf) : liste de couples package:licence à installer même si la licence est dans INCOMPATIBLE_LICENSE. Surtout utilisé pendant la phase de mise au point avec des outils de développement ou de débogage (nano:GPL-3.0-only et gdbserver:GPL-3.0-only par exemple)
  • LICENSE_FLAGS_ACCEPTED (local.conf) : liste de licences spécifiques (généralement propriétaires) qu’il faut accepter explicitement pour pouvoir compiler les recettes du projet.



3- Spécificités du build

Les variables rentrant dans cette catégorie sont un peu disparates. Il s’agit de paramétrer le comportement du build.

  • BUILDNAME (local.conf) le contenu de cette variable est intégré dans les noms des fichiers produits en fin de compilation. Par défaut c’est le time stamp (horodatage) du début du build.
  • PACKAGE_CLASSES (local.conf) : contient package_rpm, package_deb ou package_ipk suivant le format désiré pour stocker les paquets binaires avant leur installation sur l’image finale.
  • BBLAYERS (bblayers.conf) la liste des emplacements des layers à parcourir pour rechercher les recettes disponibles. Cette variable est stockée normalement dans conf/bblayers.conf (le premier fichier parcouru par bitbake). On la manipule avec la commande bitbake-layers.
  • OE_TERMINAL (site.conf ou local.conf) : cette variable indique quel type de terminal bitbake doit invoquer lorsqu’on effectue des opérations comme menuconfig ou devshell. Il est parfois nécessaire de modifier la valeur quand on est connecté à distance (par SSH) à la machine de build pour indiquer screen par exemple.
  • EXTERNALSRC:pn-<recipe-name> (avec INHERIT += "externalsrc" dans local.conf) ou EXTERNALSRC (avec inherit externalsrc dans <recipe-name>.bb) : permet de préciser le chemin local des sources à utiliser pour compiler le package sans les télécharger. Surtout utilisé par l’intermédiaire de la commande devtool modify <package> pour préparer un patch sur le package.



4 – Toolchain et SDK

  • SDKMACHINE (local.conf) : cette variable contient le type de machine pour laquelle le SDK (que l’on extrait avec l’option -c populate_sdk de bitbake) est compilé. Par défaut SDKMACHINE (machine sur laquelle on utilisera le SDK) est égale à BUILD_ARCH (machine sur laquelle on compile le SDK). La valeur la plus courante est x86_64. Si SDKMACHINE et BUILD_ARCH sont différentes on parle d’une situation de « cross canadian toolchain » .
  • SDK_VENDOR (${SDKMACHINE}.conf ou local.conf) : les outils de compilation du SDK seront nommés avec le schéma ${TARGET_ARCH}-${SDK_VENDOR}-${TARGET_OS}-<toolname>, par exemple arm-poky-linux-gnueabi-gcc. Par défaut la valeur est poky.
  • TARGET_ARCH et TUNE_ARCH (${MACHINE}.conf) l’architecture de la cible (arm, x86_64, riscv, etc.)
  • TARGET_OS (${SDKMACHINE}.conf ou local.conf) : contient le nom de l’OS de la cible : linux, linux-gnueabi, linux-musl, linux-musleabi.



5 – Support matériel

  • MACHINE (local.conf) : cette variable contient le nom de la plateforme matérielle supportant le système. Une fois le fichier local.conf lu, bitbake recherche un fichier ${MACHINE}.conf en parcourant – par ordre de priorité croissante – les sous-répertoires conf/machine/ des layers indiqués dans ${BBLAYERS}.
  • MACHINEOVERRIDES (local.conf ou ${MACHINE}.conf) : liste d’overrides correspondant à la machine sélectionnée. Par défaut il s’agit simplement du contenu de ${MACHINE} toutefois il est possible de l’étendre pour s’assurer qu’un override est bien présent dans la liste ${COMPATIBLE_MACHINE} d’une recette (généralement celle du kernel).
  • MACHINE_FEATURES (local.conf ou ${MACHINE}.conf) : liste des fonctionnalités hardware supportées par la cible. Cette liste est normalement renseignée dans la description de la cible et amendée (en supprimant des fonctionnalités) dans local.conf. La liste des fonctionnalités supportées par Yocto Project est décrite ici : https://docs.yoctoproject.org/dev/singleindex.html#ref-features-machine.
  • PREFERRED_PROVIDER_virtual/kernel, PREFERRED_PROVIDER_virtual/bootloader , PREFERRED_PROVIDER_virtual/egl, etc. (${MACHINE}.conf ou local.conf) : le choix de la recette à utiliser pour compiler, le noyau Linux, le bootloader, la bibliothèque graphique, etc.
  • PREFERRED_VERSION_<package> (${MACHINE}.conf ou local.conf) : le numéro de version choisi pour la recette <package> indiquée dans un PREFERRED_PROVIDER_virtual/ ci-dessus.
  • SERIAL_CONSOLES (${MACHINE}.conf ou local.conf) : liste des consoles séries sur lesquelles démarrer une terminal getty.
  • KERNEL_MODULE_AUTOLOAD (${MACHINE}.conf ou local.conf) : liste de modules noyau à charger automatiquement au boot.

D’autres options de configuration du support matériel sont présentes dans les recettes du kernel et du bootloader que nous verrons dans le prochain article.



6 – Image binaire et partitionnement

Le terme « image » fait ici référence au fichier-image binaire obtenu à la fin de build, et que l’on copie sur le support de stockage de la cible.

  • WKS_FILE ou WKS_FILES (${MACHINE}.conf ou local.conf) : nom du fichier de description du partitionnement de l’image finale. Ce fichier est recherché dans les sous-répertoires wic/ des différents layers. La variable WKS_FILES contient une liste de fichiers .wks, seul le premier trouvé en parcourant les layers par ordre croissant de priorité est pris en considération.
  • IMAGE_NAME (local.conf) : nom du fichier d’image binaire. Par défaut il s’agit d’une séquence « ${IMAGE_BASENAME}${IMAGE_MACHINE_SUFFIX}${IMAGE_VERSION_SUFFIX} » mais on peut être amené à modifier ce nom, surtout lorsque l’image est ensuite copiée automatiquement (via des scripts) sur la cible de test.
  • IMAGE_FSTYPES (${MACHINE}.conf ou local.conf) contient la liste des formats de fichiers de sortie attendus (généralement tar.xz et wic). La liste complète des formats disponibles se trouve ici : https://docs.yoctoproject.org/dev/singleindex.html#term-IMAGE_TYPES.
  • IMAGE_BOOT_FILES (${MACHINE}.conf ou local.conf) : liste des fichiers à installer sur la partition de boot. Les fichiers sont recherchés dans le répertoire ${DEPLOY_DIR_IMAGE}. En général ce sont les fichiers du bootloader et éventuellement le kernel et le device tree.
  • IMAGE_ROOTFS_EXTRA_SPACE (${MACHINE}.conf ou local.conf) : espace mémoire supplémentaire à ajouter dans l’image binaire une fois copié le rootfs. L’unité utilisé est le kilo-octet.



7 – Distro, choix et fonctionnalités

Une distro est un ensemble de paramètres de configuration qui sélectionnent des packages et les configurent pour répondre à certains besoins.

  • DISTRO (local.conf) : contient le nom de la distro utilisé pour le build. Ce nom doit correspondre à un fichier ${DISTRO}.conf se trouvant dans un sous-répertoire conf/distro/ d’un layer. Par défaut DISTRO vaut « poky » et le fichier de description est poky/meta-poky/conf/distro/poky.conf.
  • DISTRO (${DISTRO}.conf) : dans le fichier de configuration, la variable DISTRO contient le nom cours de la distribution, par exemple « poky« 
  • DISTRO_NAME (${DISTRO}.conf) : nom complet de la distribution, par exemple « Poky (Yocto Project Reference Distro) »
  • DISTRO_VERSION (${DISTRO}.conf) : numéro de version de la distribution.
  • DISTRO_FEATURES (${DISTRO}.conf ou local.conf ) : liste de fonctionnalités de haut-niveau proposées par la distribution. Une recette peut adopter certains comportement en fonction de la présence ou de l’absence d’une fonctionnalité dans cette liste.
  • INIT_MANAGER (${DISTRO}.conf ou local.conf) : choix du mécanisme d’initialisation après le boot du kernel. Par défaut sysvinit, peut être remplacé par systemd ou mdev-busybox,
  • REQUIRED_DISTRO_FEATURES, ANY_OF_DISTRO_FEATURES, CONFLICT_DISTRO_FEATURES : ces variables sont utilisées dans le contexte d’une recette. Nous les verrons dans le prochain article.
  • DISTROOVERRIDES (${DISTRO}.conf) : liste (dont le séparateur est le deux-points « : » ) des overrides définis par la distribution. Le contenu de cette variable est ajouté à la variable globale OVERRIDES. En fin de parsing des recettes, une variable « foo » sera remplacée par le contenu de la variable « foo:bar » si la chaîne « bar » est dans la liste des OVERRIDES.
  • TCLIBC (${DISTRO}.conf ou local.conf) : choix de la bibliothèque C (utilisée par tous les processus de l’espace utilisateur pour invoquer des appels-système), par défaut c’est glibc, mais on peut préférer musl, newlib ou baremetal.



8 – Image et fonctionnalités d’image

La notion d’image correspond ici à la sélection des packages et au paramétrage que l’on retrouvera dans l’arborescence du root filesystem, et donc dans le fichier d’image binaire tel que nous l’avons vu au paragraphe 6.

  • IMAGE_BASENAME : définie automatiquement à partir du nom de la recette d’image qui doit se trouver dans un sous-répertoire recipes-*/images/ d’un layer.
  • IMAGE_INSTALL (${IMAGE_BASENAME}.bb, local.conf) : liste des packages et des groupes de packages à installer sur la cible. Cette variable doit être configurée en utilisant « :append » et non pas "+= » pour des raisons de définition de contenu par défaut.
  • IMAGE_FEATURES (${IMAGE_BASENAME}.bb) : fonctionnalités de haut-niveau permettant d’installer et configurer de multiples packages. On trouve une liste des fonctionnalités disponibles ici : https://docs.yoctoproject.org/dev/singleindex.html#ref-features-image.
  • EXTRA_IMAGE_FEATURES (local.conf) : liste de fonctionnalités complémentaires à ajouter à IMAGE_FEATURES.
  • EXTRA_USERS_PARAMS (dans ${IMAGE_BASENAME}.bb avec la clause inherit extrausers, ou dans local.conf avec la ligne INHERIT += "extrausers") : liste (dont le séparateur est le point-virgule) de commandes pour ajouter (useraddd, groupadd), supprimer (userdel, groupdel), ou modifier (usermod, groupmod) des utilisateurs ou des groupes d’utilisateurs.



9 – Caractéristiques des layers

Les variables mentionnées ici sont renseignées dans les fichiers conf/layer.conf de chaque layer. Les layers sont listés dans la variable BBLAYERS de conf/bblayers.conf.

  • BBFILES (layer.conf) : liste de motifs du shell listant tous les fichiers de recette (*.bb) et d’extension (*.bbappend) à charger. Chaque fichier layer.conf parcouru étend cette liste globale.
  • BBPATH (layer.conf) : emplacements des différents layers listés sous forme de path (le séparateur est un deux-points) alors que BBLAYERS contient une liste dont le séparateur est une espace.
  • BBFILE_COLLECTIONS (layer.conf) : liste des layers représentés par des identifiants uniques. L’identifiant d’un layer est fourni dans layer.conf, c’est souvent le nom qui suit le préfixe meta- du répertoire l’abritant.
  • BBFILE_PRIORITY_layer-id (layer.conf) : la priorité du layer dont l’identifiant est layer-id. Les layers sont parcourus par ordre de priorité croissante. Il est conseillé d’utiliser une priorité inférieure à 99, car c’est celle utilisé pour le layer workspace de devtool, employé pendant la mise au point du système.
  • LAYERSERIES_COMPAT_layer-id (layer.conf) : liste des versions (code name) de Poky avec laquelle le layer est compatible.



Conclusion

Nous avons vu ici une petite partie des variables globales utilisées par bitbake. Ce sont celles qu’on utilise le plus couramment.
Dans le prochain article, nous examinerons les variables spécifiques aux contextes des recettes.

Pour en savoir plus et mettre en pratique, n’hésitez à participer à une session de formation « Linux embarqué avec Yocto Project » ou « Yocto Project avancé » que j’anime chez Logilin.

URL de trackback pour cette page