Nous avons vu comment produire une image dont le contenu est personnalisé, et nous savons y ajouter automatiquement des fichiers existants (des scripts par exemple) sur notre machine de production.
Il est rare qu’un système embarqué ne contienne que du code métier écrit sous forme de scripts. Ceci est possible (notamment si les applications sont développées en Python, NodeJS, etc.) mais la plupart du temps, il sera nécessaire de compiler au moins une partie de l’applicatif métier.
Yocto Project, comme tout environnement Linux, propose une chaîne de compilation Gnu complète, contenant des compilateurs C, C++, Java, et même Ada ou Fortran si on le souhaite. Dans cette séquence nous allons extraire cette toolchain afin de pouvoir compiler notre code métier indépendamment de Yocto, puis installer manuellement sur la cible les fichiers exécutables produits.
Cette approche est couramment employée lors de la phase de mise au point et débogage du code métier. Une fois que l’applicatif est bien finalisé, il sera intéressant de l’intégrer directement dans le build de Yocto Project, ce sera le sujet de la prochaine séquence.
La première étape consiste à demander à Yocto de nous fournir une
chaîne de compilation que nous pourrons utiliser indépendamment de
bitbake
, des recettes et des layers que nous avons
vus jusqu’à présent.
La plupart du temps notre système cible sera construit autour d’un processeur (par exemple un cœur ARM ou Risc-V) différent de celui équipant notre système de production (généralement dans la gamme x86-64). Il faut donc disposer d’une chaîne de cross-compilation, c’est-à-dire un ensemble comprenant le compilateur, l’assembleur, l’éditeur de liens, l’archiveur, le débogueur, etc. fonctionnant sur notre PC mais produisant du code binaire pour une architecture différente.
Il est possible de trouver sur le web des chaînes de cross-compilation toutes prêtes, mais il est largement préférable de prendre celle qui a été produite par Yocto lors de sa première compilation.
Vous vous souvenez, du premier appel à bitbake
qui durait
plusieurs heures ?
S’il était si long, c’est justement parce qu’il préparait ses propres outils de compilation. Demandons-lui de les partager avec nous…
Pour cela nous appelons bitbake
en lui ajoutant une option
supplémentaire
«-c populate_sdk
». Celle-ci
lui demande de nous fournir le SDK
(Software Development Kit),
l’ensemble des outils nécessaires pour produire du code métier pour
notre image. Cet ensemble est un peu plus riche que la simple chaîne de
compilation, puisqu’il contient également les fichiers headers
pour les bibliothèques supplémentaires ajoutées dans l’image.
[build-qemu]$ bitbake -c populate_sdk my-image [...] [build-qemu]$ ls tmp/deploy/ images licenses rpm sdk spdx
La durée de cette préparation est très variable en fonction de ce qui a
été compilé au préalable. Ne soyez pas surpris si elle atteint une
heure, voire plus. Nous voyons qu’un nouveau sous-dossier
«sdk/
» est apparu dans le répertoire
tmp/deploy/
. Examinons son contenu :
[build-qemu]$ ls tmp/deploy/sdk/ my-distro-glibc-x86_64-my-image-cortexa15t2hf-neon-qemuarm-toolchain-1.0-host.spdx.tar.zst my-distro-glibc-x86_64-my-image-cortexa15t2hf-neon-qemuarm-toolchain-1.0-target.spdx.tar.zst my-distro-glibc-x86_64-my-image-cortexa15t2hf-neon-qemuarm-toolchain-1.0.host.manifest my-distro-glibc-x86_64-my-image-cortexa15t2hf-neon-qemuarm-toolchain-1.0.sh my-distro-glibc-x86_64-my-image-cortexa15t2hf-neon-qemuarm-toolchain-1.0.target.manifest my-distro-glibc-x86_64-my-image-cortexa15t2hf-neon-qemuarm-toolchain-1.0.testdata.json [build-qemu]$
Six fichiers sont donc présents. Les deux fichiers aux suffixes
«.manifest
» sont des listes des
packages et bibliothèques installés sur la cible et sur le poste
de développement. Les deux fichiers «.spdx.tar.zst
»
sont des archives contenant les licences des packages installés.
Le fichier «.testdat.json
»
contient la configuration (variables d’environnement) utilisée pour
produire la toolchain. Le fichier qui nous intéresse le plus est
le script d'extension «.sh
». Il occupe quand
même plus de 800 Mo, car il encapsule toute la chaîne de compilation
sous forme binaire.
L’intérêt d’extraire cette
toolchain est que
nous pouvons l’installer sur une machine différente de celle que nous
avons employée pour faire fonctionner bitbake
.
Dans le cadre d’un développement embarqué industriel c’est très utile
car cela permet à l’équipe système de se concentrer sur
l'infrastructure bas-niveau (utilitaires, bibliothèques, noyau, support
matériel, etc.) tout en fournissant aux développeurs de l’équipe
applicative l’environnement pour compiler et tester leur code métier.
Le SDK peut être installé sur toute machine dont l’architecture est
compatible avec celle qui a produit le script (ici x86_64
avec la bibliothèque glibc
). On peut parfois rencontrer
des soucis de compatibilité des versions de la bibliothèque C, que l’on
contourne souvent en fournissant aux développeurs applicatifs une
machine virtuelle ou un container intégrant la bonne version de la
libC et la toolchain préinstallée (machine virtuelle
qu’ils peuvent d’ailleurs employer sur un autre système d’exploitation
que Linux).
Je vais installer ici la toolchain sur la même machine que celle qui m’a servi à préparer le SDK. Je copie néanmoins le script dans un autre emplacement avant de l’exécuter.
[build-qemu]$cp tmp/deploy/sdk/my-distro-glibc-x86_64-my-image-cortexa15t2hf-neon-qemuarm-toolchain-1.0.sh ~/
[build-qemu]$ cd ~ [~]$ ./my-distro-glibc-x86_64-my-image-cortexa15t2hf-neon-qemuarm-toolchain-1.0.sh My experimental distro SDK installer version 1.0 ================================================ Enter target directory for SDK (default: /opt/my-distro/1.0):
Le script nous demande où installer la toolchain. Il nous
propose par défaut une installation dans
«/opt
». Ceci est parfaitement adapté lorsque
plusieurs développeurs travaillent sur la même machine et sont tous
amenés à employer cette chaîne de compilation. L’installation nécessite
alors les droits root, ce que le script obtient en invoquant
«sudo
».
Dans le cadre de ce cours, je serai le seul à appeler la
toolchain, aussi vais-je l’installer directement dans mon
répertoire personnel. Je fournis donc un chemin personnalisé.
J’incorpore dans le chemin le nom du projet (yocto-lab
)
car mon répertoire ~/sdk
contient déjà plusieurs
toolchains appartenant à différents projets de mes clients.
Enter target directory for SDK (default: /opt/my-distro/1.0): ~/sdk/yocto-lab You are about to install the SDK to "/home/cpb/sdk/yocto-lab". Proceed [Y/n]? y
Après confirmation, le script passe à l’installation de la toolchain pendant quelques instants.
Extracting SDK.................................................................................................................................................................................done Setting it up...done SDK has been successfully set up and is ready to be used. Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g. $ . /home/cpb/sdk/yocto-lab/environment-setup-cortexa15t2hf-neon-poky-linux-gnueabi [~]$
À la fin de l’installation, un commentaire nous indique qu’un script est installé dans le répertoire indiqué, et qu’il devra être appelé avant chaque session de travail employant notre toolchain. Ce script configure les variables d’environnement nécessaires à l’invocation des différents outils de la chaîne de compilation. Voyons l’état de quelques unes de ces variables avant l’appel du script. J'ouvre une nouvelle console shell pour ne pas avoir de confusion avec les variables d'environnement configurées par le script d'initialisation de Poky.
[~]$ echo $PATH /home/cpb/.local/bin:/home/cpb/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin [~]$ echo $ARCH [~]$ echo $CROSS_COMPILE [~]$ echo $CC [~]$ echo $CFLAGS [~]$ echo $CXX [~]$ echo $CXXFLAGS [~]$ echo $LD [~]$ echo $LDFLAGS [~]$ echo $AS [~]$ echo $GDB [~]$
Les variables concernant la compilation sont vides. Le script doit être "sourcé" pour modifier l’environnement du shell appelant. Voici les mêmes variables après son exécution.
[~]$ source ~/sdk/yocto-lab/environment-setup-cortexa15t2hf-neon-poky-linux-gnueabi [~]$ echo $PATH /home/cpb/sdk/yocto-lab/sysroots/x86_64-pokysdk-linux/usr/bin:/home/cpb/sdk/yocto-lab/sysroots/x86_64-pokysdk-linux/usr/sbin:/home/cpb/sdk/yocto-lab/sysroots/x86_64-pokysdk-linux/bin:/home/cpb/sdk/yocto-lab/sysroots/x86_64-pokysdk-linux/sbin:/home/cpb/sdk/yocto-lab/sysroots/x86_64-pokysdk-linux/usr/bin/../x86_64-pokysdk-linux/bin:/home/cpb/sdk/yocto-lab/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi:/home/cpb/sdk/yocto-lab/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-musl:/home/cpb/.local/bin:/home/cpb/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/cpb/bin [~]$ echo $ARCH arm [~]$ echo $CROSS_COMPILE arm-poky-linux-gnueabi- [~]$ echo $CC arm-poky-linux-gnueabi-gcc -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a15 -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 --sysroot=/home/cpb/sdk/yocto-lab/sysroots/cortexa15t2hf-neon-poky-linux-gnueabi [~]$ echo $CFLAGS -O2 -pipe -g -feliminate-unused-debug-types [~]$ echo $CXX arm-poky-linux-gnueabi-g++ -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a15 -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 --sysroot=/home/cpb/sdk/yocto-lab/sysroots/cortexa15t2hf-neon-poky-linux-gnueabi [~]$ echo $CXXFLAGS -O2 -pipe -g -feliminate-unused-debug-types [~]$ echo $LD arm-poky-linux-gnueabi-ld --sysroot=/home/cpb/sdk/yocto-lab/sysroots/cortexa15t2hf-neon-poky-linux-gnueabi [~]$ echo $LDFLAGS -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -Wl,-z,relro,-z,now [~]$ echo $AS arm-poky-linux-gnueabi-as [~]$ echo $GDB arm-poky-linux-gnueabi-gdb [~]$
Toutes ces variables sont assez standards dans les
Makefile
. Voici leurs significations :
Nom | Signification |
---|---|
ARCH |
Architecture de la cible. Surtout utilisée pour la compilation du noyau. |
CROSS_COMPILE |
Préfixe à ajouter aux noms des outils standards. Employée par
certains Makefile dont celui du noyau. |
PATH |
Liste des répertoires à parcourir pour rechercher les exécutables. |
CC |
Compilateur C. |
CFLAGS |
Options du compilateur C. |
CXX |
Compilateur C++. |
CXXFLAGS |
Options du compilateur C++. |
CPP |
Préprocesseur C/C++. |
CPPFLAGS |
Options du préprocesseur C/C++. |
AS |
Assembleur. |
LD |
Éditeur de liens (linker). |
LDFLAGS |
Options du linker. |
AR |
Archiveur. |
GDB |
Débogueur. |
STRIP |
Suppresseur de symboles. |
RANLIB |
Indexeur de fichiers d’archives (bibliothèques). |
NM |
Visualisation des symboles d’un fichier objet. |
M4 |
Macro-processeur employé par les autotools et pour la documentation. |
Vérifions la présence et le fonctionnement du compilateur C par exemple :
[~]$ $CC --versionarm-poky-linux-gnueabi-gcc (GCC) 13.3.0 Copyright (C) 2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. [~]$
Nous pouvons prendre le petit fichier
source suivant nommé «my-hello.c
»:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/param.h> #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif int main(void) { char hostname[MAXHOSTNAMELEN]; gethostname(hostname, MAXHOSTNAMELEN); hostname[MAXHOSTNAMELEN - 1] = '\0'; fprintf(stdout, "Hello from %s\n", hostname); return EXIT_SUCCESS; }
Tout d'abord nous le compilons pour la machine de développement afin de vérifier son bon fonctionnement. C'est un avantage qu'offre l'utilisation de Linux sur la machine hôte comme sur la cible : pouvoir tester facilement — au moins en partie — le code métier sur notre poste de développement.
[~]$ gcc my-hello.c -Wall -o my-hello [~]$ ./my-hello Hello from cpb-laptop [~]$
Parfait ! Maintenant nous le cross-compilons pour la cible :
[~]$ $CC $CFLAGS my-hello.c -o my-hello [~]$ ./my-hello -bash: ./my-hello: cannot execute binary file: Exec format error [~]$ file my-hello my-hello: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=06a3222bbaeb1ec0a86d73bd72f99668961bba9e, for GNU/Linux 5.15.0, with debug_info, not stripped [~]$
Après compilation, il est évidemment impossible d’exécuter le programme
puisqu’il est prévu pour un processeur d’une architecture différente.
C’est bien ce que nous indique la commande file
.
Lorsque Qemu démarre, il crée une interface Ethernet pour la cible
reliée à une interface «Tap» sur la machine hôte
(c’est pour cela qu’il demande les droits root au démarrage).
Les deux interfaces se trouvent dans le sous-réseau
192.168.7.0/24
, la machine hôte étant en
192.168.7.1
et la cible en 192.168.7.2
.
Nous pouvons utiliser la commande
«scp
» pour transférer l’exécutable
produit sur la cible. Comme le système de fichiers principal est en
lecture-seule, j’envoie mon exécutable dans le répertoire
«/tmp
» sur lequel est monté un système de
fichiers virtuel tmpfs
résidant en mémoire.
[~]$ scp my-hello root@192.168.7.2:/tmp/ The authenticity of host '192.168.7.2 (192.168.7.2)' can't be established. RSA key fingerprint is SHA256:G0slPbW3xgsCD6a1QcHuljzfxnqMb221Q5+CGTzUN7s. This key is not known by any other names Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '192.168.7.2' (RSA) to the list of known hosts. root@192.168.7.2's password: (linux) my-hello 100% 14KB 4.6MB/s 00:00 [~]$
Je peux alors me connecter sur la cible pour lancer mon exécutable :
My experimental distro 1.0 mybox ttyAMA0 mybox login: root Password: (linux) root@mybox:~# /tmp/my-hello Hello from mybox root@mybox:~#
La compilation manuelle directe en appelant le compilateur n’est
utilisable que dans des cas très simples, pour un projet avec un seul
fichier source, et ne nécessitant pas d’options spécifiques de
compilation. Dès que le nombre de fichiers sources impliqués augmente,
on fait appel à un Makefile
ou à un autre
système de compilation (cmake
, meson
, etc.)
Voici un exemple simple de Makefile qui fait référence aux variables configurées par le script de la toolchain.
CFLAGS += -Wall EXE = my-hello OBJS = my-hello.o .PHONY: all all: $(EXE) $(EXE): $(OBJS) $(CC) $(LDFLAGS) -o $@ $^ %.o: %.c $(CC) $(CFLAGS) -c $< .PHONY: clean clean: rm -f *.o $(EXE)
On peut l’utiliser pour une compilation native (dont le code résultat sera exécuté sur la même machine que celle de compilation).
Pour pouvoir compiler le code sur PC, il ne faut pas que le script
environment-setup-cortexa15t2hf-neon-poky-linux-gnueabi
ait
été «sourcé» auparavant, sinon l'environnement contiendra
les variables correspondant au cross-compiler. Il faut donc
travailler dans un nouveau shell, par exemple en ouvrant un nouvel
onglet ou un nouveau terminal.
[~]$ echo $CC [~]$ make clean rm -f *.o my-hello [~]$ make cc -Wall -c my-hello.c cc -o my-hello my-hello.o [~]$ ./my-hello Hello from cpb-laptop [~]$
Puis nous pouvons recommencer, après avoir sourcé le script, pour faire une cross-compilation dont le résultat devra être exécuté sur la cible.
[~]$ source sdk/yocto-lab/environment-setup-cortexa15t2hf-neon-poky-linux-gnueabi [~]$ make clean rm -f *.o my-hello [~]$ make arm-poky-linux-gnueabi-gcc -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a15 -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 --sysroot=/home/cpb/sdk/yocto-lab/sysroots/cortexa15t2hf-neon-poky-linux-gnueabi -O2 -pipe -g -feliminate-unused-debug-types -Wall -c my-hello.c arm-poky-linux-gnueabi-gcc -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a15 -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 --sysroot=/home/cpb/sdk/yocto-lab/sysroots/cortexa15t2hf-neon-poky-linux-gnueabi -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -Wl,-z,relro,-z,now -o my-hello my-hello.o [~]$ ./my-hello -bash: ./my-hello: cannot execute binary file: Exec format error [~]$
Bien sûr le fichier exécutable ne peut être lancé sur la machine de compilation et comme précédemment il faut le copier sur la cible pour pouvoir le faire fonctionner.
Le mécanisme des Autotools permet d’assurer une bonne portabilité d’un code source sur différentes plateformes supportées par le projet Gnu. Ils sont utilisé dans de nombreux projets libres. Voici une version de notre Hello World utilisant ces outils :
[~]$ wget https://www.logilin.fr/files/yocto-lab/hello-autotools-1.0.tar.bz2 [...] hello-autotools-1.0.tar 100%[=============================>] 83,52K --.-KB/s in 0,02s [~]$ tar xf hello-autotools-1.0.tar.bz2 [~]$ cd hello-autotools/ [hello-autotools]$ ls aclocal.m4 compile configure depcomp install-sh Makefile.in autom4te.cache config.h.in configure.ac hello-autotools.c Makefile.am missing [hello-autotools]$
Réalisons une première compilation native pour le PC de développement.
Pour cela, on appelle le script «configure
»
fourni dans le package. Comme précédemment, il ne faut pas que le
script environment-setup-…
ait été chargé par le
shell. Il convient donc de basculer temporairement dans un nouveau
shell.
[hello-autotools]$ ./configure checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for a thread-safe mkdir -p... /usr/bin/mkdir -p checking for gawk... gawk checking whether make sets $(MAKE)... yes checking whether make supports nested variables... yes checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... no checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking whether gcc understands -c and -o together... yes checking for style of include used by make... GNU checking dependency style of gcc... gcc3 checking how to run the C preprocessor... gcc -E checking for grep that handles long lines and -e... /usr/bin/grep checking for egrep... /usr/bin/grep -E checking for ANSI C header files... yes checking for sys/types.h... yes checking for sys/stat.h... yes checking for stdlib.h... yes checking for string.h... yes checking for memory.h... yes checking for strings.h... yes checking for inttypes.h... yes checking for stdint.h... yes checking for unistd.h... yes checking for stdlib.h... (cached) yes checking sys/param.h usability... yes checking sys/param.h presence... yes checking for sys/param.h... yes checking for unistd.h... (cached) yes checking for gethostname... yes checking that generated files are newer than configure... done configure: creating ./config.status config.status: creating Makefile config.status: creating config.h config.status: executing depfiles commands [hello-autotools]$
Après toutes ses vérifications, le script
«configure
» a préparé un Makefile
que nous pouvons utiliser pour produire l’exécutable.
[hello-autotools]$ make make all-am make[1]: Entering directory '/home/cpb/hello-autotools' gcc -DHAVE_CONFIG_H -I. -g -O2 -MT hello-autotools.o -MD -MP -MF .deps/hello-autotools.Tpo -c -o hello-autotools.o hello-autotools.c mv -f .deps/hello-autotools.Tpo .deps/hello-autotools.Po gcc -g -O2 -o hello-autotools hello-autotools.o make[1]: Leaving directory '/home/cpb/hello-autotools' [hello-autotools]$ ./hello-autotools Hello from cpb-laptop (built with autotools) [hello-autotools]$
Nous pouvons également appeler «configure
» en
lui indiquant avec son option «--host
» le
préfixe à ajouter devant les noms des outils de la chaîne de
compilation. L’option «--host
» n’est pas très
judicieusement choisie, elle prête à confusion car dans l'univers des
systèmes embarqués, on appelle généralement «hôte» le poste
de développement (souvent un PC). Avec la commande
configure
, il faut comprendre «hôte» comme
«machine qui hébergera l’exécutable final».
Il faut que configure
puisse appeler les commandes de
cross-compilation, aussi devons nous d’abord appeler le script
d’initialisation de l’environnement.
[hello-autotools]$ make clean test -z "hello-autotools" || rm -f hello-autotools rm -f *.o [hello-autotools]$ source ~/sdk/yocto-lab/environment-setup-cortexa15t2hf-neon-poky-linux-gnueabi [hello-autotools]$
Puis nous appelons «configure
» Pour connaître
le préfixe à transmettre, on peut utiliser le contenu de la variable
CROSS_COMPILE
.
[hello-autotools]$ ./configure --host=$CROSS_COMPILE configure: loading site script /home/cpb/sdk/yocto-lab/site-config-cortexa15t2hf-neon-poky-linux-gnueabi checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for arm-poky-linux-gnueabi--strip... arm-poky-linux-gnueabi-strip checking for a thread-safe mkdir -p... /usr/bin/mkdir -p checking for gawk... gawk checking whether make sets $(MAKE)... yes checking whether make supports nested variables... yes [...]
Le reste de la compilation est identique à la précédente :
[hello-autotools]$ make make all-am make[1]: Entering directory '/home/cpb/hello-autotools' arm-poky-linux-gnueabi-gcc -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a15 -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 --sysroot=/home/cpb/sdk/yocto-lab/sysroots/cortexa15t2hf-neon-poky-linux-gnueabi -DHAVE_CONFIG_H -I. -O2 -pipe -g -feliminate-unused-debug-types -MT hello-autotools.o -MD -MP -MF .deps/hello-autotools.Tpo -c -o hello-autotools.o hello-autotools.c mv -f .deps/hello-autotools.Tpo .deps/hello-autotools.Po arm-poky-linux-gnueabi-gcc -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a15 -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 --sysroot=/home/cpb/sdk/yocto-lab/sysroots/cortexa15t2hf-neon-poky-linux-gnueabi -O2 -pipe -g -feliminate-unused-debug-types -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -Wl,-z,relro,-z,now -o hello-autotools hello-autotools.o make[1]: Leaving directory '/home/cpb/hello-autotools' [hello-autotools]$
Il est possible également de cross-compiler automatiquement un projet utilisant l’outil CMake. Celui est également employé pour la compilation de nombreux projets libres. Voici un exemple de projet avec CMake :
[~]$ wget https://www.logilin.fr/files/yocto-lab/hello-cmake-1.0.tar.bz2 [...] hello-cmake-1.0.tar.bz2 100%[===================>] 695 --.-KB/s ds 0s [~]$ tar xf hello-cmake-1.0.tar.bz2 [~]$ cd hello-cmake/ [hello-cmake]$ ls CMakeLists.txt hello-cmake.c [hello-cmake]$
Il nous suffit de «sourcer» le script d’initialisation de
l’environnement et d'appeler «cmake .
»
(ne pas oublier le point) puis make
pour que la compilation soit automatiquement produite pour la cible
embarquée.
[hello-cmake]$ source ~/sdk/yocto-lab/environment-setup-cortexa15t2hf-neon-poky-linux-gnueabi [hello-cmake]$ cmake . -- The C compiler identification is GNU 13.3.0 -- The CXX compiler identification is GNU 13.3.0 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /home/cpb/sdk/yocto-lab/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /home/cpb/sdk/yocto-lab/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-g++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done (0.3s) -- Generating done (0.0s) -- Build files have been written to: /home/cpb/hello-cmake [hello-cmake]$ make [ 50%] Building C object CMakeFiles/hello-cmake.dir/hello-cmake.c.o [100%] Linking C executable hello-cmake [100%] Built target hello-cmake [hello-cmake]$ ls CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt hello-cmake hello-cmake.c Makefile [hello-cmake]$ file hello-cmake hello-cmake: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=b520e4f1577e3ba53196da06801f9318f6742c67, for GNU/Linux 5.15.0, with debug_info, not stripped [hello-cmake]$
Nous avons vu dans cette séquence comment récupérer la toolchain
de Yocto et compiler une application de manière indépendante de
bitbake
. Nous avons compilé du code en appelant
directement le cross-compiler, en utilisant un
Makefile
écrit spécifiquement, en employant les
Autotools et CMake.
Naturellement, dans un cadre de développement applicatif industriel on
fait rarement appel directement au compilateur ou à make
,
on passe plutôt par l'intermédiaire d'un Environnement de
Développement Intégré comme Eclipse, Visual Studio Code,
Code::Blocks, Netbeans, Geany, etc.
Le principe est néanmoins identique à ce qu'on a vu ici, il suffira de
configurer l'environnement de développement pour qu'il accède à la
toolchain exportée par Yocto.
L’étape suivante dans cette progression va être d’incorporer directement notre code métier dans la production de l’image Yocto en écrivant notre propre recette.
Si vous préférez une session de cours interactif, en mode présentiel ou distanciel, n'hésitez pas à vous inscrire à mes formations "Développeur Linux embarqué avec Yocto Project" ou "Yocto Project avancé" .
Ce document est placé sous licence Creative Commons CC BY-NC. Vous pouvez copier son contenu et le réemployer à votre gré pour une utilisation non-commerciale. Vous devez en outre mentionner sa provenance.
Le nom Yocto Project est une marque déposée par la Linux Foundation. Le présent document n'est en aucune façon approuvé par Yocto Project ou la Linux Foundation.