Laboratorul 07. Yocto images and SDK

Asa cum am mentionat si laboratorul trecut Yocto este o colecție de utilitare, metadate și șabloane ce permit construirea/compilarea distribuțiilor de Linux pentru platforme embedded ce oferă posibilitatea de a crea distribuții personalizate pornind de la 0 sau de la imagini scheletice. In cadrul acestui laborator vom continua si vom adauga context si exemple informatiei dobandite pana acum. Printre conceptele pe care le vom acoperi putem include: notiunea de imagine cum se poate lucra cu ea, care este rolul acestei notiuni si cum putem lucra cu ea si de asemenea vom adauga aici si notiundea de SDK si modul in care putem genera cod sursa pentru o platforma hardware (MACHINE, asa cum este ea definita in domeniul Yocto Project).

Imagine

Când am rulat „bitbake core-image-base” laboratorul trecut, build engine-ul Bitbake se uită la variabila PROVIDES a fiecărei rețete pentru a afla rețeta pentru o anumită aplicatie tinta. Valoarea implicită a PROVIDES este PN.

  • PN –> Numele rețetei
  • PV –> Versiunea rețetei
  • PR –> Revizuirea rețetei

Uneori, o țintă poate avea mai mulți furnizori. PREFERRED_PROVIDER determină cărei rețete ar trebui să i se acorde preferință atunci când mai multe rețete oferă același articol.

De exemplu. virtual/kernel, u-boot va fi furnizat de mai multe rețete

  • PREFERRED_PROVIDER_virtual/kernel = “linux-imx”
  • PREFERRED_PROVIDER_u-boot = „uboot-imx”

Acest lucru ar trebui să fie scris în local.conf sau machine.conf

Când sunt disponibile mai multe versiuni ale unei rețete, variabila PREFERRED_VERSION determină rețetei care trebuie să primească preferință. Dacă nu precizăm versiunea, bitbake va prelua cea mai mare versiune din punct de vedere lexico-numeric. De exemplu.

  • PREFERRED_VERSION_linux-imx = “3.10.17-1.0.0”
  • PREFERRED_VERSION_u-boot-imx = „2013-04”

Ceea ce este diferita la o reteta de imagine fata de o reteta pentru un aplicatie este definit in modul in care task-urile sunt definite intern.

task

Task-ul este unitatea cea mai mica de execuție pe care build engine-ul Bitbake o poate executa. Task-urile sunt definite intern in fisiere generice numite clase. Mai jos puteti gasi o definitie pentru principalele task-uri disponibile:

  • do_build

Sarcina implicită pentru toate rețetele. Această sarcină depinde de toate celelalte sarcini normale necesare pentru a construi o rețetă.

  • do_configure

Configurează sursa activând și dezactivând orice opțiuni de configurare și de timp de construcție pentru software-ul care este construit. Sarcina rulează cu directorul de lucru curent setat la B. Comportamentul implicit al acestei sarcini este de a rula oe_runmake clean dacă este găsit un makefile (Makefile, makefile sau GNUmakefile) și CLEANBROKEN nu este setat la „1”. Dacă nu este găsit un astfel de fișier sau variabila CLEANBROKEN este setată la „1”, sarcina do_configure nu face nimic.

  • do_compile

Compilează codul sursă. Această sarcină rulează cu directorul de lucru curent setat la B. Comportamentul implicit al acestei sarcini este de a rula funcția oe_runmake dacă este găsit un makefile (Makefile, makefile sau GNUmakefile). Dacă nu este găsit un astfel de fișier, sarcina do_compile nu face nimic.

  • do_deploy

Scrie fișiere de ieșire care urmează să fie implementate în DEPLOY_DIR_IMAGE. Sarcina rulează cu directorul de lucru curent setat la B. Rețetele care implementează această sarcină ar trebui să moștenească clasa de implementare și ar trebui să scrie rezultatul în DEPLOYDIR, care nu trebuie confundat cu DEPLOY_DIR. Clasa deploy setează do_deploy ca sarcină de stare partajată (sstate) care poate fi accelerată prin utilizarea sstate. Mecanismul sstate are grijă să copieze rezultatul de la DEPLOYDIR în DEPLOY_DIR_IMAGE.

  • do_fetch

Preia codul sursă. Această sarcină utilizează variabila SRC_URI și prefixul argumentului pentru a determina modulul de preluare corect.

  • do_rootfs

Creează sistemul de fișiere rădăcină (structură de fișiere și directoare) pentru o imagine. Consultați secțiunea Generarea imaginilor din manualul de prezentare și concepte a proiectului Yocto pentru mai multe informații despre cum este creat sistemul de fișiere rădăcină.

  • do_image

