Il contesto

Nello sviluppo di soluzioni embedded esiste uno standard tecnico de facto: Yocto Linux, o più brevemente Yocto. Il progetto Yocto è un progetto collaborativo: consente ai vari produttori facenti parte della supply chain di un dispositivo embedded di fornire un layer di sorgenti compilabili per varie piattaforme. 

Per esempio, se si acquista una scheda madre con processore NXP (ex Freescale) con il progetto Yocto troveremo inclusi i sorgenti e gli script necessari a compilare da zero le componenti di una distribuzione Linux prodotte da NXP insieme al suo hardware e necessarie a far funzionare tale sistema operativo con i chipset NXP.

I punti di forza del progetto Yocto sono:

  • la natura distribuita: ogni fornitore nella supply chain aggiunge il suo “strato” di sorgenti compilabili: si distribuisce così il carico di lavoro necessario alla realizzazione di un prodotto embedded, dal kernel all’interfaccia utente;
  • la natura multi-piattaforma: Yocto distribuisce sorgenti e script di compilazione facendo sì che un produttore possa creare uno solo set di sorgenti che si adatti a tutte le componenti/periferiche da lui vendute. Tornando all’esempio di NXP, tale azienda ha un unico repository di sorgenti per tutte le piattaforme vendute e degli script che customizzano la compilazione in base al processore (i.MX6, i.MX7 etc…)

Qt/QML: lo standard embedded per lo sviluppo di UI/UX

Se Yocto è lo standard de facto per realizzare una distribuzione Linux in un contesto industriale embedded, le librerie Qt/QML sono lo standard de facto per lo sviluppo della UI e di buona parte della logica di interazione tra UI e business logic. Tali librerie sono così integrate nell’ecosistema embedded che hanno un loro strato in Yocto. Ovviamente, versioni diverse di Yocto distribuiscono versioni diverse di Qt/QML, e queste, a loro volta, possono contenere funzionalità diverse o meglio da versione a versione possono introdurre funzionalità nuove.

Yocto: i problemi per i System Integrator

Il difetto di tale soluzione risiede nel fatto che risulta molto difficile poter intervenire e modificare uno degli “strati” senza avere una conoscenza approfondita del sistema Yocto, per questo il software system integrator, che spesso si trova alla fine della supply chain, è costretto:

  1. ad investire ingenti somme di tempo e denaro per diventare esperto Yocto, oppure,
  2. ad adeguarsi ai pacchetti software+hardware che riesce a trovare in commercio, effettuando una scelta sul prodotto “meno distante” dalle sue necessità.

Questo aspetto è molto sentito, specialmente quando l’integratore deve fornire al cliente più soluzioni embedded che – per ragioni di convenienza economica- provengono da supply chain diverse. In particolare, è molto probabile che due sistemi embedded prodotti da aziende diverse siano distribuiti con versioni di Yocto diverse e contenenti versioni non compatibili tra loro di Qt/QML.

Tuttavia, l’obiettivo dell’integratore è quello di realizzare lo stesso software, con lo stesso sorgente, e renderlo funzionante con pari specifiche e UX sulle diverse piattaforme. Gestire più codebase infatti farebbe aumentare in maniera rilevante i costi di sviluppo e manutenzione del prodotto.

La soluzione: Yocto compile toolchain

Esiste una “via di mezzo” tra le due alternative elencate in precedenza. Uno dei così detti “target” di Yocto è la compile toolchain, ovvero il kit di software necessari per cross-compilare il software sul proprio pc e distribuirlo poi sul dispositivo associato. Impiegando tale toolchain e recuperando i sorgenti di progetti Yocto non compatibili, è possibile utilizzare questo sistema per adattare due distribuzioni Yocto tra loro.

In particolare, detta A la prima distribuzione e B la seconda, è possibile impiegare la toolchain di B per ricompilare i sorgenti di uno strato di A, oppure risalire direttamente all’upstream di tale strato e compilare con la toolchain di B i sorgenti “vanilla” (senza patch) di uno strato. In questo secondo caso è ovviamente necessario verificare che il software vanilla sia compatibile con l’hardware.

