Recettes d’intégration — relier haw à votre toolchain
haw ne regroupe ni ne réimplémente jamais un compilateur, un générateur de config ou un émulateur. Il ne fait que déléguer au shell la commande build = / test = par dépôt que vous déclarez (avec le répertoire du dépôt comme répertoire de travail, de sorte que $PWD dans la commande est le chemin du dépôt). C’est là toute la surface d’intégration : mettez la commande de votre toolchain dans build =, et haw pilote toute la flotte — en parallèle, épinglée à haw.lock, avec un code de sortie de qualité CI.
Ainsi « intégrer haw » est le même geste unique que votre compilateur soit gcc, une image Docker ou une suite automobile sous licence à 50 k€. Cette page montre les deux :
- Recettes réellement exécutées (toolchains ouvertes : cross-compilation Docker, émulation QEMU, FreeRTOS) — avec une vraie sortie capturée.
- Schémas de câblage pour les outils propriétaires/sous licence (Vector, EB tresos, Green Hills, IAR, Tasking, Renode) — la forme exacte, honnêtement marquée non exécutée ici (nous n’avons pas les licences), afin que rien ne soit inventé.
L’idée unique :
haw build/haw testexécutentbuild =/test =par dépôt et échouent (non nul) si la commande d’un dépôt échoue. Rien danshawn’est spécifique à ARM, Docker ou QEMU. Enveloppez n’importe quelle toolchain de la même manière.
Toolchain dans un conteneur (aucune cross-toolchain hôte nécessaire)
Vous installez rarement un cross-compilateur sur la machine de chaque développeur. Placez-le dans une image Docker une fois pour toutes et référencez-le depuis build =. Les deux images utilisées ci-dessous :
# haw-arm-gcc — bare-metal ARM cross-compiler
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc-arm-none-eabi libnewlib-arm-none-eabi make ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# haw-arm-emu — same, plus the QEMU emulator for on-CI firmware runs
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc-arm-none-eabi libnewlib-arm-none-eabi make git ca-certificates qemu-system-arm \
&& rm -rf /var/lib/apt/lists/*
$ docker run --rm haw-arm-emu sh -c 'arm-none-eabi-gcc --version | head -1; qemu-system-arm --version | head -1'
arm-none-eabi-gcc (15:10.3-2021.07-4) 10.3.1 20210621 (release)
QEMU emulator version 6.2.0 (Debian 1:6.2+dfsg-2ubuntu6.31)
Recette 1 — Cross-compilation Docker (ARM Cortex-M bare-metal) ✅ exécutée
littlefs (un vrai système de fichiers tolérant aux pannes pour MCU) compilé en archive statique Cortex-M4 à l’intérieur de l’image de toolchain ; l’étape test = vérifie que l’objet produit est authentiquement ARM.
[repo.littlefs]
url = "https://github.com/littlefs-project/littlefs.git"
rev = "master"
groups = ["firmware"]
build = "docker run --rm -v \"$PWD\":/w -w /w haw-arm-gcc sh -c 'arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Os -Wall -c lfs.c lfs_util.c && arm-none-eabi-ar rcs lfs-cortexm4.a lfs.o lfs_util.o && arm-none-eabi-size lfs-cortexm4.a'"
test = "docker run --rm -v \"$PWD\":/w -w /w haw-arm-gcc sh -c 'arm-none-eabi-objdump -f lfs.o | grep -i \"architecture: arm\" && echo CONFIRMED_ARM_CORTEX_M_OBJECT'"
[stack.fw]
repos = ["littlefs"]
Vraie sortie capturée (haw build puis haw test, tous deux en sortie 0) :
$ haw build
── littlefs ──
text data bss dec hex filename
21880 0 0 21880 5578 lfs.o (ex lfs-cortexm4.a)
120 0 0 120 78 lfs_util.o (ex lfs-cortexm4.a)
build ran in 1/1 repos
$ haw test
── littlefs ──
architecture: armv7e-m, flags 0x00000011:
CONFIRMED_ARM_CORTEX_M_OBJECT
test ran in 1/1 repos
armv7e-m est l’ISA du Cortex-M4 — un authentique objet ARM bare-metal, produit par arm-none-eabi-gcc à l’intérieur de Docker, orchestré par haw, avec un haw en machine native.
Recette 2 — Exécution émulée QEMU (FreeRTOS sur Cortex-M3) ✅ exécutée
La démo QEMU officielle de FreeRTOS construite avec le FreeRTOS-Kernel, puis démarrée sur qemu-system-arm -M mps2-an385 -cpu cortex-m3. L’ordonnanceur exécute la démo blinky (une tâche + un timer logiciel alimentant une file) et imprime sur l’UART semi-hébergé ; test = cherche un marqueur vivant via grep, de sorte qu’un RTOS réellement en cours d’exécution sort en 0 et une image morte sort en 1.
[repo.freertos]
url = "https://github.com/FreeRTOS/FreeRTOS.git"
rev = "main"
groups = ["rtos"]
build = "docker run --rm -v \"$PWD\":/w -w /w haw-arm-emu make -C FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc"
test = "docker run --rm -v \"$PWD\":/w -w /w haw-arm-emu sh -c 'timeout 8 qemu-system-arm -machine mps2-an385 -cpu cortex-m3 -kernel FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc/output/RTOSDemo.out -monitor none -nographic -serial stdio -semihosting-config enable=on,target=native 2>&1 | head -40 | grep -q \"Message received from task\" && echo QEMU_FREERTOS_RUN_CONFIRMED'"
[stack.rtos]
repos = ["freertos"]
Vraie sortie capturée :
$ haw build # relie output/RTOSDemo.out
text data bss dec hex filename
23902 232 121589 145723 2393b ./output/RTOSDemo.out
build ran in 1/1 repos
$ haw test # l'ordonnanceur FreeRTOS s'exécute réellement sous QEMU
── freertos ──
Message received from task
Message received from task
... (37 au total, plus 3 "Message received from software timer") ...
QEMU_FREERTOS_RUN_CONFIRMED
test ran in 1/1 repos
Contrôle négatif vérifié : pointez le grep vers un marqueur qui n’apparaît jamais et l’étape QEMU sort en 1 — de sorte que haw test échoue réellement si le RTOS ne démarre pas, plutôt que de toujours passer.
Les submodules sont tolérants aux pannes.
haw sync --recurse-submodulesinitialise chaque submodule indépendamment et saute ceux qui sont cassés/injoignables avec un avertissement au lieu d’interrompre — important pour les gros dépôts amont commeFreeRTOS/FreeRTOSqui déclarent une vaste forêt de submodules lourds (wolfSSL, plusieurs AWS IoT SDK, …). Le noyau dont votre cible a besoin (FreeRTOS/Source) est initialisé ; un submodule qui renvoie 404 imprime simplementhaw: skipped submodule '<path>': …et la synchronisation réussit tout de même. (les transportsext/fd/filerestent strictement désactivés dans les récupérations de submodules — la garde contre la RCE est préservée.)
Remplacez QEMU par Renode en une ligne — test = "renode --console -e 'include @sim.resc; start; sleep 5; quit'" puis cherchez le log UART via grep de la même manière.
Davantage de flottes embarquées validées ✅ exécutées
Au-delà des recettes mono-dépôt de cross-compilation/QEMU ci-dessus, le manifeste examples/embedded-real/ compose cinq vrais dépôts amont embarqués/critiques pour la sûreté publics en une seule flotte et les construit tous avec un unique haw build -j4. Chaque commande de ce manifeste a été réellement exécutée et vue réussir sur un hôte clang/cmake/make :
| Dépôt | Domaine | Résultat |
|---|---|---|
| CoreMark | benchmark | construit et exécute le benchmark |
| cJSON | données | construit + ctest 19/19 |
| Monocypher | crypto | construit libmonocypher.a |
| libcanard | protocole | la vérification de compilation C11 passe |
| Mbed-TLS | sécurité | construit libmbedcrypto/tls/x509.a (nécessite les submodules) |
Vraie sortie capturée (haw test sur la flotte, sortie 0) :
── coremark ──
CoreMark 1.0 : 26021.337497 / Apple LLVM 17.0.0 (clang-1700.0.13.5) -O2 -DPERFORMANCE_RUN=1 / Heap
COREMARK_RAN
── cjson ──
100% tests passed out of 19
── monocypher ──
MONOCYPHER_LIB_OK
test ran in 3/3 repos
Mbed-TLS déclare ses framework/ et tf-psa-crypto/ comme submodules git ; haw sync --recurse-submodules les initialise (tolérant aux pannes — un submodule cassé est sauté avec un avertissement, pas fatal). Le même checkout cJSON cross-compile également en objet Cortex-M4 bare-metal via haw-arm-emu (architecture: armv7e-m), de sorte qu’une seule flotte couvre un build hôte et un build croisé. La table complète par dépôt, les prérequis et la recette croisée figurent dans le README de l’exemple.
Schémas pour toolchains sous licence / propriétaires ⚠️ non exécutées ici
Voici les formes de câblage exactes pour les outils automobiles/de sûreté commerciaux. Nous ne pouvons pas les exécuter (sous licence) — les flags suivent l’interface batch/CLI de chaque fournisseur ; adaptez-les à votre projet selon la documentation du fournisseur. L’essentiel : c’est la même délégation au shell build =.
Le modèle mental AUTOSAR par dépôt ECU : config (ARXML) → générateur fournisseur → C BSW/RTE généré → compilateur fournisseur → ELF, le tout épinglé dans haw.lock.
# EB tresos (Elektrobit) — génère le BSW depuis la config, puis compile
[repo.ecu-comfort]
url = "git@gitlab.company.com:ecu/comfort-bsw.git"
rev = "release/2.4"
groups = ["ecu", "autosar"]
build = "$TRESOS_BASE/bin/tresos_cmd.sh -p ComfortEcu generate && make -C output"
test = "make -C output test" # VectorCAST / Tessy / votre harnais MCAL
[plugins]
misra = ["pre-request"] # contrôle le code généré + manuel selon MISRA C
aspice = ["post-land"] # émet la traçabilité ASPICE lors de la finalisation du changement
# Vector MICROSAR / DaVinci Configurator Pro
build = "DVConfiguratorCmd -d PowertrainEcu.dpa --generateAll && make"
# Compilateurs (prêts à l'emploi — une chaîne chacun ; une flotte peut les mélanger)
build = "gbuild -top default.gpj" # Green Hills MULTI (ccarm)
build = "iarbuild MyProject.ewp -build Release" # IAR Embedded Workbench (iccarm)
build = "amk -f project.mk" # TASKING (cctc / carm)
build = "make CC=dcc" # Wind River Diab
# Zephyr RTOS — west pilote lui-même le build de carte + l'exécution QEMU/renode
build = "west build -b qemu_cortex_m3 samples/hello_world"
test = "west build -t run" # ou : twister
Parce que chacun n’est qu’une chaîne, un seul haw.toml peut composer un ECU GHS à côté d’un ECU IAR à côté d’une passerelle gcc, et haw build -j8 les construit tous en parallèle avec un succès/échec correct par dépôt et une sortie non nulle si l’un casse — votre porte CI. (haw peut aussi importer un west.yml Zephyr / un manifeste repo de Google : haw import --from west.yml.)
Pourquoi c’est important pour le travail réglementé
- Reproductible. Chaque dépôt de config/BSW/RTE est épinglé à un SHA exact dans
haw.lock— le code généré est auditable et identique au bit près d’une reconstruction à l’autre (l’argument pour ASPICE / ISO 26262 / DO-178C). - Orchestré.
hawexécute générer → compiler → émuler sur toute la flotte d’ECU en parallèle, avec un code de sortie CI, en utilisant vos outils sous licence sans modification. - Gouverné. Les plugins sur les phases du cycle de vie produisent les produits de travail de qualification —
misra(porte pre-request),aspice/ SBOM / provenance / signature (post-build/post-land), les bundleshaw evidence. Voir Plugins, Domains, Compliance.
Vous n’adaptez pas votre toolchain à haw. Vous mettez sa commande dans build =, et haw pilote la flotte.