Skip to content

255 migrate the so3 build system to infrabase and move to the new so3 logo#256

Merged
daniel-rossier merged 130 commits into
mainfrom
255-migrate-the-so3-build-system-to-infrabase-and-move-to-the-new-so3-logo
Jun 29, 2026
Merged

255 migrate the so3 build system to infrabase and move to the new so3 logo#256
daniel-rossier merged 130 commits into
mainfrom
255-migrate-the-so3-build-system-to-infrabase-and-move-to-the-new-so3-logo

Conversation

@daniel-rossier

Copy link
Copy Markdown
Contributor

No description provided.

Daniel Rossier added 30 commits June 12, 2026 12:14
Re-sync the build system from the edgemtech Infrabase tree (without
torizon and e1c), nest the SO3 sources under so3/ to match the Infrabase
per-OS layout, and build so3/usr-so3/rootfs-so3/avz in-tree.

- build/: Infrabase meta-layers re-synced from edgemtech; torizon, e1c
  and verdin removed; new meta-toolchain layer (musl-cross-make recipe
  building the aarch64/arm musl user-space toolchain into build/tmp)
- SO3 sources nested under so3/{so3,usr,rootfs,target}; recipe paths and
  .gitignore updated for the new layout (artifacts re-ignored)
- in-tree recipes: so3 (6.2.0), usr-so3, rootfs-so3, avz (no github
  fetch); u-boot fetched+patched (2022.04, aligned with edgemtech)
- deploy via unprivileged bitbake + sudo -n (meta-filesystem)
- bsp-so3 builds, deploys and boots to so3% standalone (virt64) and as
  an AVZ guest (virt64_avz_so3 ITS, EL2)
…system-to-infrabase-and-move-to-the-new-so3-logo
The old manual qemu/ mechanism (fetch.sh + qemu.patch) is superseded by
the meta-qemu recipe: it fetches the same QEMU 8.2.2 and applies the same
hw/arm/virt.{c,h} patches (CLCD/KMI/PS2). Verified that build.sh -x qemu
rebuilds an equivalent qemu-system-aarch64. qemu/ stays gitignored and is
regenerated on demand.
Revert the avz recipe to fetching SO3 from upstream at a pinned SRCREV
and building the hypervisor (EL2) from it, instead of the in-tree so3/
sources. AVZ is decoupled from the in-tree SO3, which is the guest/
capsule (EL1) under development. Verified: bitbake avz fetches, attaches
into avz/, configures virt64_avz_defconfig and builds avz/so3.bin.
The do_build make invocation relied on a CROSS_COMPILE inherited from the
caller's shell, which broke virt32 (arm) builds when the shell had an
aarch64 CROSS_COMPILE set (cc1: unknown value 'generic-armv7-a' for
-mtune). Pass CROSS_COMPILE=${IB_TOOLCHAIN}- explicitly so virt32 uses
arm-linux-gnueabihf- and virt64 uses aarch64-none-linux-gnu-, matching
atf.bbclass.
Drop the usr/lib/lvgl git submodule (.gitmodules removed) and go back to
the original meta-usr strategy: lvgl is fetched at build time by the
meta-usr lvgl bbappend, gated on the :lvgl OVERRIDE. usr-so3 re-enables
do_fetch/unpack/attach so the bbappend pulls lvgl into usr/lib/lvgl
(do_patch stays noexec — the slv/lvgl integration patches are already
baked into the in-tree usr/). The lvgl bbappend now mkdir's lib/lvgl
(no longer pre-created by the submodule). usr/lib/lvgl is gitignored;
meta-usr otherwise realigned with edgemtech.
The bbclass selects the current platform's target (QEMU_TARGET: arm-softmmu
for virt32, aarch64-softmmu for virt64) and, when reconfiguring, appends any
other arch already built under qemu/build so meson does not drop it. Thus
building arm-softmmu then aarch64-softmmu (or vice-versa, e.g. switching
IB_PLATFORM between so3 standalone/avz/capsule) keeps both qemu-system-*
binaries instead of wiping the previous one. do_configure is nostamp so the
accumulation re-evaluates each build.
The SO3 kernel is built in place, so switching IB_PLATFORM between
virt64 and virt32 (aarch64<->arm) leaves a stale .config and object
files behind, producing a wrong-arch kernel. Track the last built
arch in a .ib_last_arch marker and run 'make distclean' only when it
changes, keeping same-arch rebuilds incremental.
Two arch-switch bugs surfaced when building SO3 for virt32 (arm) after
virt64 (aarch64):

