diff --git a/.emb/base.emb.yaml b/.emb/base.emb.yaml new file mode 100644 index 00000000..e18b3d70 --- /dev/null +++ b/.emb/base.emb.yaml @@ -0,0 +1,53 @@ +# Shared base for the ivi-homescreen board manifests in this .emb/ directory. +# +# emb (emb_cli) auto-discovers `.emb/` when you run `emb cross` against the +# project root and deep-merges each .emb.yaml over this base. Each board +# file's target name is its filename (e.g. zero3.emb.yaml -> `--target zero3`), +# or a `cross.targets` key. Build from the repo root (the directory that holds +# CMakeLists.txt), which is what emb uses as the CMake source: +# +# emb cross . --list-targets +# emb cross . --target zero3 --build --backend software \ +# --app ../micro_cluster --mode release --deploy radxa@radxa-zero3.lan +# emb cross . --build # native host build of every backend below +# +# `base.emb.yaml` is the reserved base filename and is never itself a target. +id: ivi-homescreen +type: app +supported_archs: [arm64, x86_64] +supported_host_types: [fedora, ubuntu] + +cross: + # `provider` is required only to parse this block; it is ignored for the + # native (`--target local`, the default) build, which uses the host toolchain. + # Every board target overrides it with its own provider. + provider: arm-gnu + defines: + DISABLE_PLUGINS: 'ON' # shared by the native build and the boards + # Native host backend matrix: `emb cross . --build` (no --target) compiles + # every backend with the host toolchain — the dev compile smoke-test. A board + # target declares its own cross.backends, which REPLACES this set (it does not + # union), so a board never inherits these host-only entries. + backends: + wayland-egl: + BUILD_BACKEND_WAYLAND_EGL: 'ON' + BUILD_BACKEND_WAYLAND_VULKAN: 'OFF' + wayland-vulkan: + BUILD_BACKEND_WAYLAND_EGL: 'OFF' + BUILD_BACKEND_WAYLAND_VULKAN: 'ON' + drm-kms-egl: + BUILD_BACKEND_DRM_KMS_EGL: 'ON' + BUILD_BACKEND_WAYLAND_EGL: 'OFF' + BUILD_BACKEND_WAYLAND_VULKAN: 'OFF' + drm-kms-vulkan: + BUILD_BACKEND_DRM_KMS_VULKAN: 'ON' + BUILD_BACKEND_WAYLAND_EGL: 'OFF' + BUILD_BACKEND_WAYLAND_VULKAN: 'OFF' + software: + BUILD_BACKEND_SOFTWARE: 'ON' + BUILD_BACKEND_WAYLAND_EGL: 'OFF' + BUILD_BACKEND_WAYLAND_VULKAN: 'OFF' + headless-egl: + BUILD_BACKEND_HEADLESS_EGL: 'ON' + BUILD_BACKEND_WAYLAND_EGL: 'OFF' + BUILD_BACKEND_WAYLAND_VULKAN: 'OFF' diff --git a/.emb/raspberry-pi.emb.yaml b/.emb/raspberry-pi.emb.yaml new file mode 100644 index 00000000..5dd9aa5d --- /dev/null +++ b/.emb/raspberry-pi.emb.yaml @@ -0,0 +1,130 @@ +# ivi-homescreen on Raspberry Pi (PiOS aarch64) — the project layer. +# +# Hardware/OS facts (toolchain, sysroot image, partition, cpu tuning, base GUI +# stack) come from emb's shipped board library (boards/raspberry-pi.emb.yaml); +# each target `extends` a board and overlays this embedder's backends, augment, +# and plugin packages. Driven by .github/workflows/pios.yml: +# +# emb cross raspberry-pi.emb.yaml --list-targets +# emb cross raspberry-pi.emb.yaml --target rpi5-bookworm --publish --image +# emb cross raspberry-pi.emb.yaml --target rpi5-bookworm --build --backend drm-kms-egl -w /emb +# +# Backends: rpi5 builds all five (incl. drm-kms-vulkan); rpi4 and zero-2w build +# the four without it. Plugins on (PLUGINS_DIR=../ivi-homescreen-plugins/plugins). +# bookworm cross-builds libdisplay-info 0.2.0 (ships 0.1.1; drm-cxx needs >=0.2.0) +# and omits apt libdisplay-info-dev so the static .a isn't shadowed; trixie ships +# 0.2.0 and adds it. Vulkan headers are vendored, so neither OS stages them. +id: ivi-homescreen +type: app +supported_archs: [arm64] +supported_host_types: [ubuntu, fedora] + +build: + app_path: . + archs: [arm64] + modes: [release] + output: bundles + +cross: + defines: + BUILD_BACKEND_HEADLESS_EGL: 'OFF' + DISABLE_PLUGINS: 'OFF' + PLUGINS_DIR: '../ivi-homescreen-plugins/plugins' + + package: + name: ivi-homescreen + version: 1.0.0 + maintainer: "Joel Winarske " + description: "IVI Flutter Shell, cross-built by emb" + section: utils + bin: shell/homescreen + install_dir: /usr/bin + + targets: + # -- Raspberry Pi 5 (Cortex-A76) — all five backends ----------------- + rpi5-bookworm: + extends: rpi5-bookworm + sysroot: + dev_packages: &proj_packages_bookworm + - libcamera-dev + - libcurl4-openssl-dev + - libgstreamer1.0-dev + - libgstreamer-plugins-base1.0-dev + - libjpeg-dev + - libpipewire-0.3-dev + - libsecret-1-dev + - libxml2-dev + augment: &augment_bookworm + - pkg: libdisplay-info + min: "0.2.0" + url: https://gitlab.freedesktop.org/emersion/libdisplay-info/-/archive/0.2.0/libdisplay-info-0.2.0.tar.gz + build: meson + static: true + backends: &backends_rpi5 + wayland-egl: &be_wayland_egl + BUILD_BACKEND_WAYLAND_EGL: 'ON' + BUILD_BACKEND_WAYLAND_VULKAN: 'OFF' + BUILD_BACKEND_DRM_KMS_EGL: 'OFF' + BUILD_BACKEND_SOFTWARE: 'OFF' + wayland-vulkan: &be_wayland_vulkan + BUILD_BACKEND_WAYLAND_EGL: 'OFF' + BUILD_BACKEND_WAYLAND_VULKAN: 'ON' + BUILD_BACKEND_DRM_KMS_EGL: 'OFF' + BUILD_BACKEND_SOFTWARE: 'OFF' + drm-kms-egl: &be_drm_kms_egl + BUILD_BACKEND_WAYLAND_EGL: 'OFF' + BUILD_BACKEND_WAYLAND_VULKAN: 'OFF' + BUILD_BACKEND_DRM_KMS_EGL: 'ON' + BUILD_BACKEND_SOFTWARE: 'OFF' + drm-kms-vulkan: + BUILD_BACKEND_WAYLAND_EGL: 'OFF' + BUILD_BACKEND_WAYLAND_VULKAN: 'OFF' + BUILD_BACKEND_DRM_KMS_EGL: 'OFF' + BUILD_BACKEND_DRM_KMS_VULKAN: 'ON' + BUILD_BACKEND_SOFTWARE: 'OFF' + BUILD_COMPOSITOR: 'ON' + software: &be_software + BUILD_BACKEND_WAYLAND_EGL: 'OFF' + BUILD_BACKEND_WAYLAND_VULKAN: 'OFF' + BUILD_BACKEND_DRM_KMS_EGL: 'OFF' + BUILD_BACKEND_SOFTWARE: 'ON' + rpi5-trixie: + extends: rpi5-trixie + sysroot: + dev_packages: &proj_packages_trixie + - libcamera-dev + - libcurl4-openssl-dev + - libgstreamer1.0-dev + - libgstreamer-plugins-base1.0-dev + - libjpeg-dev + - libpipewire-0.3-dev + - libsecret-1-dev + - libxml2-dev + - libdisplay-info-dev + backends: *backends_rpi5 + + # -- Raspberry Pi 4 (Cortex-A72) — four backends -------------------- + rpi4-bookworm: + extends: rpi4-bookworm + sysroot: {dev_packages: *proj_packages_bookworm} + augment: *augment_bookworm + backends: &backends_four + wayland-egl: *be_wayland_egl + wayland-vulkan: *be_wayland_vulkan + drm-kms-egl: *be_drm_kms_egl + software: *be_software + rpi4-trixie: + extends: rpi4-trixie + sysroot: {dev_packages: *proj_packages_trixie} + backends: *backends_four + + # -- Raspberry Pi Zero 2 W (Cortex-A53) — four backends ------------- + rpi-zero-2w-bookworm: + extends: rpi-zero-2w-bookworm + sysroot: {dev_packages: *proj_packages_bookworm} + augment: *augment_bookworm + backends: *backends_four + rpi-zero-2w-trixie: + extends: rpi-zero-2w-trixie + sysroot: {dev_packages: *proj_packages_trixie} + backends: *backends_four diff --git a/.github/workflows/pios.yml b/.github/workflows/pios.yml index a7678f95..574de336 100644 --- a/.github/workflows/pios.yml +++ b/.github/workflows/pios.yml @@ -1,14 +1,19 @@ --- -# Cross-compiled PiOS (aarch64) artifacts via scripts/build_pi.sh. +# Cross-compiled PiOS (aarch64) artifacts via emb + a prebuilt toolchain image. # -# Runs on x86_64 GitHub runners on purpose: the pinned ARM toolchains link -# against the matching PiOS glibc only when hosted on x86_64 (bookworm's -# GCC 12 has no aarch64-hosted build, and the aarch64-hosted GCC 14/15 link -# against glibc >= 2.38, which bookworm's 2.36 can't satisfy). +# Two phases: +# publish- (per PiOS variant) — emb resolves the toolchain + sysroot and +# publishes a content-addressed OCI image to GHCR. The emb cross +# sandbox is cached, and `emb cross --publish` skips the build +# when the image (keyed by the manifest's sysroot_key) already +# exists, so this is a near-no-op once warm. +# build-... (per board x os x backend) — runs INSIDE the published image, +# where `emb cross --build -w /emb` is a pure cache hit on the +# baked toolchain + sysroot. No per-run toolchain/sysroot fetch. # -# A per-PiOS "prep" job warms the cache (toolchain + sysroot + engine, and -# the from-source libdisplay-info on bookworm) once; the build matrix then -# fans out per backend, restoring that cache and compiling a single backend. +# Runs on x86_64 runners: the pinned ARM toolchains cross-compile aarch64 (no +# emulation). Hardware facts live in emb's board library; this repo's +# raspberry-pi.emb.yaml `extends` it with ivi-homescreen's backends + plugins. name: pios on: @@ -23,28 +28,23 @@ concurrency: cancel-in-progress: true env: - # Everything build_pi.sh downloads/derives lives here so one cache covers - # toolchain, sysroot, engine SDK, and the local libdisplay-info build. - IVI_XC_ROOT: ${{ github.workspace }}/.ivi-xc + EMB_REPO: https://github.com/toyota-connected/emb_cli.git + IMAGE: ghcr.io/${{ github.repository_owner }}/emb-cross-aarch64-none-linux-gnu + # emb cross sandbox (toolchain + sysroot) for the publish phase — cached. + EMB_WS: ${{ github.workspace }}/.emb-ws jobs: - prep: + publish: if: ${{ github.server_url == 'https://github.com' }} runs-on: ubuntu-24.04 permissions: contents: read + packages: write strategy: fail-fast: false matrix: - include: - - pios: trixie - args: "" - - pios: bookworm - # bookworm ships an older libdisplay-info (0.1.1) and Vulkan SDK - # (VK_HEADER_VERSION 239); cross-build/overlay newer ones so - # drm-kms-egl and wayland-vulkan both build. - args: "--with-local-display-info --with-local-vulkan-headers" - name: prep-${{ matrix.pios }} + pios: [bookworm, trixie] + name: publish-${{ matrix.pios }} steps: - name: Checkout ivi-homescreen uses: actions/checkout@v5 @@ -52,56 +52,65 @@ jobs: path: ivi-homescreen submodules: recursive - - name: Checkout ivi-homescreen-plugins (sibling) - uses: actions/checkout@v5 - with: - repository: toyota-connected/ivi-homescreen-plugins - path: ivi-homescreen-plugins - submodules: recursive - - - name: Install host build tools + - name: Install emb resolve host tools run: | sudo apt-get update - sudo apt-get -y install --no-install-recommends \ - curl xz-utils tar fdisk rsync cmake pkg-config \ - qemu-user-static meson ninja-build libwayland-bin + sudo apt-get install -y --no-install-recommends \ + tar xz-utils rsync curl ca-certificates - - name: Cache cross sandbox (toolchain + sysroot + engine) + - name: Fetch emb + run: git clone --depth 1 "$EMB_REPO" emb_cli + + - name: Cache cross sandbox (toolchain + sysroot) uses: actions/cache@v5 with: - path: ${{ env.IVI_XC_ROOT }} - key: xc-${{ matrix.pios }}-${{ hashFiles('ivi-homescreen/scripts/build_pi.sh') }} + path: ${{ env.EMB_WS }} + key: emb-xc-${{ matrix.pios }}-${{ hashFiles('ivi-homescreen/.emb/base.emb.yaml', 'ivi-homescreen/.emb/raspberry-pi.emb.yaml', 'emb_cli/boards/raspberry-pi.emb.yaml') }} restore-keys: | - xc-${{ matrix.pios }}- + emb-xc-${{ matrix.pios }}- - - name: Prepare (fetch toolchain, sysroot, engine; build libdisplay-info) + - name: Log in to GHCR + run: | + echo "${{ secrets.GITHUB_TOKEN }}" \ + | docker login ghcr.io -u "${{ github.actor }}" --password-stdin + + # rpi5- is the canonical publish target: the sysroot (and thus the + # image) is model-independent, so one image per OS serves rpi4/zero-2w + # too. --tag is the stable alias the build matrix consumes; the + # immutable sysroot_key tag is always pushed + skip-checked. + - name: Publish toolchain image (${{ matrix.pios }}) working-directory: ivi-homescreen run: | - ./scripts/build_pi.sh --pios ${{ matrix.pios }} \ - --backend all ${{ matrix.args }} --prepare-only + eval "$(../emb_cli/bootstrap.sh --shellenv)" + emb --version + emb cross . \ + --target "rpi5-${{ matrix.pios }}" \ + --publish --image "$IMAGE" --tag "${{ matrix.pios }}" \ + -w "$EMB_WS" build: - needs: prep + needs: publish if: ${{ github.server_url == 'https://github.com' }} runs-on: ubuntu-24.04 permissions: contents: read + packages: read + container: + image: ghcr.io/${{ github.repository_owner }}/emb-cross-aarch64-none-linux-gnu:${{ matrix.pios }} + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} strategy: fail-fast: false matrix: - include: - # trixie ships libdisplay-info >= 0.2.0, so all four backends build - # without the local libdisplay-info workaround. - - { pios: trixie, backend: wayland-egl, args: "" } - - { pios: trixie, backend: wayland-vulkan, args: "" } - - { pios: trixie, backend: drm-kms-egl, args: "" } - - { pios: trixie, backend: software, args: "" } - # bookworm: drm-kms-egl needs the locally-built libdisplay-info. - - { pios: bookworm, backend: wayland-egl, args: "" } - - { pios: bookworm, backend: wayland-vulkan, args: "--with-local-vulkan-headers" } - - { pios: bookworm, backend: drm-kms-egl, args: "--with-local-display-info" } - - { pios: bookworm, backend: software, args: "" } - name: build-${{ matrix.pios }}-${{ matrix.backend }} + pios: [bookworm, trixie] + board: [rpi5, rpi4, rpi-zero-2w] + backend: [wayland-egl, wayland-vulkan, drm-kms-egl, drm-kms-vulkan, software] + # drm-kms-vulkan is rpi5-only. + exclude: + - { board: rpi4, backend: drm-kms-vulkan } + - { board: rpi-zero-2w, backend: drm-kms-vulkan } + name: build-${{ matrix.board }}-${{ matrix.pios }}-${{ matrix.backend }} steps: - name: Checkout ivi-homescreen uses: actions/checkout@v5 @@ -116,30 +125,40 @@ jobs: path: ivi-homescreen-plugins submodules: recursive - - name: Install host build tools - run: | - sudo apt-get update - sudo apt-get -y install --no-install-recommends \ - curl xz-utils tar fdisk rsync cmake pkg-config \ - qemu-user-static meson ninja-build libwayland-bin + - name: Fetch emb + run: git clone --depth 1 "$EMB_REPO" emb_cli - - name: Restore cross sandbox - uses: actions/cache@v5 - with: - path: ${{ env.IVI_XC_ROOT }} - key: xc-${{ matrix.pios }}-${{ hashFiles('ivi-homescreen/scripts/build_pi.sh') }} - restore-keys: | - xc-${{ matrix.pios }}- - - - name: Build + # The image bakes the toolchain + sysroot at /emb, so -w /emb resolves as + # a pure cache hit (no download/extract). Host build tools (cmake, ninja, + # meson, wayland-scanner) are baked too; only the augment libs rebuild. + - name: Build ${{ matrix.backend }} working-directory: ivi-homescreen + # Container jobs default to dash (sh); pipefail/SECONDS need bash. + shell: bash run: | - ./scripts/build_pi.sh --pios ${{ matrix.pios }} \ - --backend ${{ matrix.backend }} ${{ matrix.args }} + set -o pipefail + eval "$(../emb_cli/bootstrap.sh --shellenv)" + emb --version + start=$SECONDS + emb cross . \ + --target "${{ matrix.board }}-${{ matrix.pios }}" \ + --build --backend "${{ matrix.backend }}" \ + --no-verify -w /emb | tee /tmp/emb-build.log + dur=$(( SECONDS - start )) + # Per-job timing summary: the cache-hit consume should resolve in + # seconds (no toolchain/sysroot fetch). emb prints resolve/augment/ + # build phase times; capture them plus the wall-clock total. + { + echo "### ${{ matrix.board }}-${{ matrix.pios }} · ${{ matrix.backend }}" + echo "" + echo "- total: ${dur}s (cache-hit consume — no toolchain/sysroot fetch)" + grep -aE "Resolved|augment +:|build +:" /tmp/emb-build.log \ + | sed -E 's/^[[:space:]]*[^A-Za-z]*/- /' || true + } >> "$GITHUB_STEP_SUMMARY" - name: Upload homescreen binary uses: actions/upload-artifact@v7 with: - name: homescreen-${{ matrix.pios }}-${{ matrix.backend }} - path: ivi-homescreen/cmake-build-xc-pi-${{ matrix.pios }}-${{ matrix.backend }}/shell/homescreen + name: homescreen-${{ matrix.board }}-${{ matrix.pios }}-${{ matrix.backend }} + path: /emb/.config/flutter_workspace/cross-build-*/build-${{ matrix.backend }}/shell/homescreen if-no-files-found: error