
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 :
- Performances pendant le build
- Erreurs et incompatibilités de recettes
- Spécificités du build
- Toolchain et SDK
- Support matériel
- Image binaire et partitionnement
- Distro, choix et fonctionnalités
- Image et fonctionnalités d’image
- 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.confn’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.conffournit 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.confoulocal.conf) : nombre de jobs simultanés lancés parbitbakependant le build. Par défautbitbakelance 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.confoulocal.conf) : lors des étapesdo_compile(),bitbakeappelle la commandemakeavec 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 n² 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 à limiterPARALLEL_MAKEsi on a beaucoup de cœurs de CPU et une quantité de RAM pas très élevée.
BB_NUMBER_PARSE_THREADS(site.confoulocal.conf) : avant de commencer les compilations,bitbakepasse 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_LEVELetBB_TASK_IONICE_LEVEL(site.confoulocal.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 entre0(par défaut) et+19. Pour ionice l’intervalle est de0(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_IOetBB_PRESSURE_MAX_MEMORY(site.confoulocal.conf) : le noyau Linux fournit dans ses fichiers/proc/pressure/cpu,/proc/pressure/ioet/proc/pressure/memoryune 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à desquelsbitbakecesse 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.confoulocal.conf) : cette variable contient le chemin où les fichiers sources des packages sont stockés après téléchargement – étapedo_fetch()– et avant décompression – étapedo_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.confoulocal.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.
PREMIRRORSetMIRRORS(site.confoulocal.conf) : contiennent des chemins de recherche supplémentaires pour les packages sources. Dans l’ordrebitbakeconsulte :- le chemin mentionné dans
DL_DIR, - les emplacements dans
PREMIRRORS, - les URL indiquées dans
SRC_URI, - les emplacements indiqués dans
MIRRORS.
- le chemin mentionné dans
SSTATE_MIRRORS(site.confetlocal.conf) joue pour le shared state cache le même rôle queMIRRORS. 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.confetlocal.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.confetlocal.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.confetlocal.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.bbappendest trouvé lors du parsing initial des recettes, mais qu’il ne s’applique sur aucun fichier.bbprésent,bitbakedoit 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.bbappendd’un projet précédent, qui ne s’appliquent pas sur les recettes des layers actuellement présents.ALLOW_EMPTY:<recipe-name> (local.confou<recipe-name>.bb) en mettant cette variable à « 1 » on demande àbitbakede 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_DIRSetBB_DISKMON_WARNINTERVAL(site.confoulocal.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,STOPTASKSouHALT), le répertoire concerné par le monitoring (notamment${TMPDIR}qui est la base de l’arborescence des fichiers de sortie debitbake), la place libre minimale et éventuellement le nombre minimum d’i-nodes disponibles suffixés par les multiplicateursK,MouG.
Filtrage des recettes
BBMASK(local.conf) décrit une liste de recettes dontbitbakene doit pas tenir compte. C’est comme si l’on supprimait les fichiers.bbet.bbappendcorrespondant (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 listeRRECOMMENDSd’une autre recette. Si une recette est explicitement indiquée dansIMAGE_INSTALLou dans uneRDEPENDS, elle sera installée normalement même si elle est indiquée dans cette variable.SKIP_RECIPE(local.confou${DISTRO}.conf) : table de recettes à ne pas compiler accompagnées des raisons justifiant ce choix. Le format estSKIP_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*etAGPL-3.0*.INCOMPATIBLE_LICENSE_EXCEPTIONS(local.conf) : liste de couples package:licence à installer même si la licence est dansINCOMPATIBLE_LICENSE. Surtout utilisé pendant la phase de mise au point avec des outils de développement ou de débogage (nano:GPL-3.0-onlyetgdbserver:GPL-3.0-onlypar 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) : contientpackage_rpm,package_deboupackage_ipksuivant 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 dansconf/bblayers.conf(le premier fichier parcouru parbitbake). On la manipule avec la commandebitbake-layers.- OE_TERMINAL (
site.confoulocal.conf) : cette variable indique quel type de terminalbitbakedoit invoquer lorsqu’on effectue des opérations commemenuconfigoudevshell. Il est parfois nécessaire de modifier la valeur quand on est connecté à distance (par SSH) à la machine de build pour indiquerscreenpar exemple. EXTERNALSRC:pn-<recipe-name>(avecINHERIT += "externalsrc"danslocal.conf) ouEXTERNALSRC(avecinherit externalsrcdans<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 commandedevtool 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_sdkdebitbake) est compilé. Par défautSDKMACHINE(machine sur laquelle on utilisera le SDK) est égale àBUILD_ARCH(machine sur laquelle on compile le SDK). La valeur la plus courante estx86_64. SiSDKMACHINEetBUILD_ARCHsont différentes on parle d’une situation de « cross canadian toolchain » .SDK_VENDOR(${SDKMACHINE}.confoulocal.conf) : les outils de compilation du SDK seront nommés avec le schéma${TARGET_ARCH}-${SDK_VENDOR}-${TARGET_OS}-<toolname>, par exemplearm-poky-linux-gnueabi-gcc. Par défaut la valeur estpoky.TARGET_ARCHetTUNE_ARCH(${MACHINE}.conf) l’architecture de la cible (arm,x86_64,riscv, etc.)TARGET_OS(${SDKMACHINE}.confoulocal.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 fichierlocal.conflu,bitbakerecherche un fichier${MACHINE}.confen parcourant – par ordre de priorité croissante – les sous-répertoiresconf/machine/des layers indiqués dans${BBLAYERS}.MACHINEOVERRIDES(local.confou${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.confou${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) danslocal.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}.confoulocal.conf) : le choix de la recette à utiliser pour compiler, le noyau Linux, le bootloader, la bibliothèque graphique, etc.PREFERRED_VERSION_<package>(${MACHINE}.confoulocal.conf) : le numéro de version choisi pour la recette<package>indiquée dans unPREFERRED_PROVIDER_virtual/ci-dessus.SERIAL_CONSOLES(${MACHINE}.confoulocal.conf) : liste des consoles séries sur lesquelles démarrer une terminalgetty.KERNEL_MODULE_AUTOLOAD(${MACHINE}.confoulocal.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_FILEouWKS_FILES(${MACHINE}.confoulocal.conf) : nom du fichier de description du partitionnement de l’image finale. Ce fichier est recherché dans les sous-répertoireswic/des différents layers. La variableWKS_FILEScontient 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}.confoulocal.conf) contient la liste des formats de fichiers de sortie attendus (généralementtar.xzetwic). La liste complète des formats disponibles se trouve ici : https://docs.yoctoproject.org/dev/singleindex.html#term-IMAGE_TYPES.IMAGE_BOOT_FILES(${MACHINE}.confoulocal.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}.confoulocal.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}.confse trouvant dans un sous-répertoireconf/distro/d’un layer. Par défautDISTROvaut «poky» et le fichier de description estpoky/meta-poky/conf/distro/poky.conf.DISTRO(${DISTRO}.conf) : dans le fichier de configuration, la variableDISTROcontient 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}.confoulocal.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}.confoulocal.conf) : choix du mécanisme d’initialisation après le boot du kernel. Par défautsysvinit, peut être remplacé parsystemdoumdev-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 globaleOVERRIDES. 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 desOVERRIDES.TCLIBC(${DISTRO}.confoulocal.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’estglibc, mais on peut préférermusl,newliboubaremetal.
–
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épertoirerecipes-*/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}.bbavec la clauseinherit extrausers, ou danslocal.confavec la ligneINHERIT += "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 fichierlayer.confparcouru é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 queBBLAYERScontient 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 danslayer.conf, c’est souvent le nom qui suit le préfixemeta-du répertoire l’abritant.BBFILE_PRIORITY_layer-id(layer.conf) : la priorité du layer dont l’identifiant estlayer-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 layerworkspacededevtool, 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.
–