Începe procesul de generare a imaginii. Sarcina do_image rulează după ce sistemul a rulat sarcina do_rootfs în timpul căreia pachetele sunt identificate pentru instalare în imagine și este creat sistemul de fișiere rădăcină, complet cu post-procesare. Sarcina do_image efectuează preprocesarea imaginii prin IMAGE_PREPROCESS_COMMAND și generează în mod dinamic sarcini de suport do_image_* după cum este necesar.

  • do_install

Copiază fișierele care urmează să fie împachetate în zona de stocare D. Această sarcină rulează cu directorul de lucru curent setat la B, care este directorul de compilare. Sarcina do_install, precum și alte sarcini care depind direct sau indirect de fișierele instalate (de exemplu, do_package, do_package_write_* și do_rootfs), rulează sub fakeroot.

  • do_package

Analizează conținutul zonei de stocare D și împarte conținutul în subseturi pe baza pachetelor și fișierelor disponibile. Această sarcină folosește variabilele PACKAGES si FILES.

  • do_patch

Localizează fișierele cu extensia *.patch și le aplică codului sursă. După preluarea și despachetarea fișierelor sursă, sistemul de compilare folosește instrucțiunile SRC_URI ale rețetei pentru a localiza și aplica fișierele de patch la codul sursă.

  • do_populate_sdk

Creează structura de fișiere și directoare pentru un SDK instalabil. Consultați secțiunea Generare SDK din manualul de prezentare generală și concepte a proiectului Yocto pentru mai multe informații.

  • do_populate_sysroot

Copilează un subset de fișiere instalate de sarcina do_install în sysroot-ul corespunzător. Pentru informații despre cum să accesați aceste fișiere din alte rețete, consultați variabilele STAGING_DIR*. Directoarele care de obicei nu ar fi necesare pentru alte rețete în momentul construirii (de exemplu, /etc) nu sunt copiate implicit. Pentru informații despre directoarele copiate implicit, consultați variabilele SYSROOT_DIRS*. Puteți modifica aceste variabile în interiorul rețetei dvs. dacă trebuie să faceți directoare suplimentare (sau mai puține) disponibile pentru alte rețete în timpul construirii. Sarcina do_populate_sysroot este o sarcină de stare partajată (sstate), ceea ce înseamnă că sarcina poate fi accelerată prin utilizarea stării. Realizați, de asemenea, că, dacă sarcina este re-execută, orice ieșire anterioară este eliminată (adică „curățată”).

  • do_prepare_recipe_sysroot

Instalează fișierele în sysroots-uri individuale specifice rețetei (adică recipe-sysroot și recipe-sysroot-native sub WORKDIR pe baza dependențelor specificate de DEPENDS). Consultați clasa „în scenă” pentru mai multe informații.

  • do_rm_work

Elimină fișierele de lucru după ce sistemul de build a terminat cu ele. Puteți afla mai multe uitându-vă la secțiunea „rm_work.bbclass”.

  • do_unpack

Despachetează codul sursă într-un director de lucru indicat de WORKDIR. Variabila S joacă rol de sursa pentru fișierele dezambalate. Pentru mai multe informații despre modul în care fișierele sursă sunt despachetate, consultați secțiunea Preluare surse din manualul de prezentare generală și concepte a proiectului Yocto și, de asemenea, consultați descrierile variabilelor WORKDIR și S.

Pentru mai multe informații despre crearea imaginilor, consultați secțiunea Generarea imaginilor din manualul de prezentare și concepte a proiectului Yocto.

clasa

Clasele in Yocto Project (.bbclass) reprezinta o definitie generica a task-urilor ce se poate aplica unei retete, notiune ce permite extinderea sau modificarea. Sunt folosite pentru a abstractiza funcționalitatea comună și a le partaja între mai multe fișiere cu rețete (.bb), pentru a gestiona unele probleme generale. De exemplu, gestionarea CMake în rețete se face în cmake.bbclass, astfel încât atunci când adăugați inherit cmake, rețeta dvs. va gestiona specificul CMake.

Mai multe notiuni despre fiecare clasa in parte se pot afla accesand link-ul: Clase in Yocto Project din manualul de prezentare și concepte a proiectului Yocto.

masina

