Layers
In Yocto i recipe si occupano della gestione di un singolo applicativo o funzionalità, mentre i layer sono semplicemente dei raccoglitori di molteplici recipe. L’idea alla base di un layer Yocto è che questo deve rendere praticamente “plug and play” l’aggiunta di funzionalità molto complesse ad un generico sistema. Una buona prassi infatti è quella di costruire un progetto basandosi su almeno 3 layer distinti:
- hardware specifico
- funzionalità comuni
- applicativi specifici
Questo con l’obiettivo di modularizzare il progetto e permettere il riuso di un layer in progetti diversi, senza incappare in problematiche di conflitti tra recipe.
In Yocto queste sono proprio le 3 tipologie di layer:
- BSP
- Distro
- Application
Un singolo layer può mescolare molteplici tipologie, ma appunto non è una buona prassi.
BSP
BSP è l’ acronimo di Board Support Package
(documentazione ufficiale).
L’obiettivo di questo layer è di occuparsi
di tutte le magagne associate ad una determinata
scheda o architettura.
Ad esempio esistono BSP layer per:
- l’intera famiglia di
SoCa microprocessore prodotti daSTM(meta-st-stm32mp) - la famiglia delle schede
raspberrypi(meta-raspberrypi) - tutti i processori basati su architettura
ARM(meta-arm) - le schede
Intel AlteraconFPGA(meta-intelfpga) e molti molti altri.
Per supportare una determinata scheda è normale il dovere utilizzare molteplici layer BSP in “sequenza”. Se molteplici schede utilizzano processori ARM, ha senso che le funzionalità generiche di un processore ARM siano racchiuse in proprio layer, mentre le cose più specifiche ad una scheda o processore risiedano in un layer aggiuntivo. Questa è la filosofia di Yocto e, più in generale, di un buon progetto software.
Distro
Distro è associato all’ idea di distribuzione Linux,
ovvero una raccolta di strumenti e funzionalità software
che ci si aspetta di trovare in un determinato ambiente Linux
(documentazione ufficiale).
Ad esempio
in una distribuzione
Debianci aspettiamo di trovare ilpackage manageraptin una distribuzione desktop ci aspettiamo di trovare un
display servercomeWaylandoXin una qualsiasi distribuzione ci aspettiamo di trovare i classici comandi shell come
lsgrepe così via
Di base, Linux rappresenta solo il kernel, mentre queste assunzioni riguardano la presenza di pacchetti software installati (e correttamente configurati). Un Distro layer racchiude quindi tutte quelle cose che ci aspettiamo di trovare di base in un sistema Linux. Poi per casi specifici possiamo andare ad aggiungere o rimuovere cose, ma qua stiamo cercando di coprire il buon 80% dei casi.
Software
Questo nome è volutamente generico.
Qualsiasi cosa che stiamo vedendo
è definibile come software.
Pure i layer BSP e Distro possono essere definiti Software.
Infatti i layer BSP e Distro sono specifici,
mentre Software è molto più generico.
È “tutto il resto”
(documentazione ufficiale).
La grande distinzione è che un layer Software
fatto bene deve essere hardware-agnostic.
Ad esempio, un layer Software può implementare:
- un applicativo complesso come
Gnome(meta-gnome) - un interprete
Python(meta-python) - varie utility per creare un
web server(meta-webserver)
Questi layer, tra l’altro, sono così generici
ed essenziali che fanno parte della raccolta
meta-openembedded,
chiamata anche oe-extra,
perchè non rappresenta il build system open-embedded di per sè,
ma aggiunge il supporto per funzionalità estremamente comuni.
Altri esempi di layer Software, che però non fanno
parte di oe-extra sono:
- il supporto per
FirefoxeChromium(meta-browser) - il supporto per
SDK Dartper applicazione mobile (meta-dart) - il supporto
Flutter(meta-flutter) e molti altri.
dove trovarli
OpenEmbedded fornisce un portale web
dove poter trovare quasi tutti i layer Yocto
possibili e immaginabili al
OpenEmbedded Layer Index.
Per ognuno di questi troviamo dettagli
sui recipe contenuti all’interno,
su eventuali dipendenze da altri layer,
sul livello di “qualità” del layer
e molto altro.
Il livello di qualità è da intendersi
come la quantità di buone prassi
che sono state seguite e che quindi
garantiscono una buona
integrazione del layer all’ interno
del build system.
In sostanza indica se un layer
sia stato pensato per non creare
conflitti vari con altri layer
(Yocto Project Compatible Layers).
Poi ovviamente possono esistere
altri layer disponibili ovunque
nel web, ma quelli nel oe index
almeno sono stati visionati da
qualcuno di esperto.
come sono fatti
Un layer è descritto tramite un file layer.conf
che definisce alcune informazioni sul layer
e soprattuto definisce i path a cui trovare i vari recipe.
Yocto definisce una struttura di precisa
di cartelle e file da utilizzare
per costruire un layer,
ma tutte queste convenzioni sono definite
tramite il file layer.conf.
La struttura generica è questa:
meta-example
├── classes
│ └── example-class.bbclass
├── conf
│ └── layer.conf
├── recipes-****
├── recipes-****
└── recipes-****
├── example-recipe-1
└── example-recipe-2
└── example-recipe-2.bbovvero una cartella conf dove configurare il layer
e molteplici cartelle recipes- per
contenere uno o più recipe.
Un generico layer.conf può essere:
1# We have a conf and classes directory, add to BBPATH
2BBPATH =. "${LAYERDIR}:"
3
4# We have recipes-* directories, add to BBFILES
5BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
6 ${LAYERDIR}/recipes-*/*/*.bbappend"
7
8BBFILE_COLLECTIONS += "yocto"
9BBFILE_PATTERN_yocto = "^${LAYERDIR}/"
10BBFILE_PRIORITY_yocto = "5"
11
12LAYERSERIES_COMPAT_yocto = "scarthgap"
13
14# This should only be incremented on significant changes that will
15# cause compatibility issues with other layers
16LAYERVERSION_yocto = "3"
17
18LAYERDEPENDS_yocto = "core"
19
20REQUIRED_POKY_BBLAYERS_CONF_VERSION = "2"La prima cosa che avviene è la modifica della variabile
BBPATH che è la variabile utilizzata in tutto il build system
per definire i percorsi da analizzare.
Tramite un immediate prepend viene aggiunto il
path definito da LAYERDIR,
la quale contiene il valore assoluto del percorso alla
cartella del nostro layer.
Questa assegnazione è il motivo per cui
nei recipe possiamo fare riferimento ad altri file
utilizzando il percorso relativo rispetto alla directory del layer stesso.
Successivamente con BBFILE vengono definiti
i percorsi in cui bitbake dovrà cercare eventuali file .bb.
Questi percorsi sono valutati a partire da un qualsiasi
percorso definito in BBPATH.
In BBFILE potremmo definire dei percorsi che escono
al di fuori del layer, ma questo è decisamente sconsigliato.
Sempre qui viene anche decisa la struttura delle cartelle recipes-,
che è sempre del tipo:
recipes-CATEGORY
├── RECIPE-1
│ └── RECIPE-1.bb
└── RECIPE-2
└── RECIPE-2.bbappendSolitamente per le cartelle recipes-
vengono utilizzati dei nomi che sono
già presenti nel layer meta,
in modo da replicarne la struttura, ad esempio:
meta
├── conf
├── recipes-bsp
├── recipes-connectivity
├── recipes-core
└── recipes-kernelQuesta non è una regola ferrea,
ma semplicemente una convenzione
che permette poi di visualizzare
più facilmente le “sovrapposizioni”
di molteplici layer.
Infatti se un layer presenta un .bb
in meta-layer/recipes-core/app.bb,
allora la convenzione suggerisce
che un diverso layer posizioni
un app_%.bbappend al percorso
meta-other-layer/recipes-core/app_%.bbappend.
come sono fatti pt.2
Quella che abbiamo appena visto
è la struttura di un layer generico
e i layer generici sono quelli di tipologia Software.
I layer BSP e Distro hanno come unica differenza
la presenza di una sottocartella aggiuntiva alla cartella conf.
Se è presente la cartella conf/machine
allora il layer è di tipo BSP.
Se è presente la cartella conf/distro
allora il layer è di tipo Distro.
E’ possibile utilizzare entrambe le cartelle nello stesso layer,
a discapito della modularità di questo.
Queste cartelle contengono degli ulteriori file .conf
che sfruttano la solita logica di variabili bitbake.
Utilizzano variabili che sono usate
per pilotare meccanismi molto particolari,
come MACHINE_FEATURES e DISTRO_FEATURES,
ma li vedremo nelle sezioni dedicate
ai layer BSP e Distro.
Questa voleva essere solo una premessa.
Un esempio di struttura:
meta-example-bsp
├── classes
├── conf
│ ├── machine
│ │ ├── example-board-1.conf
│ │ └── example-board-2.conf
│ └── layer.conf
├── recipes-****
├── recipes-****
└── recipes-****Siccome molte definizioni
sono spesso comuni a molteplici schede
è possibile raggruppare queste
definizioni comuni all’interno di file .inc
e includerli all’interno dei vari file .conf:
meta-example-bsp
├── classes
├── conf
│ ├── machine
│ │ ├── include
│ │ │ └── common.inc
│ │ ├── example-board-1.conf
│ │ └── example-board-2.conf
│ └── layer.conf
├── recipes-****
├── recipes-****
└── recipes-****1include conf/machine/include/common.inc
2
3BOARDNAME = "board-1"classi bitbake
Per essere riconosciute devono avere estensione .bbclass
ed essere contenute dentro una sottocartella classes
della directory del layer.
Altre posizioni non sono riconosciute.
Un esempio di struttura di un layer con classi bitbake:
meta-example
├── classes
│ ├── example-class-1.bbclass
│ ├── example-class-2.bbclass
│ └── example-class-3.bbclass
├── conf
├── recipes-****
├── recipes-****
└── recipes-****Nel layer meta sono presenti anche le sottocartelle
classes-recipe e classes-global,
ma per gli altri layer è disponibile solo la presenza o meno
della sottocartella classes.
Questo a causa di regole “hard-coded” di bitbake.
conclusioni
Bene, se hai iniziato a leggere questo articolo partendo dalle conclusioni ti dò la soddisfazione di ricevere un elenco delle cose utili. Adesso sappiamo:
- le 3 tipologie di layer
- come riconoscerli
- dove cercarli su internet
- dentro a un layer possiamo usare path relativi
- come sono organizzati i recipe
- dove trovare le classi