1. 'OVERRIDES += ":so3"' inserts a leading space, so OVERRIDES became
   "...:arm :so3" and the CPU token parsed as "arm " (trailing space).
   :<cpu> overrides such as IB_MUSL_TARGET:arm then never collapsed, so
   the user-space cmake build got a literal ${IB_MUSL_TARGET} on PATH and
   could not find arm-linux-musleabihf-gcc. Switch to OVERRIDES:append in
   all five SO3 recipes (no inserted space).

2. The usr-so3 cmake build dir caches the toolchain in CMakeCache.txt, so
   switching arch kept emitting aarch64 binaries (an aarch64 init.elf on a
   32-bit kernel -> prefetch abort at boot). Wipe so3/usr/build when the
   arch changes, tracked via a .ib_last_arch marker at the usr/ root.
Both QEMU launch scripts only handled virt64, so with IB_PLATFORM=virt32
they printed the MAC/GDB lines and exited without starting QEMU. Select
QEMU_BIN per platform (qemu-system-arm for virt32) and add a virt32 branch
booting U-Boot directly (-M virt -cpu cortex-a15 -kernel u-boot/u-boot,
sdcard.img.virt32). stg.sh keeps the virtio GPU/keyboard/mouse + SDL
window; the virt64-only guard is widened to accept virt32.
u-boot is built from the meta-uboot recipe (github 2022.04 @ pinned
SRCREV + the SO3 patch set), which fetches and attaches it, backing any
prior copy up to u-boot.back. The committed in-tree u-boot/ was therefore
obsolete and was clobbered on every build, producing a huge spurious
diff. Remove all 18k files from tracking and gitignore /u-boot/, matching
how qemu/ and avz/ are already handled.
The patch set was inherited wholesale from the edgemtech recipe and had
never been regenerated by do_updiff in this repo. It carried two classes
of cruft:

  * duplicate chains — the same source file patched twice (e.g. board.c
    in 0004 and 0077, setexpr.c in 0008/0081, the tools/boot/*.c and the
    defconfigs each appearing in two generations with ./ vs b/ labels),
    the residue of repeated append-only updiff runs across a label-format
    change;
  * build artifacts frozen as patches — hello_world.srec, autoconf.mk,
    autoconf.mk.dep, include/config/uboot.release, include/generated/*
    (dt.h, *_autogenerated.h), lib/efi_selftest/efi_miniapp_*.h.

Regenerated from scratch: diff the pristine fetch against the working
tree (do_diffcompose), drop the old numbered set, promote the staged
one-patch-per-file result (do_updiff). 64 messy patches -> 54 clean,
consolidated, git-labelled patches. e1c_boot.c is kept (compiled but
unused) per decision. Verified: a clean fetch+unpack+patch+build applies
all 54 and produces a working u-boot.

Also completed the do_diffcompose artifact exclude-list in patch.bbclass
(autoconf.mk, autoconf.mk.dep, *.srec, efi_miniapp_*.h) so future updiff
runs stay clean.
ls sets CLOEXEC via fcntl(). arm64 musl issues this as fcntl (NR 25),
which SO3 handles; arm32 (virt32) musl issues the same call as fcntl64
(NR 221), which syscall.tbl never registered -> 'unhandled syscall: 221'
warning and a silently-failing -ENOSYS. Map fcntl64 to the existing
__sys_fcntl handler so virt32 behaves like virt64.
Killing a process whose spawned thread was blocked in the kernel hit
'BUG in kernel/thread.c:105' (discard_tcb_in_pcb: WAITING 'not handled
yet'). A sleeping thread sits in __sleep() with a struct timer on its
own kernel stack, so it cannot just be freed — the pending timer would
dangle and later fire on freed memory.

Handle it cooperatively: add a tcb->killed flag; discard_tcb_in_pcb()
flags+wakes WAITING threads (instead of BUG()) and waits for them via
the existing threads_active completion, reaping them afterwards.
A woken thread resumes in __sleep(), stops its own timer, sees killed
and self-terminates with thread_exit() — entirely in kernel, never
returning to the (already-released) user pages. READY threads are still
force-freed (they must not resume into freed user space).

Verified: Ctrl-C of lvgl_demo stress (whose slv tick thread loops in
usleep) no longer panics.

Limitation: only the __sleep() wait is instrumented. A thread killed
while blocked on a futex/mutex would not yet self-terminate; that needs
the same killed-check added to those wait paths.
The 128 KB lvgl heap is too small to build lv_demo_widgets (lv_conf.h's
own note flags this), so the widget tree failed to allocate, nothing
rendered, and the main thread spun in lv_timer_handler() without
reaching a syscall boundary — making Ctrl-C undeliverable. 4 MB fits the
demo comfortably; it is BSS (zero-init) so the .elf on disk is unchanged.
A diagnostic that bypasses LVGL: opens /dev/fb, queries geometry via the
same ioctls slv uses, mmap()s the VRAM and draws colour bars + an
animated square straight into it. Lets us tell apart a broken display
pipeline (PL111 CLCD -> QEMU SDL) from an LVGL-side problem. Ctrl-C to
quit.
fb_mmap() mapped the CLCD VRAM cacheable, which is wrong for a
framebuffer: on real hardware the CPU writes linger in the data cache
and never reach the scanout buffer. Map it non-cacheable (nocache=true).
(Under QEMU/TCG it is cosmetic since the cache is not modelled, but it is
required on real targets.)
SO3 drives the PL111 CLCD + PL050 keyboard/mouse that the so3 QEMU patch
wires unconditionally into '-M virt'; it has no virtio-gpu driver, so the
virtio-gpu/keyboard/mouse devices only added a competing blank console.
More importantly the SDL backend did not present the PL111 console's
surface at all (verified: pl110 renders the framebuffer into the surface
- monitor 'screendump' shows it - yet the SDL window stayed black).
Switching to '-display gtk' shows the panel correctly (and its View menu
lists every console). Drop the virtio-gpu/keyboard/mouse devices.
Paint the colour-bar background once, then per frame only restore the
square's previous rows and redraw it, instead of memcpy-ing the whole
3 MB framebuffer every frame.
The serial IRQ delivered SIGINT to current() - whatever thread happened
to be running when the Ctrl-C key arrived. A foreground app asleep in a
syscall (e.g. usleep) is not the running thread (the idle thread is, with
pcb==NULL), so Ctrl-C was silently dropped; it only worked for CPU-busy
apps. And at the shell prompt the prompt was never reprinted.

Two parts:

1. Track the foreground console process. Add a global fg_pcb, set by
   sys_do_wait4() to the child a process blocks waiting on (the shell's
   foreground job) and restored to the waiter when it exits. The serial
   IRQ now targets fg_pcb (fallback: current()), so SIGINT reaches the
   foreground app even while it sleeps.

2. Cancel the line at the prompt instead of signalling the shell. When a
   console read is in progress (read_lock held), the IRQ sets serial_intr;
   pl011_get_byte returns ETX and console_getc discards the typed line and
   returns an empty line, so the shell's fgets returns and it reprints the
   prompt once. This avoids musl's sticky-EOF on a 0-byte read and a
   siglongjmp-through-fgets file-lock leak. Matches the driver's existing
   read_lock design comment.

Relies on the cooperative WAITING-thread teardown for the kill path.
Mirror the virt32 graphical fix onto the virt64 branch: SO3 drives the
same PL111 CLCD + PL050 (virt64.dts has clcd@08800000 / pl050 nodes), has
no virtio-gpu driver, and the SDL backend does not present the PL111
console. Switch to '-display gtk' and drop the virtio-gpu/keyboard/mouse
devices. The flash0.img AVZ-vs-U-Boot boot heuristic is unchanged.

Untested (no virt64 graphical run this session) but the framebuffer path
is identical to virt32; the kernel-side fixes (non-cacheable fb, Ctrl-C)
are arch-shared.
An interrupted task (e.g. Ctrl-C during a clean) can leave a recipe
WORKDIR that exists but lacks its temp/ subdir. bitbake then cannot
create that task's fifo and fails with
  do_clean: [Errno 2] No such file or directory: .../temp/fifo.NNNN
(hit on 'build.sh -ca bsp-so3'). Before clean/build, scan tmp/work and
remove any workdir missing temp/ (it holds nothing useful) so bitbake
recreates it cleanly.
'build.sh -ca bsp-so3' failed with
  usr-so3 do_clean: [Errno 2] No such file or directory: .../temp/fifo.NNNN

Root cause: the lvgl bbappend's shell do_clean:append ran
'rm -rf ${WORKDIR}/*', which deleted the running clean task's own temp/
(holding its fifo + run script) mid-execution, leaving an empty workdir.
The next clean then could not create its fifo there and failed.

Fix: make do_clean a Python task (usr.bbclass) plus Python do_clean:append
in the usr-so3 recipe and the lvgl bbappend. Python tasks create their
temp dir themselves and use no fifo, so they are robust when the workdir
is fresh/empty. The lvgl append no longer touches WORKDIR (bitbake owns
it); it only purges the fetched lvgl tree (in-tree usr/lib/lvgl, src/lib,
${S}/lib/lvgl). Verified: fresh clean, repeat clean, full 'bsp-so3 -c
clean', and clean->rebuild (aarch64) all succeed.
…2 entries

Remove the IB_PLATFORM:so3 override: SO3 now always builds for the main
IB_PLATFORM. That override was referenced only here and resolved via
OVERRIDES, so a value diverging from IB_PLATFORM silently built SO3 for
the wrong arch. The standalone / AVZ-guest / capsule contexts are not
distinct platforms - they differ only by IB_CONFIG:so3 / IB_TARGET_ITS:so3
(e.g. capsule = virt64_capsule_defconfig + virt64_capsule), which are
independent of the platform variable.

Also add the virt32 counterparts that were missing
(PREFERRED_VERSION_so3, IB_CONFIG:so3, IB_TARGET_ITS:so3, IB_STORAGE_MODE)
and default IB_PLATFORM to virt64.
AVZ is an EL2 hypervisor. The virt64 launcher only enabled EL2
(virtualization=on) when filesystem/flash0.img was present (ATF chain);
booting AVZ via the ITS without ATF used plain -M virt,gic-version=2
(EL1), so AVZ faulted on its first EL2 system-register write
(Synchronous Abort -> reset). Detect the selected so3 ITS from local.conf
and, when it is an avz ITS, add virtualization=on with -kernel u-boot
(virt64_defconfig is EL2-aware). Verified: AVZ now boots.

@clemdiep clemdiep left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems ok to me, I didn't find any regression on the sources.
I haven't time to test it however

Just a small comment that I want to address before approving.

Comment thread build/conf/local.conf Outdated
Daniel Rossier added 2 commits June 24, 2026 19:52
The guard tested IB_STORAGE_DEVICE == "", but a commented-out (unset)
variable is None in bitbake, not "", so it never fired — a mechanical
hard/target deploy could then write to a wrong/default device (e.g.
/dev/sda) and overwrite a host disk. Use 'not IB_STORAGE_DEVICE' (catches
None and empty) with an explicit message, and add the missing guard to the
verdin class (which formatted /dev/${device} unconditionally).
A default device on a hard deploy (e.g. /dev/sda) could overwrite a host
disk on a mechanical clean-clone deploy. Leave it unset; the do_fs_init_storage
guard now fails explicitly when 'hard' mode needs it (commit 949090c).

@clemdiep clemdiep left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good for me

Daniel Rossier and others added 18 commits June 26, 2026 11:31
The lv_perf images COPY the whole repo into /so3. do_attach_infrabase
keeps a host-specific sha256 manifest (IB_TARGET.attach.sha256) and a
.back copy of the previously attached tree next to each component dir.
These are gitignored but were not dockerignored, so COPY pulled the host
manifest into the container; the in-container attach then checked the
freshly-COPYd usr-so3 tree against that stale manifest, saw the new
shell/utility sources as local modifications, and aborted
do_attach_infrabase with exit 1.

Exclude all attach manifests and .back dirs (replacing the explicit
qemu.back/u-boot.back lines) so the container starts with no manifest and
performs a clean first attach. No tracked files match these patterns.
The QEMU virt platforms build U-Boot 2022.04 (the recipe that carries
configs/virt32_defconfig and virt64_defconfig); only verdin uses the
2024.07 port that assembles imx-boot/flash.bin. virt64 and rpi4_64 were
pinned to 2022.04 but virt32 was not, so bitbake defaulted it to the
newest recipe (2024.07). That recipe has no virt32_defconfig, and its
32-bit armv7 startup (start.S/crt0.S/lowlevel_init.S) fails to assemble
against the renamed CFG_SYS_INIT_RAM_ADDR symbols:

  arch/arm/cpu/armv7/lowlevel_init.S:32: Error: syntax error --
    `ldr sp,=(CFG_SYS_INIT_RAM_ADDR+CFG_SYS_INIT_RAM_SIZE-256)'

so the lv_perf virt32 Docker image failed at uboot do_configure/do_build.
Add the missing virt32 pin. Verified: with the pin, virt32 builds U-Boot
2022.04 and do_build succeeds through the full bitbake fetch+patch path.
The perf launcher used -icount shift=0,sleep=on,align=on. align=on paces
the guest to host wall-clock and prints "Warning: the guest is now late
by N seconds" whenever it cannot keep up, which floods the benchmark
output. Determinism for the FPS numbers comes from the icount virtual
clock and -semihosting, not from align, so switch to align=off (the
default) to drop the warnings without changing the measured results.
show_env() read the first "^IB_PLATFORM" line of local.conf (head -1),
which is the "IB_PLATFORM ?= virt64" default. The lv_perf Dockerfiles
append "IB_PLATFORM = virt32/virt64" after it, and bitbake honours the
last assignment, so a virt32 container build was mislabelled
"platform=virt64" in the banner while actually building virt32.

Read the last plain (non-:override) IB_PLATFORM assignment instead, so
the banner matches what bitbake resolves. Purely cosmetic; the build
itself already used the correct platform.
The slv port advanced lv_tick from a helper thread doing usleep(10000) +
lv_tick_inc(10), giving 10 ms tick granularity. The LVGL perf benchmark
derives render/flush/CPU time from lv_tick deltas, so any frame shorter
than 10 ms measured as 0. On virt32 every scene renders in under one
10 ms tick (and light scenes do on virt64 too), so the benchmark
reported 0 render time and a flat 25 FPS everywhere.

Replace the tick thread with lv_tick_set_cb() reading
clock_gettime(CLOCK_MONOTONIC), which SO3 backs with the ARM generic
timer (microsecond resolution). LVGL now samples real sub-millisecond
time, so render/flush times are accurate on both virt32 and virt64.
Move the per-platform FIT image sources (.its) out of so3/target into the
owning BSP layers and render them at build time:
  - SO3 / AVZ images   -> meta-bsp/recipes-bsp/so3/files/its/
  - Linux agency images -> meta-bsp/recipes-bsp/linux/files/its/

bsp_render_its (bsp.bbclass) expands the ${IB_*_PATH} / ${IB_PLATFORM}
placeholders to absolute paths, emitting each rendered .its into the
gitignored <ctx>/images/ dir. The old so3/target/*.its and the hand-rolled
mkuboot.sh are dropped.

bsp-so3 / bsp-capsules derive the AVZ guest ITB name from IB_TARGET_ITS via
IB_GUEST_SUFFIX (two-ITB e1c-boot: AVZ ITB in x0 + guest ITB in x1).
bsp.bbclass also carries the IB_RAMFS_SOURCE default used by the agency.
Reorganise the Linux/SO3 user-space sources into committed base + override
patch sets:
  - usr-linux base patches now live under recipes-usr/linux/files/
    (0100-0120); the agency apps (injector / melist / saveme / restoreme /
    shutdownme) are delivered by the :soo override, trimmed of the
    micofe-specific pieces (emiso-engine, COUI, ...).
  - LVGL / SLV patches moved out of the SO3 set into recipes-usr/lvgl/,
    applied only under the :lvgl override.
  - drop the now-duplicated / orphan patches (old so3 lvgl set, the soo
    emiso-engine series, and linux 0021-Makefile shadowed by :soo 0005).
The committed SO3 user space is now the plain base: drop slv/ and the
lvgl_* example sources and their CMake wiring. LVGL/SLV are delivered only
when the :lvgl override is selected (recipes-usr/lvgl applies its patch set
into so3/usr at build time). hello.c is kept as a minimal in-tree app.
Run the Linux agency as an AVZ guest that boots a small initramfs and
switch_root's into the real rootfs on p2 (ext4, /dev/vda2 over virtio-blk).

- IB_RAMFS_SOURCE selects what the guest ITB embeds as the boot ramfs
  (do_prepare_initrd, bsp-linux): "rootfs" (default) = the full buildroot
  rootfs.cpio (run-from-RAM); "initrd" = the static board/<plat>/initrd.cpio,
  a small busybox image whose /init mounts /dev/vda2 and switch_root's into
  it (initrd_init.sh is the readable source of that /init).
- Kernel boot logs: the e1c-boot uEnv now sets bootargs (console=ttyAMA0,
  earlycon, loglevel=8, root=/dev/ram). The guest dtb has no /chosen, so the
  cmdline must come from the U-Boot env (e1c_boot.c env_get + fdt_chosen).
- usr-linux:do_deploy bakes the agency apps INTO rootfs.cpio (a build step),
  so p2 gets them for free when rootfs-linux:do_deploy extracts the final
  cpio at deploy time (no separate media write; fixes an empty /root).
- Deploy is decoupled from the build: rootfs/usr do_deploy no longer pull
  buildroot:do_build, so deploy.sh writes the media without recompiling.
- Rebrand the agency rootfs: SOO ASCII logo + "Smart Object Oriented" /
  "Copyright (c) 2014-2026 HEIG-VD/REDS Institute", hostname soo, /etc/issue,
  and an /etc/inittab.d placeholder (silences the sysvinit 3.04 message).
build.sh / deploy.sh now take the recipe as a positional argument (-x is
kept as an optional alias); -a is removed and -l lists every recipe. A BSP
name builds/deploys the whole BSP, a component name just that recipe.

mount.sh -i / umount.sh -i extract then repack board/<plat>/initrd.cpio
under fakeroot (root ownership preserved via the saved fakeroot state),
reachable through a filesystem/p1 symlink just like the partition mounts.
The platform is auto-detected from local.conf.
Drop the -a flag from all build.sh / deploy.sh invocations in the docs and
Docker images (positional recipe now), and document that deploy consumes the
build's artefacts without recompiling (edit -> build.sh -> deploy.sh).

.gitignore: ignore the whole linux/ build tree (fetched agency kernel +
regenerated linux/usr + rendered images) — nothing under it is tracked.
The x86-qemu rootfs board (post_build/post_image scripts + overlay) is not
part of the supported platforms (virt32/virt64/rpi4_64/verdin); remove it.
Align the documentation (text + diagrams) with the migrated build system
and the agency model:
  - the agency is Linux; AVZ boots a single guest at EL1 (Linux, or a plain
    SO3 with CONFIG_SOO=n) — no more RT agency / DOMID_AGENCY_RT.
  - FIT ITS templates are rendered from the BSP layer (no so3/target).
  - build.sh / deploy.sh take the recipe as a positional argument (the
    former -a / -k / -b / -r / -f flags are gone); deploy consumes what
    build.sh produced without recompiling.
  - capsules need the Linux agency, now buildable here via the :soo override
    (meta-linux + meta-usr/soo).

Regenerated so3.drawio and the affected PNGs (modes, boot, avz, build,
exception_levels) and fixed debugging.rst (SO3 guest ELF). Sphinx builds
clean.
AVZ boots a single agency guest (Linux, or a plain SO3); there is no
real-time agency subdomain. Remove the DOMID_AGENCY_RT (domain id 1)
definition, the DOM_TO_MEMSLOT special-case that folded it onto the agency
memslot, and the stale event-channel dump for it. Domain id 1 is now
reserved. Matches the documentation.
hello.c entered the tree unformatted and failed the style.yml clang-format
check (clang-format 19): K&R brace on the function, space indentation and
stray blank lines. Reformat to the kernel .clang-format style.
Replay .github/workflows/style.yml locally before pushing: clang-format 19
over so3/so3 (excluding *.S) and so3/usr (excluding the vendored / generated
trees), on git-tracked files only — matching the CI's actions/checkout, so
generated artefacts (kconfig parser, asm-offsets.h) are not flagged.
`--fix` reformats the offending files in place.
The lv_perf images exist to run the LVGL scene benchmark, but the whole
lvgl/slv build (lib lvgl, lib slv and the lvgl_*.elf apps, including
lvgl_benchmark.elf which is the init program) is gated on the :lvgl
override. That override is off by default in local.conf (correct for the
standalone bsp-so3 build), so a freshly built lv_perf image otherwise
ships with no LVGL and no benchmark at all.

Append EXTRA_OVERRIDES .= ":lvgl" to each image's local.conf override
block so the benchmark is built and boots as init.
@daniel-rossier daniel-rossier merged commit 796b6f4 into main Jun 29, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate the so3 build system to InfraBase and move to the new SO3 logo

2 participants