În general, există trei tipuri de informatii disponibile intr-un layer. Le puteți vedea expuse in imaginea alaturara ce descrie fluxul de lucru pentru sistemul de build numit Bitbake.

  • Metadate (.bb + Patch-uri): Straturi de software care conțin fișiere de rețete furnizate de utilizator, patch-uri și fișiere anexate. Un bun exemplu de layer software ar putea fi meta-qt5. Acest layer este pentru versiunea 5.0 a popularului IDE utilizat pentru dezvoltarea de aplicații multiplatformă Qt pentru desktop, dispozitive încorporate și mobil.
  • Configurație BSP a mașinii: Board Support Package (BSP) care oferă configurații specifice mașinii. Acest tip de informații este specific unei anumite arhitecturi țintă. Un bun exemplu de layer BSP din distribuția de referință (Poky) este layer-ul meta-yocto-bsp.
  • Configurare politici specifice distributiei: Layere de distribuție care oferă politici de nivel superior sau generale pentru imaginile sau SDK-urile care sunt construite pentru o anumită distribuție. De exemplu, în layer-ul de referinta al distributiei Poky numit meta-poky se afla o serie de variante de astfel de politici specifice. În layeer-ul de distribuție se află un director conf/distro care conține fișiere de configurare a distribuției (de exemplu, poky.conf care conține multe configurații de politică pentru distribuția Poky.

In general informatia specifica de masina se afla in layer specifice de BSP, acolo pe langa configuratia particulara pentru masina disponibila de obicei in fisierul de configuratie conf/machine/machine.conf ce descrie in general versiune de kernel si bootloader specifica target-ului ales se mai afla retete cu configuratii particulare pentru a pune in functiune suportul de baza cum ar fi drivere video, grafice, audio etc.

Un exemplu pentru un fisier cu o definitie a masinii este qemuarm.conf folosit si in cadrul laboratorului. Aici se mai pot observa configuratii pentru preferintele de compilator alese, configurarea interfetei seriale, inclusiv argumente necesare pentru pornirea emulatorului de Qemu.

distributie

In cazul distributiei de referinta definita in poky.conf pe care o sa se bazeze majoritatea activitatii noastre se poate observa ca pe langa informatii despre numele si versiunea distributiei sau maintainer-ul acesteia se mai pot identifica o serie de caracteristici, FEATURES asa cum sunt ele numite.

Acest capitol oferă o referință pentru caracteristicile echipamentelor livrate și ale distribuției pe care le puteți include ca parte a imaginii dvs., o referință la caracteristicile imaginii pe care le puteți selecta și o referință la completarea caracteristicilor. Caracteristicile oferă un mecanism pentru a stabili ce pachete ar trebui incluse în imaginile generate. Distribuțiile pot selecta caracteristicile pe care doresc să le suporte prin variabila DISTRO_FEATURES, care este setată sau atașată în fișierul de configurare al unei distribuții, cum ar fi poky.conf, poky-tiny.conf, poky-lsb.conf și așa mai departe. Caracteristicile mașinii sunt setate în variabila MACHINE_FEATURES, care este setată în fișierul de configurare a mașinii și specifică caracteristicile hardware pentru o anumită mașină.

Aceste două variabile se combină pentru a determina ce module kernel, utilitare și alte pachete trebuie incluse. O anumită distribuție poate suporta un subset selectat de caracteristici, astfel încât unele caracteristici ale mașinii ar putea să nu fie incluse dacă distribuția în sine nu le acceptă.

Pentru mai multe detalii despre lista de caracteristici suportate in fiecare categorie: DISTRO_FEATURES, MACHINE_FEATURES sau IMAGE_FEATURES puteti consulta link-ul Caracteristicilor Yocto Project atasate.

SDK

De asemenea in imaginea de mai sus cu poky.conf am putut observa notiuni despre Software Development Kit (SDK), acest SDK similar imaginii este specific arhitecturii harware si include tot suportul necesar dezvoltarii de aplicatii pentru target-ul ales. In general SDK-ul contine următoarele:

  • Cross-Development Toolchain: acest lanț de instrumente conține un compilator, un debugger și diverse instrumente asociate.
  • Biblioteci, anteturi și simboluri: bibliotecile, anteturile și simbolurile sunt specifice imaginii (adică se potrivesc cu imaginea cu care a fost construit SDK-ul).
  • Script de configurare a mediului: Acest fișier *.sh, odată preluat, configurează mediul de dezvoltare prin definirea variabilelor și pregătirea pentru utilizarea SDK.

Puteți utiliza un SDK pentru a dezvolta și testa în mod independent codul care este destinat să ruleze pe o mașină țintă. SDK-urile sunt complet autonome. Binarele sunt legate de propria lor copie a librariei standard C (libc), ceea ce duce la nicio dependență de sistemul țintă. Pentru a realiza acest lucru, pointer-ul către loader-ul dinamic este configurat în momentul instalării, deoarece acea cale nu poate fi modificată dinamic. Acesta este motivul pentru un wrapper în jurul arhivelor populate_sdk și populate_sdk_ext.

$ bitbake core-image-base -c populate_sdk

O altă caracteristică a SDK-urilor este că este produs un singur set de binare pentru toolchain-ul folosit pentru cross-compilare indiferent de arhitectura dată. Această caracteristică profită de faptul că hardware-ul țintă poate fi transmis către gcc ca un set de opțiuni de compilare. Aceste opțiuni sunt setate de scriptul de mediu și sunt conținute în variabile precum CC și LD. Acest lucru reduce spațiul necesar pentru unelte. Înțelegeți, totuși, că fiecare țintă are încă nevoie de propriul sistem sysroot, deoarece acele binare sunt specifice țintei.

Mediul de dezvoltare SDK constă din următoarele:

  • SDK-ul autonom, care este un lanț de instrumente încrucișat specific arhitecturii și sysroots (țintă și nativ) care se potrivesc, toate construite de engine-ul Bitbake (de exemplu, SDK-ul). Lanțul de instrumente și sysroots se bazează pe o configurație de metadate și extensii, care vă permit să dezvoltați încrucișat pe mașina gazdă pentru hardware-ul țintă. În plus, SDK-ul extensibil conține funcționalitatea devtool pentru generare automata de retete.
  • Quick EMUlator (QEMU), care vă permite să simulați hardware-ul țintă. QEMU nu face parte literalmente din SDK. Trebuie să construiți și să includeți acest emulator separat. Cu toate acestea, QEMU joacă un rol important în procesul de dezvoltare care se învârte în jurul utilizării SDK-ului.

SDK-ul este instalat pe orice mașină și poate fi folosit pentru a dezvolta aplicații, imagini chiar si functionalitati ale kernelului de Linux sau ale bootloader-ului. Un SDK poate fi folosit chiar și de un inginer QA sau un inginer responsabil cu release-urile. Conceptul fundamental este că mașina care are instalat SDK-ul nu trebuie să fie asociată cu mașina care are instalat proiectul Yocto. Un dezvoltator poate compila și testa în mod independent un obiect pe mașina sa și apoi, când obiectul este gata pentru integrare într-o imagine, îl poate pune pur și simplu la dispoziția mașinii care are Proiectul Yocto. Odată ce obiectul este disponibil, imaginea poate fi reconstruită folosind Proiectul Yocto pentru a produce imaginea modificată.

Pentru a instala SDK-ul pe statia locala se utilizeaza urmatoarele instructiuni:

$ mkdir ../sdk-install
$ ./tmp/deploy/sdk/poky-glibc-x86_64-core-image-base-cortexa15t2hf-neon-qemuarm-toolchain-4.0.5.sh -d ../sdk-install
$ source /opt/poky/4.0.5/environment-setup-cortexa15t2hf-neon-poky-linux-gnueabi

Exerciții

  • Adaugati un utilizator nou in sistem.

Pentru a modifica numele pe care îl publică un RaspberryPi este suficient să modificăm /etc/hostname. Pentru aceasta am putea modifica fișierul din imagine, dar dezavantajul este că ar trebui să facem această modificare la fiecare recompilare. Am prefera să obținem direct o imagine cu numele nou, iar ca să obținem acest lucru trebuie să modificăm rețetele Bitbake care stau la baza pachetelor instalate în imagine. Fisierul hostname ar trebui sa fie plasat aici: <poky_path>/meta/recipes-core/base-files/. Vedeți și codul sursă al rețetei originale aici.

Pentru a adăuga un fișier hostname în imagine trebuie să:

  • aveți un fișier hostname în locația unde sunt toate fișierele de inclus
  • modificați fișierul .bbappend (adăugirea la rețetă), adăugând în variabila SRC_URI noul fișier (cu += ) și implementând o funcție cu numele do_install:append(), care se va executa în cadrul rețetei după do_install
  • de asemenea, tot în fișierul .bbappend va trebui să adăugați calea către directorul cu fișierul nou:
    • FILESEXTRAPATHS:prepend := “${THISDIR}/${PN}:”
  • Rulați apoi bitbake core-image-base
  • Verificați rezultatul rulând noua imagine cu Qemu!

Puteti de asemenea consulta exemplele disponibile in layer-ul meta-skeleton precum reteta useradd-example.bb

  • Creati un serviciu SystemD care porneste binarulul myhelloworld generat cu ajutorul retetei HelloWorld.bb din laboratorul trecut. Este recomandat sa actualizati reteta HelloWorld.bb deja disponibila.

Nu uitati sa adaugati suportul in imaginea de root filesystem folosita si sa rulați bitbake core-image-base. Verificați ca aveti rezultatul dorit rulând noua imagine cu Qemu!

  • Dupa ce ati adaugat tot suportul de mai sus, generati un SDK pentru imaginea buildata anterior si modificati aplicatia myhelloworld.c astfel incat sa raporteze informatii despre sistemul pe care ruleaza. Apoi buildati noua aplicatie cu SDK obtinut anterior si incarcati noul binar sub in alt nume in Qemu. Observati rezultatul!
si/lab/2022/laboratoare/07.txt · Last modified: 2023/09/26 14:15 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0