diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8abb14c93e..d8aa3b9a84 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -57,6 +57,10 @@ jobs: # local.conf uses IB_BOOT_CHAIN="full" (ATF + OP-TEE + AVZ); AVZ is # fetched from a local dev path, so "full" cannot build in CI. echo "IB_BOOT_CHAIN = \"uboot\"" >> build/conf/local.conf + # CI only builds + deploys the BSP; it never runs the emulator, so + # skip the (multi-minute) QEMU compile that build.sh bsp-so3 would + # otherwise bootstrap on the virt platforms. + echo "IB_BUILD_QEMU = \"0\"" >> build/conf/local.conf . ./env.sh build.sh bsp-so3 # Create the (empty) SD-card image — privileged losetup/mkfs/parted — diff --git a/build/conf/local.conf b/build/conf/local.conf index 8b82911707..10fbe96d3a 100644 --- a/build/conf/local.conf +++ b/build/conf/local.conf @@ -9,6 +9,13 @@ IB_PLATFORM ?= "virt64" # IB_PLATFORM ?= "rpi4_64" # IB_PLATFORM ?= "verdin-imx8mp" +# On the QEMU-emulated platforms (virt32/virt64) a full BSP build +# (build.sh bsp-so3 / bsp-linux) also builds the QEMU emulator when its binary +# is still missing, so a fresh tree is runnable (st.sh) without a separate +# `build.sh qemu`. Set to "0" to skip that (e.g. CI that only builds+deploys and +# never runs the emulator). Ignored on hardware platforms (verdin, rpi4). +IB_BUILD_QEMU ?= "1" + # ============================================================================ # SO3 # ============================================================================ diff --git a/build/meta/classes/base.bbclass b/build/meta/classes/base.bbclass index fc1d65e847..9602a7d6a1 100644 --- a/build/meta/classes/base.bbclass +++ b/build/meta/classes/base.bbclass @@ -205,9 +205,10 @@ do_attach_infrabase () { if [ -d "${IB_TARGET}" ] && [ -f "$ib_manifest" ] && [ "${IB_FORCE_ATTACH}" != "1" ]; then ib_dirty=$(cd "${IB_TARGET}" && LC_ALL=C sha256sum -c --quiet "$ib_manifest" 2>/dev/null | sed -n 's/: FAILED.*$//p') if [ -n "$ib_dirty" ]; then - bbwarn "Local modifications detected in ${IB_TARGET}, not captured in the ${PN} patch set:" + echo "WARNING: Local modifications detected in ${IB_TARGET}, not captured in the ${PN} patch set:" >&2 echo "$ib_dirty" | sed 's|^\./| |' >&2 - bbfatal "Refusing to re-attach ${PN} (would overwrite the files above). Run 'bitbake ${PN} -c updiff' to fold them into the patch set, or set IB_FORCE_ATTACH=1 to discard them and re-attach (prior tree is kept in ${IB_TARGET}.back)." + echo "ERROR: Refusing to re-attach ${PN} (would overwrite the files above). Run 'bitbake ${PN} -c updiff' to fold them into the patch set, or set IB_FORCE_ATTACH=1 to discard them and re-attach (prior tree is kept in ${IB_TARGET}.back)." >&2 + exit 1 fi fi diff --git a/doc/source/user_guide.rst b/doc/source/user_guide.rst index e62eb2c43b..4fa697a2d2 100644 --- a/doc/source/user_guide.rst +++ b/doc/source/user_guide.rst @@ -64,6 +64,14 @@ the FIT image): build.sh bsp-so3 +On the emulated platforms (``virt32``/``virt64``) this also builds the patched +QEMU the first time (when ``qemu/build/qemu-system-*`` is still missing), so the +tree is runnable at step 6 without a separate ``build.sh qemu``. Once built, QEMU +is left alone on later BSP builds; set ``IB_BUILD_QEMU = "0"`` in +``build/conf/local.conf`` to opt out (e.g. a build-only CI that never runs the +emulator). Rebuilding QEMU after editing its sources stays the explicit +``build.sh -x qemu`` (see :ref:`build_system`). + **4. Create the SD-card image.** ``build.sh bsp-so3`` only *compiles* — the empty SD-card image (``filesystem/sdcard.img.``) is produced by the separate, privileged ``filesystem`` recipe (``losetup``/``mkfs``/``parted``, escalated with diff --git a/docker/Dockerfile.lvperf_32b b/docker/Dockerfile.lvperf_32b index 4c305ea19e..d619d344e4 100644 --- a/docker/Dockerfile.lvperf_32b +++ b/docker/Dockerfile.lvperf_32b @@ -30,9 +30,10 @@ RUN { \ echo 'EXTRA_OVERRIDES .= ":lvgl"'; \ } >> build/conf/local.conf -# Non-privileged: build the emulator + the full BSP (compile only; the -# privileged rootfs loop-mount is deferred to deploy.sh at run time). -RUN bash -c 'set -e; . ./env.sh; build.sh -x qemu; build.sh bsp-so3' +# Non-privileged: build the full BSP (compile only; the privileged rootfs +# loop-mount is deferred to deploy.sh at run time). On virt32 the BSP build +# also pulls in the emulator (meta-qemu) automatically, as its binary is absent. +RUN bash -c 'set -e; . ./env.sh; build.sh bsp-so3' RUN printf '#!/bin/sh\n' > install_dependencies.sh && chmod +x install_dependencies.sh diff --git a/docker/Dockerfile.lvperf_64b b/docker/Dockerfile.lvperf_64b index cfac8723f9..c4da4159f5 100644 --- a/docker/Dockerfile.lvperf_64b +++ b/docker/Dockerfile.lvperf_64b @@ -43,11 +43,12 @@ RUN { \ echo 'EXTRA_OVERRIDES .= ":lvgl"'; \ } >> build/conf/local.conf -# Build everything non-privileged: the emulator (meta-qemu) plus the full BSP. +# Build everything non-privileged: the full BSP, which on virt64 also pulls in +# the emulator (meta-qemu) automatically since its binary is absent here. # `build.sh bsp-so3` is privilege-free — it only compiles (usr, u-boot, the -# kernel, the MUSL toolchain) and creates an empty rootfs.fat; the privileged -# rootfs loop-mount happens later, in deploy.sh. -RUN bash -c 'set -e; . ./env.sh; build.sh -x qemu; build.sh bsp-so3' +# kernel, the MUSL toolchain, qemu) and creates an empty rootfs.fat; the +# privileged rootfs loop-mount happens later, in deploy.sh. +RUN bash -c 'set -e; . ./env.sh; build.sh bsp-so3' # Hook to add extra dependencies at run time without rebuilding the image. RUN printf '#!/bin/sh\n' > install_dependencies.sh && chmod +x install_dependencies.sh diff --git a/docker/README.md b/docker/README.md index f6b70e5fc6..705c544d5e 100644 --- a/docker/README.md +++ b/docker/README.md @@ -47,13 +47,14 @@ docker run -it --privileged --network=host -v /dev:/dev so3-lvperf64b # or so3 ## Technical Details -- **At image-build time** (non-privileged), Infrabase builds the emulator and the - full BSP. `build.sh bsp-so3` is privilege-free: it only compiles (the MUSL - toolchain via `meta-toolchain`, the kernel, the user space, U-Boot) and creates - an empty `rootfs.fat`. The privileged rootfs loop-mount is deferred to - `deploy.sh`. +- **At image-build time** (non-privileged), Infrabase builds the full BSP. On the + virt platforms `build.sh bsp-so3` also builds the emulator (`meta-qemu`) + automatically when its binary is still missing, so no separate `build.sh qemu` + step is needed. It is privilege-free: it only compiles (the MUSL toolchain via + `meta-toolchain`, the kernel, the user space, U-Boot, QEMU) and creates an empty + `rootfs.fat`. The privileged rootfs loop-mount is deferred to `deploy.sh`. ``` - build.sh -x qemu && build.sh bsp-so3 + build.sh bsp-so3 ``` - **At container-run time** (privileged), the entrypoint rebuilds the user space (picking up a mounted LVGL), creates+formats the SD-card image (`build.sh -x filesystem` — diff --git a/scripts/build.sh b/scripts/build.sh index 777eae7f4a..a32aaa5385 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -43,7 +43,10 @@ pr_help() printf "$progname uboot Build u-boot\n" printf "$progname -x usr-so3 Build the SO3 user space\n" printf "$progname bsp-so3 Build the full SO3 BSP\n" - printf "$progname -v -c bsp-so3 Clean and rebuild the BSP, verbose\n" + printf "$progname -v -c bsp-so3 Clean and rebuild the BSP, verbose\n\n" + printf "On virt32/virt64, a BSP build (bsp-so3/bsp-linux) also builds QEMU when its\n" + printf "binary is still missing, so the tree is runnable with st.sh right away.\n" + printf "Set IB_BUILD_QEMU=\"0\" in build/conf/local.conf to skip that.\n" } if test $# -eq 0 @@ -153,8 +156,52 @@ then bitbake $recipename -c clean $IB_BB_OPTS fi +# Read the last uncommented assignment of a variable from local.conf. Handles +# `VAR = "x"`, `VAR ?= "x"`, `VAR := "x"`; a later line (e.g. a CI append) wins. +localconf_get() +{ + grep -E "^[[:space:]]*$1[[:space:]]*[?:]?=" build/conf/local.conf 2>/dev/null \ + | tail -1 | awk -F'"' '{print $2}' +} + +# On the QEMU-emulated platforms (virt32/virt64), a full BSP build should yield +# a runnable emulator without a separate `build.sh qemu` step. Build QEMU here +# when its binary is still missing — a bootstrap only: an already-built emulator +# is left untouched, so the inner build loop pays nothing and the qemu-hacking +# loop stays the explicit `build.sh -x qemu`. Hardware platforms (verdin, rpi4) +# never run under QEMU, so they are skipped. Opt out with IB_BUILD_QEMU="0" +# (e.g. CI that only builds+deploys and never runs the emulator). +maybe_bootstrap_qemu() +{ + case "$1" in + bsp-so3|bsp-linux) ;; + *) return 0 ;; + esac + + if test "$(localconf_get IB_BUILD_QEMU)" = "0" + then + return 0 + fi + + case "$(localconf_get IB_PLATFORM)" in + virt64) _qbin="qemu-system-aarch64" ;; + virt32) _qbin="qemu-system-arm" ;; + *) return 0 ;; + esac + + if test ! -x "$IB_ROOT_DIR/qemu/build/$_qbin" + then + printf "\n[infrabase] %s: the QEMU emulator (%s) is not built yet — building it first.\n" \ + "$1" "$_qbin" + printf " (set IB_BUILD_QEMU=\"0\" in build/conf/local.conf to skip this.)\n\n" + bitbake qemu $IB_BB_OPTS || exit 1 + fi +} + if test $dobuild -eq 1 then + maybe_bootstrap_qemu "$recipename" + if test $rootprivs -eq 1 then printf "\n *** NOTE: *** '$recipename' invokes privileged tools\n"