I passaggi per generare una toolchain di cross-compilazione sono riassumibili a livello concettuale nei seguenti punti:

  1. cross-compilare la meta-toolchain, ovvero il kit di cross-compilazione con il tool ‘Bitbake’ incluso in Yocto:
    > bitbake mate-toolchain
  2. il comando precedente creerà uno script autoinstallante per poter installare sul pc la toolchain. Lo si potrà eseguire con:
    >  /opt/$OUTPUT/$VERSION/environment-setup-$ARCH-$SUB-$YOCTOTAG-linux-gnueabi
    dove:
    1. $OUTPUT è la cartella di output configurata in bitbake
    2. $VERSION è la versione della toolchain distribuita con Yocto
    3. $ARCH è l’architettura della cpu embedded (es.cortexa7hf)
    4. $SUB è la sub architettura che abilita feature specifiche di una famiglia di processori
    5. $YOCTOTAG è la tag che identifica la distribuzione Yocto che si genera (ad esempio la distribuzione di default nominata ‘poki’)

Cross-compilare i sorgenti vanilla di Qt/QML con le toolchain Yocto

Ottenuta la tooIchain, i passaggi per una cross-compilazione di Qt/QML sono riassumibili nei seguenti punti:

  1. Scaricare i sorgenti Qt/QML della versione di interesse da github. È consigliato eseguire il checkout detached della tag indicante la versione specifica. Es:
    > git clone git://code.qt.io/qt/qt5.git
    > git checkout $VERSIONTAG
    > git submodule update –init –recursive
    dove:
    1. $VERSIONTAG è la versione delle Qt che desiderate (es. 5.12)
  2. Definire le mkspecs, ovvero le specifiche di architettura che saranno necessarie a Qt/QML per “adattarsi” all’ambiente embedded. Per partire esiste un file base chiamato $QTSOURCE/qtbase/mkspecs/linux-arm-gnueabi-g++, dove $QTSOURCE è la cartella dei sorgenti Qt/QML. Questo passaggio serve a indicare la corretta toolchain di compilazione, quindi è necessario editare questo file, sostituendo alle voci di esempio quelle della vostra toolchain. Ad es:

QMAKE_CC = arm-$YOCTOTAG-linux-gnueabi-gcc

  1. Utilizzare il tool “configure” distribuito con Qt/QML per configurare tutte le opzioni che desiderate. Attenzione! Questo è il passaggio critico che vi permetterà di personalizzare al massimo l’esperienza di compilazione, includendo o escludendo moduli Qt che necessitate o meno, configurando il supporto hardware (es. OpenGL anziché Linux Framebuffer) etc… Di particolare importanza gli switch:
    1. ‘-sysroot’ indica il percorso alla toolchain Yocto di cross-compilazione
    2. ‘-xplatform’ indica il percorso del file mkspecs realizzato al punto precedente e contenente le specifiche di cross-compilazione
    3. ‘-nomake tests -nomake examples’ esclude i test e gli esempi dalla compilazione per velocizzarla

Conclusione

Lo sviluppo di soluzioni embedded industriali passa di fatto dall’impiego di un sistema Yocto Linux. Tale sistema, per quanto flessibile, richiede uno sforzo notevole quando si voglia modificare uno dei suoi strati software. 

Questa esigenza può nascere quando ci si trovi a dover generare un’unica codebase per gestire in maniera ottimale le stesse funzionalità e UX su dispositivi diversi che vengono nativamente forniti con sistemi Yocto differenti e versioni Qt/QML differenti. 

Per ovviare al problema è possibile generare una toolchain di cross-compilazione e compilare il progetto Qt/QML vanilla.

Questa soluzione ci ha permesso, ad esempio, di abilitare pari funzionalità di UX con una stessa codebase, su dispositivi aventi o meno accelerazione grafica e destinati a definire alternative a costo diverso di una stessa gamma di prodotto.

Matteo Nunziati
Senior Software Engineer
Kiwibit

Matteo Nunziati
Senior Software Engineer
Kiwibit

POTREBBERO INTERESSARTI ANCHE

Le parole chiave dell’innovazione: ecco come l’industria 4.0 rivoluzionerà la produzione nei prossimi anni

Acatech Acatech è l'Accademia tedesca delle scienze e dell'ingegneria fondata il 1 ° gennaio 2008 e che rappresenta gli interessi delle scienze tecniche tedesche in modo indipendente in patria e all'estero, equivalente al nostro CNR. Essa fornisce valutazioni...

Share This