Merge remote-tracking branch 'origin/v2.0' into integrate/pr182

# Conflicts:
#	shell/engine.h
#	shell/view/flutter_view.cc
#	shell/view/flutter_view.h
#	shell/wayland/display.cc
This commit is contained in:
Joel Winarske
2026-06-16 13:07:49 -07:00
146 changed files with 31532 additions and 465 deletions
@@ -0,0 +1,82 @@
---
name: Setup libdisplay-info
description: >-
Use the host's libdisplay-info when it satisfies the version requirement;
otherwise build the pinned version from source and cache the install tree.
Exports PKG_CONFIG_PATH / LD_LIBRARY_PATH so subsequent cmake + ninja steps
pick up the from-source build.
inputs:
required-version:
description: Minimum version that satisfies the build.
required: false
default: "0.2.0"
pin-version:
description: Tag built from source when the host is too old.
required: false
default: "0.2.0"
runs:
using: composite
steps:
- name: Probe system libdisplay-info
id: probe
shell: bash
run: |
set -e
sys_ver="$(pkg-config --modversion libdisplay-info 2>/dev/null || true)"
if [ -n "$sys_ver" ] && \
pkg-config --atleast-version="${{ inputs.required-version }}" libdisplay-info; then
echo "Using system libdisplay-info ${sys_ver}"
echo "from-source=false" >> "$GITHUB_OUTPUT"
else
echo "System libdisplay-info ${sys_ver:-absent} does not satisfy >= ${{ inputs.required-version }}; will build ${{ inputs.pin-version }}"
echo "from-source=true" >> "$GITHUB_OUTPUT"
echo "prefix=${RUNNER_TEMP}/libdisplay-info-install" >> "$GITHUB_OUTPUT"
fi
- name: Restore cached libdisplay-info
if: steps.probe.outputs.from-source == 'true'
id: cache
uses: actions/cache@v5
with:
path: ${{ steps.probe.outputs.prefix }}
key: libdisplay-info-${{ inputs.pin-version }}-${{ runner.os }}-${{ runner.arch }}
- name: Build libdisplay-info from source
if: steps.probe.outputs.from-source == 'true' && steps.cache.outputs.cache-hit != 'true'
shell: bash
env:
PREFIX: ${{ steps.probe.outputs.prefix }}
PIN: ${{ inputs.pin-version }}
run: |
set -e
sudo apt-get -y install meson ninja-build pkg-config
src="${RUNNER_TEMP}/libdisplay-info-src"
rm -rf "$src" "$PREFIX"
git clone --depth 1 --branch "$PIN" \
https://gitlab.freedesktop.org/emersion/libdisplay-info.git "$src"
meson setup "$src/build" "$src" \
--prefix="$PREFIX" \
--buildtype=release \
-Ddefault_library=shared
meson install -C "$src/build"
- name: Export PKG_CONFIG_PATH / LD_LIBRARY_PATH
if: steps.probe.outputs.from-source == 'true'
shell: bash
env:
PREFIX: ${{ steps.probe.outputs.prefix }}
run: |
# meson installs the .pc to <prefix>/lib/pkgconfig (no multiarch);
# the multiarch variant is added defensively for distros that move it.
for d in "$PREFIX/lib/pkgconfig" "$PREFIX/lib/x86_64-linux-gnu/pkgconfig"; do
if [ -d "$d" ]; then
echo "PKG_CONFIG_PATH=$d:${PKG_CONFIG_PATH:-}" >> "$GITHUB_ENV"
fi
done
for d in "$PREFIX/lib" "$PREFIX/lib/x86_64-linux-gnu"; do
if [ -d "$d" ]; then
echo "LD_LIBRARY_PATH=$d:${LD_LIBRARY_PATH:-}" >> "$GITHUB_ENV"
fi
done
+157
View File
@@ -0,0 +1,157 @@
---
name: drm-kms
on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches: [v2.0]
workflow_dispatch:
jobs:
build:
if: ${{ github.server_url == 'https://github.com' }}
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- compiler: gcc
cc: gcc-14
cxx: g++-14
extra_pkgs: g++-14
- compiler: clang
cc: clang-19
cxx: clang++-19
extra_pkgs: clang-19 llvm-19 lld-19 libc++-19-dev libc++abi-19-dev
name: drm-${{ matrix.compiler }}
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
- name: Install dependencies
uses: awalsh128/cache-apt-pkgs-action@v1
with:
packages: >-
ninja-build
libwayland-dev wayland-protocols libxkbcommon-dev
mesa-common-dev libegl1-mesa-dev libgles2-mesa-dev mesa-utils
libdrm-dev libgbm-dev libinput-dev libudev-dev libseat-dev
libxcursor-dev
libglib2.0-dev
${{ matrix.extra_pkgs }}
version: 1.0
- name: Setup libdisplay-info (system or from-source)
uses: ./.github/actions/setup-libdisplay-info
- name: Configure (DRM/KMS EGL + compositor)
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
run: |
cmake -GNinja \
-B ${{github.workspace}}/build \
-D CMAKE_BUILD_TYPE=Debug \
-D CMAKE_EXPORT_COMPILE_COMMANDS=ON \
-D BUILD_BACKEND_DRM_KMS_EGL=ON \
-D BUILD_BACKEND_WAYLAND_EGL=OFF \
-D BUILD_BACKEND_WAYLAND_VULKAN=OFF \
-D BUILD_COMPOSITOR=ON \
-D BUILD_NUMBER=${GITHUB_RUN_ID}
- name: Build
run: ninja -C ${{github.workspace}}/build
- name: Verify binary is DRM-enabled
run: |
strings ${{github.workspace}}/build/shell/homescreen \
| grep -q '\[DrmBackend\]'
vkms-smoke:
if: ${{ github.server_url == 'https://github.com' }}
needs: build
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
- name: Install dependencies
uses: awalsh128/cache-apt-pkgs-action@v1
with:
packages: >-
ninja-build
libwayland-dev wayland-protocols libxkbcommon-dev
mesa-common-dev libegl1-mesa-dev libgles2-mesa-dev mesa-utils
libdrm-dev libgbm-dev libinput-dev libudev-dev libseat-dev
libxcursor-dev
libglib2.0-dev
clang-19 llvm-19 lld-19 libc++-19-dev libc++abi-19-dev
version: 1.0
- name: Setup libdisplay-info (system or from-source)
uses: ./.github/actions/setup-libdisplay-info
- name: Build (clang, DRM + compositor)
env:
CC: clang-19
CXX: clang++-19
run: |
cmake -GNinja \
-B ${{github.workspace}}/build \
-D CMAKE_BUILD_TYPE=Debug \
-D BUILD_BACKEND_DRM_KMS_EGL=ON \
-D BUILD_BACKEND_WAYLAND_EGL=OFF \
-D BUILD_BACKEND_WAYLAND_VULKAN=OFF \
-D BUILD_COMPOSITOR=ON \
-D BUILD_NUMBER=${GITHUB_RUN_ID}
ninja -C ${{github.workspace}}/build
- name: Load vkms
id: vkms
run: |
# The Azure CI kernel often strips vkms. Try loading it; if
# unavailable, install linux-modules-extra as a fallback.
if ! sudo modprobe vkms 2>/dev/null; then
echo "vkms not in $(uname -r); trying linux-modules-extra"
sudo apt-get -y install "linux-modules-extra-$(uname -r)" || true
sudo modprobe vkms 2>/dev/null || true
fi
if lsmod | grep -q vkms; then
echo "available=true" >> "$GITHUB_OUTPUT"
ls /sys/class/drm/card*-Virtual-* 2>/dev/null \
|| (echo "vkms loaded but no Virtual connector" && exit 1)
else
echo "available=false" >> "$GITHUB_OUTPUT"
echo "::warning::vkms module unavailable on $(uname -r); skipping smoke test"
fi
- name: Harness pre-flight (--check)
if: steps.vkms.outputs.available == 'true'
run: |
test/drm_kms_vkms.sh --check
# A full harness run requires a Flutter bundle whose
# libflutter_engine.so version matches the one in third_party/flutter.
# When a CI-ready bundle is available, uncomment the step below.
#
# - name: Full vkms smoke test
# if: steps.vkms.outputs.available == 'true'
# env:
# HOMESCREEN: ${{github.workspace}}/build/shell/homescreen
# BUNDLE: /path/to/ci/bundle/.desktop-homescreen
# SOFTWARE_RENDER: '1'
# DURATION: '5'
# run: |
# test/drm_kms_vkms.sh
+2 -2
View File
@@ -47,7 +47,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: 'true'
@@ -80,7 +80,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: 'true'
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: 'true'
+26 -1
View File
@@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: 'true'
@@ -122,3 +122,28 @@ jobs:
name: homescreen-${{ job.check_run_id }}.x86_64.rpm.zip
path: |
build/release/_packages/homescreen-*.x86_64.rpm
crash-handler:
if: ${{ github.server_url == 'https://github.com' && github.ref != 'refs/heads/agl' && always() }}
runs-on: ubuntu-22.04
steps:
- name: Check Environment
id: check_environment
shell: bash
run: |
echo "Running on Ubuntu version: $(lsb_release -d | cut -f2)"
echo "Running on architecture: $(uname -m)"
echo "Current directory: $(pwd)"
echo "Environment variables:"
env
# Get username
echo "user=$(whoami)" >> "$GITHUB_OUTPUT"
- name: Setup workspace
uses: meta-flutter/workspace-automation/.github/actions/setup-workspace@v2.0
with:
args: --disable=rive-text --enable=sentry-native --override-repo=https://github.com/toyota-connected/ivi-homescreen.git#${{ github.event.pull_request.head.ref || github.sha }}
user: ${{ steps.check_environment.outputs.user }}
ref: v2.0
cache: false
cache-key: crash-handler-pr${{ github.event.pull_request.number }}
+145
View File
@@ -0,0 +1,145 @@
---
# Cross-compiled PiOS (aarch64) artifacts via scripts/build_pi.sh.
#
# 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).
#
# 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.
name: pios
on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches: [v2.0]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
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
jobs:
prep:
if: ${{ github.server_url == 'https://github.com' }}
runs-on: ubuntu-24.04
permissions:
contents: read
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 }}
steps:
- name: Checkout ivi-homescreen
uses: actions/checkout@v5
with:
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
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: Cache cross sandbox (toolchain + sysroot + engine)
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: Prepare (fetch toolchain, sysroot, engine; build libdisplay-info)
working-directory: ivi-homescreen
run: |
./scripts/build_pi.sh --pios ${{ matrix.pios }} \
--backend all ${{ matrix.args }} --prepare-only
build:
needs: prep
if: ${{ github.server_url == 'https://github.com' }}
runs-on: ubuntu-24.04
permissions:
contents: read
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 }}
steps:
- name: Checkout ivi-homescreen
uses: actions/checkout@v5
with:
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
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: 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
working-directory: ivi-homescreen
run: |
./scripts/build_pi.sh --pios ${{ matrix.pios }} \
--backend ${{ matrix.backend }} ${{ matrix.args }}
- name: Upload homescreen binary
uses: actions/upload-artifact@v4
with:
name: homescreen-${{ matrix.pios }}-${{ matrix.backend }}
path: ivi-homescreen/cmake-build-xc-pi-${{ matrix.pios }}-${{ matrix.backend }}/shell/homescreen
if-no-files-found: error
@@ -24,7 +24,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: 'true'
+4 -4
View File
@@ -17,7 +17,7 @@ jobs:
composefiles: ${{ steps.set-matrix.outputs.composefiles }}
steps:
- name: Check out repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: find-docker-files
id: set-matrix
run: |
@@ -72,7 +72,7 @@ jobs:
password: ${{ secrets.STARGATE_ARTIFACTORY_TOKEN }}
append: true
- name: Check out repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: docker compose local build
id: compose
run: |
@@ -109,7 +109,7 @@ jobs:
dockerfile: ${{ fromJson(needs.set-matrix.outputs.dockerfiles) }}
steps:
- name: Check out repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Wiz IaC Scan
uses: sg-innersource/wizcli-wrapper@v1
with:
@@ -121,7 +121,7 @@ jobs:
runs-on: [sg-jpe-x64-ubuntu-22.04-2core]
steps:
- name: Check out repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Wiz IaC Scan
uses: sg-innersource/wizcli-wrapper@v1
with:
+3
View File
@@ -22,3 +22,6 @@
[submodule "third_party/Vulkan-Headers"]
path = third_party/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers
[submodule "third_party/drm-cxx"]
path = third_party/drm-cxx
url = https://github.com/jwinarske/drm-cxx.git
+67
View File
@@ -37,6 +37,48 @@ project(ivi-homescreen
include(git)
include(options)
if (BUILD_BACKEND_DRM_KMS_EGL)
if (BUILD_BACKEND_WAYLAND_EGL OR BUILD_BACKEND_WAYLAND_VULKAN)
message(FATAL_ERROR
"BUILD_BACKEND_DRM_KMS_EGL is mutually exclusive with "
"BUILD_BACKEND_WAYLAND_EGL and BUILD_BACKEND_WAYLAND_VULKAN")
endif ()
endif ()
if (BUILD_BACKEND_DRM_KMS_VULKAN)
if (BUILD_BACKEND_WAYLAND_EGL OR BUILD_BACKEND_WAYLAND_VULKAN OR
BUILD_BACKEND_DRM_KMS_EGL)
message(FATAL_ERROR
"BUILD_BACKEND_DRM_KMS_VULKAN is mutually exclusive with "
"BUILD_BACKEND_WAYLAND_EGL, BUILD_BACKEND_WAYLAND_VULKAN, and "
"BUILD_BACKEND_DRM_KMS_EGL")
endif ()
endif ()
# FlutterView's backend type is picked by an #if/#elif chain over the
# BUILD_BACKEND_* flags; enabling both Wayland EGL and Wayland Vulkan
# yields a single binary whose renderer is silently determined by
# header order rather than user intent. Reject the combination loudly.
if (BUILD_BACKEND_WAYLAND_EGL AND BUILD_BACKEND_WAYLAND_VULKAN)
message(FATAL_ERROR
"BUILD_BACKEND_WAYLAND_EGL and BUILD_BACKEND_WAYLAND_VULKAN "
"are mutually exclusive — pick exactly one Wayland backend")
endif ()
# Software backend is a pure-CPU presenter with no GPU or display-server
# dependencies; the renderer config is FlutterRendererType.kSoftware,
# incompatible with the GL/Vulkan configs the other backends produce.
# Reject the combination at configure time.
if (BUILD_BACKEND_SOFTWARE)
if (BUILD_BACKEND_DRM_KMS_EGL OR BUILD_BACKEND_DRM_KMS_VULKAN OR
BUILD_BACKEND_WAYLAND_EGL OR
BUILD_BACKEND_WAYLAND_VULKAN OR BUILD_BACKEND_HEADLESS_EGL)
message(FATAL_ERROR
"BUILD_BACKEND_SOFTWARE is mutually exclusive with the "
"DRM/Wayland/Headless EGL/Vulkan backends — pick exactly one")
endif ()
endif ()
message(STATUS "Project ................ ${PROJECT_NAME}")
message(STATUS "Version ................ ${PROJECT_VERSION}")
message(STATUS "Generator .............. ${CMAKE_GENERATOR}")
@@ -44,6 +86,14 @@ message(STATUS "Build Type ............. ${CMAKE_BUILD_TYPE}")
include(compiler)
# drm_kms.cmake must run after compiler.cmake so the `toolchain` INTERFACE
# library (which carries -stdlib=libc++ on clang builds) exists when we
# add_subdirectory(drm-cxx). Otherwise drm-cxx compiles against libstdc++
# and link fails with mixed ABI symbols.
if (BUILD_BACKEND_DRM_KMS_EGL OR BUILD_BACKEND_DRM_KMS_VULKAN)
include(drm_kms)
endif ()
configure_file(cmake/config_common.h.in ${PROJECT_BINARY_DIR}/config/common.h)
#
@@ -63,6 +113,23 @@ if (ENABLE_PLUGINS)
add_subdirectory(${EXT_PLUGINS_DIR} ${PROJECT_BINARY_DIR}/ext_plugins)
endif ()
endforeach ()
# Treat the vendored sdbus-c++ as a system library from our side (we don't
# edit that project): re-publish its interface include dirs as SYSTEM so its
# headers are -isystem for consumers and don't spam our build with warnings.
foreach (_tgt sdbus-c++ sdbus-c++-objlib)
if (TARGET ${_tgt})
get_target_property(_sdbus_inc ${_tgt} INTERFACE_INCLUDE_DIRECTORIES)
if (_sdbus_inc)
set_target_properties(${_tgt} PROPERTIES
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_sdbus_inc}")
endif ()
# Also suppress warnings emitted while compiling sdbus-cpp's own
# sources (e.g. -Wconversion in VTableUtils.c). System includes only
# cover consumers, so quiet the vendored target's own build here.
target_compile_options(${_tgt} PRIVATE -w)
endif ()
endforeach ()
endif ()
#
+38 -20
View File
@@ -566,22 +566,36 @@ For target Yocto builds `CMAKE_INSTALL_PREFIX` defaults to `/usr`
Sentry-native support is available for Crash Handling. This pushes a mini-dump to the cloud for triage and tracking.
To create user account and get DNS See https://sentry.io/welcome/
> To create user account and get a DSN
> see https://sentry.io/welcome/
CMake Variables
### Configuration
1. Specify your DSN via environment variable `SENTRY_DSN`
2. Add the following sections to your `config.toml` file with the following structure:
```toml
[sentry]
release = "homescreen-1.0.0"
env = "production"
attachments = [
"/path/to/crash.log",
"/path/to/config.toml"
]
[sentry.tags]
platform = "linux"
device = "ivi"
```
### CMake Variables
To enable crash handler support:
-DBUILD_CRASH_HANDLER=ON
-DCRASH_HANDLER_DSN="dsn from your account. If not defined, can be set at runtime via environment variable"
-DSENTRY_NATIVE_LIBDIR="directory where sentry native is installed, will look in CMAKE_INSTALL_PREFIX directory if not defined"
-DCRASHPAD_BINARY_DIR="directory where crashpad_handler executable is installed, will look in CMAKE_INSTALL_PREFIX directory if not defined"
-DCRASH_HANDLER_ATTACHMENTS="paths to files you'd like to attach to coredump reports, separated by commas (,)"
-DCRASH_HANDLER_TAGS="tags to accompany Sentry coredump report in the style of "TAG_NAME=tagvalue", multiple tags can be defined separated by commas (,)"
Optional Environment Variables
SENTRY_DSN -- Overrides CMake CRASH_HANDLER_DSN value
SENTRY_ATTACHMENTS -- Additional file attachments to add to Sentry crash reports (Appended to those defined in CRASH_HANDLER_ATTACHMENTS), multiple files can be defined, separated by commas (,)
SENTRY_TAGS -- Additional tags to accompany Sentry crash reports (Appended to those defined in CRASH_HANDLER_TAGS), multiple tags can be defined, separated by commas (,)
To resolve crash dump stack trace, debug binaries and symbols need to be uploaded to Sentry via sentry-cli tool: https://docs.sentry.io/cli/installation/
@@ -591,18 +605,22 @@ Required source repo: https://github.com/getsentry/sentry-native
sentry build
git clone https://github.com/getsentry/sentry-native
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_STAGING_PREFIX=`pwd`/out/usr
make install
```bash
git clone https://github.com/getsentry/sentry-native
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_STAGING_PREFIX=`pwd`/out/usr
make install
```
ivi-homescreen build
git clone https://github.com/toyota-connected/ivi-homescreen
mkdir build && cd build
cmake .. -DBUILD_CRASH_HANDLER=ON -DCRASH_HANDLER_DSN="dsn from your account"
make -j
LD_LIBRARY_PATH=<sentry staged sysroot install path>/lib homescreen --b=<your bundle folder> --f
```bash
git clone https://github.com/toyota-connected/ivi-homescreen
mkdir build && cd build
cmake .. -DBUILD_CRASH_HANDLER=ON -DSENTRY_NATIVE_LIBDIR=`pwd`/../sentry-native/build/out/usr/lib -DCRASHPAD_BINARY_DIR=`pwd`/../sentry-native/build/out/usr/bin
make -j
SENTRY_DSN=<your DSN> homescreen --b=<your bundle folder> --f
```
## Yocto recipes
+13 -1
View File
@@ -86,7 +86,19 @@ endif ()
target_compile_options(toolchain INTERFACE -stdlib=${STDLIB} -isystem"${LLVM_INCLUDE_DIRS}/c++/v1/")
if (ENABLE_STATIC_LINK)
target_link_options(toolchain INTERFACE -static-libstdc++ -static-libgcc -stdlib=${STDLIB} -lc -fuse-ld=lld -v)
if (STDLIB STREQUAL "libc++")
# Statically link libc++ and libc++abi using the linker's -Bstatic/-Bdynamic
# scoping, then restore dynamic linking for all other libraries.
# -static-libstdc++ / -static-libgcc must NOT be used here: -static-libgcc
# pulls in libgcc_eh.a which embeds _Unwind_* symbols that conflict with
# LLVM libunwind inside libsentry.so.
target_link_options(toolchain INTERFACE
-stdlib=${STDLIB}
-Wl,-Bstatic,-lc++,-lc++abi,-Bdynamic
-lc -fuse-ld=lld -v)
else ()
target_link_options(toolchain INTERFACE -static-libstdc++ -static-libgcc -stdlib=${STDLIB} -lc -fuse-ld=lld -v)
endif ()
else ()
target_link_options(toolchain INTERFACE -stdlib=${STDLIB} -lc -fuse-ld=lld -v)
endif ()
+46 -8
View File
@@ -18,10 +18,8 @@
#define CONFIG_COMMON_H_
#include <array>
#include <EGL/egl.h>
#include <waypp/waypp.h>
#include <cstdint> // int32_t in the constants below; was pulled in transitively
// by <EGL/egl.h>/<waypp.h> before those became conditional
#ifndef BUILD_BACKEND_WAYLAND_EGL
#cmakedefine01 BUILD_BACKEND_WAYLAND_EGL
@@ -35,12 +33,50 @@
#ifndef BUILD_BACKEND_DRM_KMS_EGL
#cmakedefine01 BUILD_BACKEND_DRM_KMS_EGL
#endif
#ifndef USE_DRM_SCENE
#cmakedefine01 USE_DRM_SCENE
#endif
#ifndef BUILD_BACKEND_DRM_KMS_VULKAN
#cmakedefine01 BUILD_BACKEND_DRM_KMS_VULKAN
#endif
#ifndef BUILD_BACKEND_HEADLESS_EGL
#cmakedefine01 BUILD_BACKEND_HEADLESS_EGL
#endif
#ifndef BUILD_BACKEND_SOFTWARE
#cmakedefine01 BUILD_BACKEND_SOFTWARE
#endif
#ifndef BUILD_SOFTWARE_SINK_DRM
#cmakedefine01 BUILD_SOFTWARE_SINK_DRM
#endif
#ifndef BUILD_SOFTWARE_SINK_FBDEV
#cmakedefine01 BUILD_SOFTWARE_SINK_FBDEV
#endif
#ifndef BUILD_SOFTWARE_INPUT_LIBINPUT
#cmakedefine01 BUILD_SOFTWARE_INPUT_LIBINPUT
#endif
// EGL is needed only by the EGL-based backends. Including <EGL/egl.h> here
// unconditionally dragged EGL/GL headers into the DRM-Vulkan and software
// builds, which must stay EGL/GL-free.
#if BUILD_BACKEND_WAYLAND_EGL || BUILD_BACKEND_DRM_KMS_EGL || \
BUILD_BACKEND_HEADLESS_EGL
#define IVI_HAVE_EGL 1
#include <EGL/egl.h>
#else
#define IVI_HAVE_EGL 0
#endif
// waypp (the Wayland C++ wrapper + generated protocol bindings) is needed
// only by the Wayland backends (and headless, which links wayland-gen). No
// shell/ code references waypp:: outside those backends, so the DRM EGL/Vulkan
// and software builds drop the header — and with it the libwayland-client /
// libwayland-cursor runtime deps. This condition MUST match the waypp build
// gate in third_party/CMakeLists.txt: waypp's own sources include this header
// (via logging.h), so a mismatch breaks waypp's build.
#if BUILD_BACKEND_WAYLAND_EGL || BUILD_BACKEND_WAYLAND_VULKAN || \
BUILD_BACKEND_HEADLESS_EGL
#include <waypp/waypp.h>
#endif
#cmakedefine01 BUILD_EGL_TRANSPARENCY
#cmakedefine01 BUILD_EGL_ENABLE_3D
@@ -51,11 +87,8 @@
#cmakedefine01 BUILD_CRASH_HANDLER
#if BUILD_CRASH_HANDLER
static constexpr char kCrashHandlerDsn[] = "@CRASH_HANDLER_DSN@";
static constexpr char kCrashHandlerRelease[] = "@PROJECT_NAME@@@BUILD_VER@_@BUILD_NUMBER@_dev";
static constexpr char kSentryEnvDefault[] = "@CMAKE_BUILD_TYPE@";
static constexpr char kCrashpadBinaryPath[] = "@CRASHPAD_BINARY_DIR@/crashpad_handler";
static constexpr char kCrashpadAttachments[] = "@CRASH_HANDLER_ATTACHMENTS@";
static constexpr char kCrashpadTags[] = "@CRASH_HANDLER_TAGS@";
#endif
#cmakedefine01 DEBUG_PLATFORM_MESSAGES
@@ -131,6 +164,10 @@ static constexpr char kDltContextIdDescription[] = "Flutter Embedder";
// Compositor Surface
constexpr unsigned int kCompSurfExpectedInterfaceVersion = 0x00010000;
// EGL config arrays use EGLint / EGL_* and are consumed only by the EGL
// backends; guard them with the same condition as the <EGL/egl.h> include so
// non-EGL builds neither need nor reference the EGL header.
#if IVI_HAVE_EGL
static constexpr std::array<EGLint, 5> kEglContextAttribs = {{
// clang-format off
EGL_CONTEXT_MAJOR_VERSION, 3,
@@ -185,6 +222,7 @@ static constexpr std::array<EGLint, 13> kEglConfigAttribsFallBack = {{
EGL_NONE // termination sentinel
// clang-format on
}};
#endif // IVI_HAVE_EGL
// All vkCreate* functions take an optional allocator. For now, we select the
+103
View File
@@ -0,0 +1,103 @@
#
# DRM/KMS backend build wiring.
#
# drm-cxx is consumed as a git submodule under third_party/drm-cxx and built
# in-tree via add_subdirectory. System deps (libdrm, gbm, libinput, libudev)
# are resolved through pkg-config.
#
if (NOT BUILD_BACKEND_DRM_KMS_EGL AND NOT BUILD_BACKEND_DRM_KMS_VULKAN)
return()
endif ()
find_package(PkgConfig REQUIRED)
pkg_check_modules(DRM REQUIRED IMPORTED_TARGET libdrm)
pkg_check_modules(GBM REQUIRED IMPORTED_TARGET gbm)
pkg_check_modules(LIBINPUT REQUIRED IMPORTED_TARGET libinput)
pkg_check_modules(UDEV REQUIRED IMPORTED_TARGET libudev)
set(_drm_cxx_src "${CMAKE_SOURCE_DIR}/third_party/drm-cxx")
if (NOT EXISTS "${_drm_cxx_src}/CMakeLists.txt")
message(FATAL_ERROR
"third_party/drm-cxx/CMakeLists.txt is missing. Run:\n"
" git submodule update --init --recursive third_party/drm-cxx")
endif ()
# Suppress drm-cxx's tests, examples, install rules, and Vulkan display
# support. ivi-homescreen owns the integration test surface; drm-cxx's
# Vulkan path is orthogonal to the GL renderer this backend drives.
set(DRM_CXX_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(DRM_CXX_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(DRM_CXX_BUILD_BENCHMARKS OFF CACHE BOOL "" FORCE)
set(DRM_CXX_INSTALL OFF CACHE BOOL "" FORCE)
set(DRM_CXX_VULKAN OFF CACHE BOOL "" FORCE)
# Force-on the drm-cxx modules ivi-homescreen UNCONDITIONALLY depends on,
# so a missing system dep fails the configure step here rather than
# silently auto-disabling the module and producing a binary that crashes
# at first use. Today only DRM_CXX_SESSION qualifies: drm::session::Seat
# is consumed unconditionally in backend/drm_kms_egl/drm_session.cc.
set(DRM_CXX_SESSION ON CACHE BOOL "" FORCE)
# Leave AUTO (don't FORCE) on the drm-cxx modules whose ivi-homescreen
# consumers are themselves gated on the same system dep — shell/CMakeLists
# .txt probes libxcursor (gates drm_cursor.cc + sets HAVE_DRM_CURSOR=1) and
# blend2d (gates drm_capture.cc + sets HAVE_DRM_CAPTURE=1), silently
# dropping the source file when the dep is absent. Mirroring AUTO here
# matches that optionality: drm-cxx's cursor + capture modules build when
# libxcursor + blend2d are present, silently drop out together when not.
# Forcing ON here would break the configure for environments that don't
# have libxcursor / blend2d available (CI runners without libblend2d-dev,
# minimal embedded targets that don't want either feature).
# Force-off the optional drm-cxx modules ivi-homescreen does NOT use, so
# we don't transitively pull in their deps (e.g. csd needs Blend2D
# independently of capture; gstreamer support pulls in GStreamer dev
# packages we don't need on the DRM path; streams is a Tegra/L4T-only
# concern). Flip these to ON if/when a feature lands that consumes them.
set(DRM_CXX_CSD OFF CACHE BOOL "" FORCE)
set(DRM_CXX_GSTREAMER OFF CACHE BOOL "" FORCE)
set(DRM_CXX_STREAMS OFF CACHE BOOL "" FORCE)
# CMP0079 NEW lets us attach link libraries to a target created in a
# different directory (drm-cxx's own CMakeLists, processed below).
cmake_policy(SET CMP0079 NEW)
add_subdirectory(${_drm_cxx_src} ${CMAKE_BINARY_DIR}/third_party/drm-cxx EXCLUDE_FROM_ALL)
# Treat drm-cxx as a system library (vendored submodule we keep pristine):
# mark its interface headers SYSTEM so they're -isystem for consumers, and
# silence its own-source warnings (-Wsign-conversion, -Wc++20-extensions, …).
if (TARGET drm-cxx)
get_target_property(_drmcxx_inc drm-cxx INTERFACE_INCLUDE_DIRECTORIES)
if (_drmcxx_inc)
set_target_properties(drm-cxx PROPERTIES
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_drmcxx_inc}")
endif ()
target_compile_options(drm-cxx PRIVATE -w)
endif ()
# drm-cxx is built as a sub-project and doesn't automatically inherit the
# `toolchain` INTERFACE library that applies `-stdlib=libc++` on clang
# builds. Without this, drm-cxx compiles against libstdc++ and the main
# ivi-homescreen binary (libc++) fails to link its STL symbols.
if (TARGET toolchain)
target_link_libraries(drm-cxx PRIVATE toolchain::toolchain)
# drm-cxx transitively pulls in fmt via FetchContent when the toolchain
# lacks std::print. fmt builds with the default compiler stdlib
# (libstdc++), so its objects won't satisfy the libc++ symbols the main
# binary needs. Attaching `toolchain` as a link dep would drag it into
# fmt's install EXPORT set — fmt forces FMT_INSTALL=ON — so copy just
# the compile/link flags instead, leaving fmt's export set untouched.
if (TARGET fmt)
get_target_property(_tc_copts toolchain INTERFACE_COMPILE_OPTIONS)
get_target_property(_tc_lopts toolchain INTERFACE_LINK_OPTIONS)
if (_tc_copts)
target_compile_options(fmt PRIVATE ${_tc_copts})
endif ()
if (_tc_lopts)
target_link_options(fmt PRIVATE ${_tc_lopts})
endif ()
endif ()
endif ()
+120 -23
View File
@@ -92,13 +92,49 @@ option(BUILD_COMPOSITOR "Enable FlutterCompositor backing store API" OFF)
# falls back to a non-exportable allocation if unavailable.
#
option(BUILD_COMPOSITOR_DMABUF_EXPORT
"Export Vulkan backing stores as DMA-BUF for zero-copy plugins" OFF)
"Export Vulkan backing stores as DMA-BUF for zero-copy plugins" OFF)
#
# DRM
#
option(BUILD_BACKEND_DRM "Build DRM backend" OFF)
option(BUILD_BACKEND_WAYLAND_LEASED_DRM "Build Wayland Leased DRM backend" OFF)
option(BUILD_BACKEND_DRM_KMS_EGL
"Build DRM/KMS EGL backend (mutually exclusive with EGL and Vulkan backends)"
OFF)
option(BUILD_BACKEND_DRM_KMS_VULKAN
"Build DRM/KMS Vulkan backend (mutually exclusive with the EGL and Wayland backends)"
OFF)
# Vendor VK_LAYER_KHRONOS_validation into the Vulkan backend so -d guarantees
# validation even on images that ship no system layer registry. Off by default;
# flip ON for dev/CI presets. The option is declared here so the build graph is
# stable ahead of the in-process layer wiring.
option(BUILD_VULKAN_VALIDATION
"Vendor the Khronos Vulkan validation layer into the Vulkan backend"
OFF)
# Standalone zero-copy-capability probe (drm_kms_vulkan_probe). Builds just the
# probe tool without selecting the DRM/KMS Vulkan backend, so it can be
# cross-built and run on a target — alongside any backend — to report whether
# the device can do zero-copy dma-buf scanout. Implied ON when the DRM/KMS
# Vulkan backend itself is built.
option(BUILD_DRM_KMS_VULKAN_PROBE
"Build the standalone drm_kms_vulkan zero-copy capability probe"
OFF)
# Drive the non-framed DRM/KMS present path through drm::scene::LayerScene
# rather than the in-tree PlaneRegistry + Allocator + AtomicRequest pipeline.
# Off-by-default while the integration is bedding in; flip to ON to exercise
# LayerScene-managed plane allocation, composition fallback, and session
# pause/resume forwarding. The framed-mode path is unaffected by this flag.
option(USE_DRM_SCENE
"Drive DRM/KMS non-framed present path via drm::scene::LayerScene"
OFF)
if (USE_DRM_SCENE AND NOT (BUILD_BACKEND_DRM_KMS_EGL OR BUILD_BACKEND_DRM_KMS_VULKAN))
message(FATAL_ERROR
"USE_DRM_SCENE=ON requires BUILD_BACKEND_DRM_KMS_EGL=ON or "
"BUILD_BACKEND_DRM_KMS_VULKAN=ON")
endif ()
#
# Headless
@@ -109,6 +145,49 @@ if (BUILD_BACKEND_HEADLESS_EGL)
pkg_check_modules(OSMESA osmesa glesv2 egl IMPORTED_TARGET REQUIRED)
endif ()
#
# Software (CPU rendering; no GPU, no display server)
#
option(BUILD_BACKEND_SOFTWARE
"Build software (CPU) backend — kSoftware renderer, no GPU/display required"
OFF)
if (BUILD_BACKEND_SOFTWARE)
# Optional DRM dumb-buffer sink. Defaults ON when libdrm is
# available (typical Linux dev/CI host) so the sink is reachable
# without an explicit cmake flag. Auto-disables on systems
# without libdrm; can also be force-OFF for a minimal CI image.
find_package(PkgConfig)
pkg_check_modules(DRM_DUMB libdrm IMPORTED_TARGET)
option(BUILD_SOFTWARE_SINK_DRM
"Build the DRM dumb-buffer sink for the software backend"
${DRM_DUMB_FOUND})
if (BUILD_SOFTWARE_SINK_DRM AND NOT DRM_DUMB_FOUND)
message(FATAL_ERROR
"BUILD_SOFTWARE_SINK_DRM=ON but pkg-config libdrm was not found")
endif ()
# Optional /dev/fb* sink. Linux-only, no library dependency beyond
# the kernel uapi headers (linux/fb.h) which ship with every libc.
# Default ON when targeting Linux; the build hosts targeting other
# OSes (the embedder targets Linux today, but defensive) can flip
# it off via -DBUILD_SOFTWARE_SINK_FBDEV=OFF.
option(BUILD_SOFTWARE_SINK_FBDEV
"Build the fbdev (/dev/fb*) sink for the software backend"
ON)
# Optional libinput-backed seat for keyboard / pointer events.
# Auto-on if pkg-config finds libinput + libudev + xkbcommon (the
# universal Linux desktop input stack). Force-on without the deps
# is a fatal configure error.
pkg_check_modules(SW_LIBINPUT libinput libudev xkbcommon IMPORTED_TARGET)
option(BUILD_SOFTWARE_INPUT_LIBINPUT
"Build the libinput-backed input seat for the software backend"
${SW_LIBINPUT_FOUND})
if (BUILD_SOFTWARE_INPUT_LIBINPUT AND NOT SW_LIBINPUT_FOUND)
message(FATAL_ERROR
"BUILD_SOFTWARE_INPUT_LIBINPUT=ON but pkg-config could not "
"find libinput / libudev / xkbcommon")
endif ()
endif ()
option(DEBUG_PLATFORM_MESSAGES "Debug platform messages" OFF)
#
@@ -116,29 +195,51 @@ option(DEBUG_PLATFORM_MESSAGES "Debug platform messages" OFF)
#
option(BUILD_CRASH_HANDLER "Build Crash Handler" OFF)
if (BUILD_CRASH_HANDLER)
message(STATUS "Crash Handler .......... Enabled")
include(GNUInstallDirs)
# sentry-native installs its CMake package config under the GNUInstallDirs
# libdir of its staging prefix -- typically lib/cmake/sentry, but lib64 on
# some distros and a flat cmake/sentry on older layouts. Hardcoding a single
# suffix breaks whenever ${CMAKE_INSTALL_LIBDIR} here differs from the one
# sentry-native installed with (or is empty because GNUInstallDirs had not
# been included yet). Search the likely suffixes under the chosen base so a
# libdir mismatch can't break configure.
if (SENTRY_NATIVE_LIBDIR)
if (NOT EXISTS ${SENTRY_NATIVE_LIBDIR}/cmake/sentry/sentry-config.cmake)
message(FATAL_ERROR "${SENTRY_NATIVE_LIBDIR}/cmake/sentry/sentry-config.cmake does not exist")
else ()
message(STATUS "Found libsentry at specified directory: ${SENTRY_NATIVE_LIBDIR}/cmake/sentry/sentry-config.cmake")
set(sentry_DIR ${SENTRY_NATIVE_LIBDIR}/cmake/sentry)
endif ()
set(_sentry_base ${SENTRY_NATIVE_LIBDIR})
else ()
if (EXISTS ${CMAKE_INSTALL_PREFIX}/lib/cmake/sentry/sentry-config.cmake)
message(STATUS "Found sentry at default location: ${CMAKE_INSTALL_PREFIX}/lib/cmake/sentry/sentry-config.cmake")
set(sentry_DIR {CMAKE_INSTALL_PREFIX}/lib/cmake/sentry)
else ()
message(FATAL_ERROR "Sentry could not be found at ${CMAKE_INSTALL_PREFIX}/lib/cmake/sentry/sentry-config.cmake, please set SENTRY_NATIVE_LIBDIR")
endif()
set(_sentry_base ${CMAKE_INSTALL_PREFIX})
endif ()
set(sentry_DIR "")
foreach (_suffix
${CMAKE_INSTALL_LIBDIR}/cmake/sentry
lib/cmake/sentry
lib64/cmake/sentry
cmake/sentry)
if (EXISTS ${_sentry_base}/${_suffix}/sentry-config.cmake)
set(sentry_DIR ${_sentry_base}/${_suffix})
break ()
endif ()
endforeach ()
if (sentry_DIR)
message(STATUS "Found libsentry: ${sentry_DIR}/sentry-config.cmake")
else ()
message(FATAL_ERROR
"sentry-config.cmake not found under ${_sentry_base} "
"(searched */cmake/sentry). Set SENTRY_NATIVE_LIBDIR to the "
"sentry-native staging prefix.")
endif ()
if (CRASHPAD_BINARY_DIR)
if (NOT EXISTS ${CRASHPAD_BINARY_DIR}/crashpad_handler)
message(FATAL_ERROR "${CRASHPAD_BINARY_DIR}/crashpad_handler does not exist")
else()
else ()
message(STATUS "Using crashpad_handler at specified directory: ${CRASHPAD_BINARY_DIR}")
endif()
endif ()
else ()
if (EXISTS ${CMAKE_INSTALL_PREFIX}/bin/crashpad_handler)
message(STATUS "Defaulting to system crashpad_handler at ${CMAKE_INSTALL_PREFIX}")
@@ -147,15 +248,11 @@ if (BUILD_CRASH_HANDLER)
message(FATAL_ERROR "System crashpad_handler not found at ${CMAKE_INSTALL_PREFIX}, please set CRASHPAD_BINARY_DIR")
endif()
endif()
if (NOT CRASH_HANDLER_DSN)
message(STATUS "Sentry DSN not set, use environment variable SENTRY_DSN to direct coredumps")
endif ()
find_package(sentry REQUIRED)
find_package(PkgConfig)
pkg_check_modules(UNWIND REQUIRED IMPORTED_TARGET libunwind)
string(TIMESTAMP BUILD_VER "%y%m%d")
else()
message(STATUS "Crash Handler .......... Disabled")
endif ()
#
+919
View File
File diff suppressed because it is too large Load Diff
+400
View File
@@ -0,0 +1,400 @@
#!/usr/bin/env bash
# Copyright 2026 Toyota Connected North America
#
# Cross-build of ivi-homescreen (drm_kms_egl backend) for the Boundary Devices
# Nitrogen8MM (NXP i.MX8MM — quad Cortex-A53, Vivante GC7000NanoUltra GPU,
# imx-drm/LCDIF display, Yocto "fsl-imx-wayland" userspace, GLES2/EGL only).
#
# Unlike build_unoq.sh / build_radxa_zero3.sh, this board's userspace comes from
# a local Yocto build, not a Debian image — so there is no rootfs to rsync and
# no apt to install -dev packages. Instead this script reuses the Yocto build
# tree directly:
#
# * the weston recipe's recipe-sysroot is already a complete cross dev sysroot
# (libdrm/gbm/EGL/GLESv2/libinput/libudev/libxkbcommon/libseat + headers),
# and its recipe-sysroot-native ships the matching aarch64-poky-linux gcc;
# * libdisplay-info >= 0.2.0 (required by drm-cxx, absent from the image) is
# cross-built static and installed into that sysroot;
# * the Flutter engine is dlopen'd at runtime, so it is NOT needed to build —
# a self-contained app bundle (lib/libflutter_engine.so + lib/libapp.so +
# data/) is deployed instead.
#
# The i.MX8MM LCDIF has a single primary plane (no HW cursor plane) and the
# image has no libxcursor, so the build uses the GL-composited cursor fallback.
#
# Sandbox layout (nothing is written under /usr, /opt, etc. on the host):
#
# $XC_ROOT/ default: $XDG_CACHE_HOME/ivi-homescreen-xc-nitrogen8mm
# downloads/ cached libdisplay-info tarball
# src/ extracted libdisplay-info source + meson build
#
# <repo>/cmake-build-xc-nitrogen8mm-drm-kms-egl/ CMake build dir (gitignored)
#
# NOTE: libdisplay-info is installed (static) INTO the weston recipe-sysroot.
# That is a build artifact you own; re-running weston's do_populate_sysroot in
# Yocto would wipe it, in which case just re-run this script (the step is
# idempotent).
#
# Host requirements: Linux with cmake, ninja, meson, pkg-config, curl, tar,
# ssh/scp, file. SSH key access to the board (root@nitrogen8mm.local).
#
# Usage:
# scripts/build_nitrogen8mm.sh [options]
# --yocto-build <dir> Yocto build dir holding tmp/work/...
# (default: /mnt/raid10/yocto/nxp-imx/bld-wayland)
# --machine-tuple <t> Yocto package arch dir under tmp/work
# (default: armv8a-mx8mm-poky-linux)
# --device-host <u@host> SSH target for --deploy (default: root@nitrogen8mm.local)
# --ssh-port <n> SSH port (default: 22)
# --ssh-opts <str> extra ssh/scp options (e.g. "-i ~/.ssh/id_board")
# --bundle <path> self-contained Flutter app bundle to deploy
# (default: ../flutter-wonderous-app/.desktop-homescreen)
# --plugins-dir <path> ivi-homescreen-plugins/plugins (default: ../ivi-homescreen-plugins/plugins)
# --no-plugins build homescreen only
# --with-scene enable the plane compositor + drm-cxx LayerScene
# (BUILD_COMPOSITOR + USE_DRM_SCENE)
# --display-info-version <v> libdisplay-info source tag (default: 0.2.0)
# --jobs <N> parallel build jobs (default: nproc)
# --clean wipe the CMake build dir before configuring
# --prepare-only locate toolchain + build libdisplay-info, then exit
# --deploy scp binary + bundle to the board and install the
# seatd + kiosk systemd units
# --restart with --deploy, (re)start the service now
# -h | --help this help
set -euo pipefail
# ── Defaults ─────────────────────────────────────────────────────────────
YOCTO_BUILD="/mnt/raid10/yocto/nxp-imx/bld-wayland"
MACHINE_TUPLE="armv8a-mx8mm-poky-linux"
DEVICE_HOST="root@nitrogen8mm.local"
SSH_PORT="22"
SSH_OPTS=""
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
BUNDLE="$REPO_DIR/../flutter-wonderous-app/.desktop-homescreen"
PLUGINS_DIR="$REPO_DIR/../ivi-homescreen-plugins/plugins"
NO_PLUGINS=0
WITH_SCENE=0
LIBDISPLAY_INFO_VERSION="0.2.0"
JOBS="$(nproc)"
CLEAN=0
PREPARE_ONLY=0
DO_DEPLOY=0
DO_RESTART=0
XC_ROOT="${XC_ROOT:-${XDG_CACHE_HOME:-$HOME/.cache}/ivi-homescreen-xc-nitrogen8mm}"
BUILD_DIR="$REPO_DIR/cmake-build-xc-nitrogen8mm-drm-kms-egl"
# i.MX8MM Cortex-A53 tune, mirrored from the weston recipe's CC.
XC_CPU_FLAGS="-march=armv8-a+crc+crypto -mbranch-protection=standard"
CROSS_TRIPLE="aarch64-poky-linux"
# ── Helpers ──────────────────────────────────────────────────────────────
log() { printf '\033[1;34m[build]\033[0m %s\n' "$*"; }
note() { printf ' %s\n' "$*"; }
die() { printf '\033[1;31m[build] error:\033[0m %s\n' "$*" >&2; exit 1; }
ssh_dev() { ssh -p "$SSH_PORT" $SSH_OPTS "$DEVICE_HOST" "$@"; }
scp_dev() { scp -P "$SSH_PORT" $SSH_OPTS "$@"; }
# ── Arg parsing ──────────────────────────────────────────────────────────
while [[ $# -gt 0 ]]; do
case "$1" in
--yocto-build) YOCTO_BUILD="$2"; shift 2 ;;
--machine-tuple) MACHINE_TUPLE="$2"; shift 2 ;;
--device-host) DEVICE_HOST="$2"; shift 2 ;;
--ssh-port) SSH_PORT="$2"; shift 2 ;;
--ssh-opts) SSH_OPTS="$2"; shift 2 ;;
--bundle) BUNDLE="$2"; shift 2 ;;
--plugins-dir) PLUGINS_DIR="$2"; shift 2 ;;
--no-plugins) NO_PLUGINS=1; shift ;;
--with-scene) WITH_SCENE=1; shift ;;
--display-info-version) LIBDISPLAY_INFO_VERSION="$2"; shift 2 ;;
--jobs) JOBS="$2"; shift 2 ;;
--clean) CLEAN=1; shift ;;
--prepare-only) PREPARE_ONLY=1; shift ;;
--deploy) DO_DEPLOY=1; shift ;;
--restart) DO_RESTART=1; shift ;;
-h|--help) sed -n '2,/^set -euo/p' "$0" | sed 's/^# \{0,1\}//; s/^#$//'; exit 0 ;;
*) die "unknown option: $1 (try --help)" ;;
esac
done
LIBDISPLAY_INFO_URL="https://gitlab.freedesktop.org/emersion/libdisplay-info/-/archive/${LIBDISPLAY_INFO_VERSION}/libdisplay-info-${LIBDISPLAY_INFO_VERSION}.tar.gz"
# ── Phase 0: preflight ───────────────────────────────────────────────────
phase0_preflight() {
log "Phase 0: preflight"
local missing=()
for t in cmake ninja meson pkg-config curl tar file; do
command -v "$t" >/dev/null || missing+=("$t")
done
if [[ "$DO_DEPLOY" -eq 1 ]]; then
for t in ssh scp; do command -v "$t" >/dev/null || missing+=("$t"); done
fi
if [[ ${#missing[@]} -gt 0 ]]; then
die "missing host tools: ${missing[*]}
Fedora: sudo dnf install cmake ninja-build meson pkgconf-pkg-config curl tar file openssh-clients
Debian: sudo apt install cmake ninja-build meson pkg-config curl tar file openssh-client"
fi
[[ -d "$REPO_DIR/third_party/drm-cxx" && -f "$REPO_DIR/third_party/drm-cxx/CMakeLists.txt" ]] \
|| die "third_party/drm-cxx missing — run: git submodule update --init --recursive third_party/drm-cxx"
}
# ── Phase 1: locate Yocto sysroot + cross toolchain ──────────────────────
phase1_locate() {
log "Phase 1: locate Yocto weston sysroot + cross toolchain"
local weston_glob="$YOCTO_BUILD/tmp/work/$MACHINE_TUPLE/weston"
[[ -d "$weston_glob" ]] \
|| die "weston not built under $weston_glob
Point --yocto-build at your i.MX8MM Yocto build (the dir with tmp/work/...),
and ensure weston has been built (it stages the full graphics dev sysroot)."
# Newest weston version dir (|| true: don't let an empty glob trip set -e).
local wdir
wdir="$( (ls -d "$weston_glob"/*/ 2>/dev/null || true) | sort -V | tail -1)"
[[ -n "$wdir" ]] || die "no weston version dir under $weston_glob"
XC_SYSROOT="${wdir%/}/recipe-sysroot"
local native="${wdir%/}/recipe-sysroot-native"
CROSS_BIN="$native/usr/bin/$CROSS_TRIPLE"
[[ -x "$CROSS_BIN/$CROSS_TRIPLE-gcc" ]] \
|| die "cross gcc not found: $CROSS_BIN/$CROSS_TRIPLE-gcc"
[[ -f "$XC_SYSROOT/usr/include/EGL/egl.h" ]] \
|| die "sysroot missing EGL headers: $XC_SYSROOT (is this the weston recipe-sysroot?)"
export XC_SYSROOT CROSS_BIN XC_CPU_FLAGS
note "sysroot = $XC_SYSROOT"
note "cross gcc = $CROSS_BIN/$CROSS_TRIPLE-gcc ($("$CROSS_BIN/$CROSS_TRIPLE-gcc" -dumpversion 2>/dev/null))"
note "cpu flags = $XC_CPU_FLAGS"
}
# ── Phase 2: libdisplay-info >= 0.2.0 (static) into the sysroot ───────────
displayinfo_ok() {
PKG_CONFIG_LIBDIR="$XC_SYSROOT/usr/lib/pkgconfig" PKG_CONFIG_SYSROOT_DIR="$XC_SYSROOT" \
pkg-config --atleast-version="$LIBDISPLAY_INFO_VERSION" libdisplay-info 2>/dev/null
}
phase2_display_info() {
log "Phase 2: libdisplay-info >= $LIBDISPLAY_INFO_VERSION (static, drm-cxx dep)"
if displayinfo_ok; then
note "sysroot already has libdisplay-info $(PKG_CONFIG_LIBDIR="$XC_SYSROOT/usr/lib/pkgconfig" PKG_CONFIG_SYSROOT_DIR="$XC_SYSROOT" pkg-config --modversion libdisplay-info); skipping"
return
fi
mkdir -p "$XC_ROOT/downloads" "$XC_ROOT/src"
local tarball="$XC_ROOT/downloads/libdisplay-info-${LIBDISPLAY_INFO_VERSION}.tar.gz"
local src="$XC_ROOT/src/libdisplay-info-${LIBDISPLAY_INFO_VERSION}"
local cross="$XC_ROOT/src/di-cross.ini"
local bld="$XC_ROOT/src/di-build"
if [[ ! -f "$tarball" ]]; then
log "fetching libdisplay-info $LIBDISPLAY_INFO_VERSION"
curl -fsSL -o "$tarball" "$LIBDISPLAY_INFO_URL" || die "download failed: $LIBDISPLAY_INFO_URL"
fi
if [[ ! -f "$src/meson.build" ]]; then
rm -rf "$src"; local tmp; tmp="$(mktemp -d "$XC_ROOT/src/.unpack.XXXXXX")"
tar -xzf "$tarball" -C "$tmp"; mv "$tmp"/*/ "$src"; rmdir "$tmp"
fi
cat > "$cross" <<EOF
[binaries]
c = '$CROSS_BIN/$CROSS_TRIPLE-gcc'
cpp = '$CROSS_BIN/$CROSS_TRIPLE-g++'
ar = '$CROSS_BIN/$CROSS_TRIPLE-ar'
strip = '$CROSS_BIN/$CROSS_TRIPLE-strip'
pkg-config = 'pkg-config'
[host_machine]
system = 'linux'
cpu_family = 'aarch64'
cpu = 'aarch64'
endian = 'little'
[built-in options]
c_args = ['--sysroot=$XC_SYSROOT', '-march=armv8-a+crc+crypto', '-mbranch-protection=standard']
c_link_args = ['--sysroot=$XC_SYSROOT']
EOF
log "configuring + building libdisplay-info (meson cross, static)"
rm -rf "$bld"
PKG_CONFIG_LIBDIR="$XC_SYSROOT/usr/lib/pkgconfig:$XC_SYSROOT/usr/share/pkgconfig" \
PKG_CONFIG_SYSROOT_DIR="$XC_SYSROOT" \
meson setup "$bld" "$src" --cross-file "$cross" \
--prefix /usr --libdir lib --buildtype release --default-library static
ninja -C "$bld"
DESTDIR="$XC_SYSROOT" ninja -C "$bld" install
# Drop the shared sibling (install builds only static, but be safe) so the
# linker picks the .a and homescreen needs no libdisplay-info.so on-target.
rm -f "$XC_SYSROOT/usr/lib/libdisplay-info.so"*
displayinfo_ok || die "libdisplay-info install did not yield >= $LIBDISPLAY_INFO_VERSION"
note "installed libdisplay-info (static) into $XC_SYSROOT"
}
# ── Phase 3: emit toolchain file + sysroot-aware pkg-config wrapper ───────
phase3_emit() {
log "Phase 3: emit toolchain file + pkg-config wrapper"
mkdir -p "$BUILD_DIR"
cat > "$BUILD_DIR/.xc-pkg-config" <<'EOF'
#!/bin/sh
# Sysroot-aware pkg-config wrapper for the Yocto (weston recipe) sysroot.
export PKG_CONFIG_DIR=
export PKG_CONFIG_LIBDIR="$XC_SYSROOT/usr/lib/pkgconfig:$XC_SYSROOT/usr/share/pkgconfig"
export PKG_CONFIG_SYSROOT_DIR="$XC_SYSROOT"
unset PKG_CONFIG_PATH
exec pkg-config "$@"
EOF
chmod +x "$BUILD_DIR/.xc-pkg-config"
cat > "$BUILD_DIR/.xc-toolchain.cmake" <<EOF
# Generated by scripts/build_nitrogen8mm.sh — do not edit.
# i.MX8MM, Yocto weston recipe-sysroot + aarch64-poky-linux gcc.
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_SYSROOT "\$ENV{XC_SYSROOT}")
set(CMAKE_C_COMPILER "\$ENV{CROSS_BIN}/$CROSS_TRIPLE-gcc")
set(CMAKE_CXX_COMPILER "\$ENV{CROSS_BIN}/$CROSS_TRIPLE-g++")
set(CMAKE_FIND_ROOT_PATH "\$ENV{XC_SYSROOT}")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Yocto sysroot has no Debian multiarch layout (libs live in /usr/lib).
set(_xc_cpu "-march=armv8-a+crc+crypto -mbranch-protection=standard")
set(CMAKE_C_FLAGS_INIT "\${_xc_cpu}")
set(CMAKE_CXX_FLAGS_INIT "\${_xc_cpu}")
set(PKG_CONFIG_EXECUTABLE "$BUILD_DIR/.xc-pkg-config"
CACHE FILEPATH "sysroot-aware pkg-config wrapper" FORCE)
EOF
note "toolchain file: $BUILD_DIR/.xc-toolchain.cmake"
}
# ── Phase 4: configure & build ───────────────────────────────────────────
phase4_build() {
log "Phase 4: configure & build (drm-kms-egl, jobs=$JOBS)"
[[ "$CLEAN" -eq 1 ]] && rm -rf "$BUILD_DIR"/CMakeCache.txt "$BUILD_DIR"/CMakeFiles
export XC_SYSROOT CROSS_BIN
export PATH="$CROSS_BIN:$PATH"
local args=(
-G Ninja -S "$REPO_DIR" -B "$BUILD_DIR"
-DCMAKE_TOOLCHAIN_FILE="$BUILD_DIR/.xc-toolchain.cmake"
-DCMAKE_BUILD_TYPE=Release
-DBUILD_BACKEND_WAYLAND_EGL=OFF -DBUILD_BACKEND_WAYLAND_VULKAN=OFF
-DBUILD_BACKEND_DRM_KMS_EGL=ON -DBUILD_BACKEND_SOFTWARE=OFF
-DBUILD_BACKEND_HEADLESS_EGL=OFF
)
[[ "$WITH_SCENE" -eq 1 ]] && args+=(-DBUILD_COMPOSITOR=ON -DUSE_DRM_SCENE=ON)
if [[ "$NO_PLUGINS" -eq 1 ]]; then
args+=(-DDISABLE_PLUGINS=ON)
else
[[ -d "$PLUGINS_DIR" ]] || die "plugins dir not found: $PLUGINS_DIR (use --no-plugins or --plugins-dir)"
args+=(-DDISABLE_PLUGINS=OFF -DPLUGINS_DIR="$PLUGINS_DIR")
fi
cmake "${args[@]}"
cmake --build "$BUILD_DIR" -j "$JOBS"
}
# ── Phase 5: report ──────────────────────────────────────────────────────
phase5_report() {
local exe="$BUILD_DIR/shell/homescreen"
[[ -x "$exe" ]] || die "no homescreen binary produced"
log "Phase 5: artifacts"
echo " binary : $exe"
file "$exe" | sed 's/^/ /'
echo " sysroot : $XC_SYSROOT"
}
# ── Phase 6: deploy ──────────────────────────────────────────────────────
phase6_deploy() {
[[ "$DO_DEPLOY" -eq 1 ]] || return 0
log "Phase 6: deploy to $DEVICE_HOST"
local exe="$BUILD_DIR/shell/homescreen"
[[ -d "$BUNDLE" && -f "$BUNDLE/lib/libflutter_engine.so" ]] \
|| die "bundle not found / not self-contained: $BUNDLE
Expected a dir with lib/libflutter_engine.so + lib/libapp.so + data/."
local stage="/tmp/ivi-homescreen-stage"
ssh_dev "rm -rf '$stage' && mkdir -p '$stage'"
log "staging binary + bundle"
scp_dev "$exe" "$DEVICE_HOST:$stage/homescreen" >/dev/null
scp_dev -r "$BUNDLE" "$DEVICE_HOST:$stage/bundle" >/dev/null
log "installing on board (seatd + kiosk units)"
ssh_dev "bash -s" <<'REMOTE'
set -e
stage="/tmp/ivi-homescreen-stage"
install -Dm755 "$stage/homescreen" /usr/local/bin/ivi-homescreen
rm -rf /opt/ivi-homescreen/bundle
mkdir -p /opt/ivi-homescreen
cp -a "$stage/bundle" /opt/ivi-homescreen/bundle
# seatd: the image ships the binary but runs no seatd; libseat's logind backend
# has no seat in a headless systemd service, so drive a VT-bound seatd seat.
cat > /etc/systemd/system/seatd.service <<'UNIT'
[Unit]
Description=Seat management daemon
[Service]
Type=simple
ExecStart=/usr/bin/seatd -g root
Restart=on-failure
[Install]
WantedBy=multi-user.target
UNIT
cat > /etc/systemd/system/ivi-homescreen.service <<'UNIT'
[Unit]
Description=ivi-homescreen (drm_kms_egl)
After=seatd.service systemd-udev-settle.service
Wants=seatd.service
[Service]
Type=simple
Environment=LIBSEAT_BACKEND=seatd
Environment=XDG_RUNTIME_DIR=/run/user/0
# Flutter apps (path_provider/shared_preferences) require HOME; a systemd
# service has none by default, unlike an interactive login shell.
Environment=HOME=/root
WorkingDirectory=/opt/ivi-homescreen
ExecStartPre=/bin/mkdir -p /run/user/0
ExecStartPre=-/bin/sh -c 'for g in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do echo performance > "$g" 2>/dev/null || true; done'
ExecStart=/usr/local/bin/ivi-homescreen -b /opt/ivi-homescreen/bundle
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload
systemctl enable seatd.service ivi-homescreen.service
rm -rf "$stage"
echo "install: done"
REMOTE
if [[ "$DO_RESTART" -eq 1 ]]; then
log "starting service"
ssh_dev "systemctl restart seatd.service ivi-homescreen.service || true"
fi
echo
echo " Deployed + enabled on $DEVICE_HOST (starts on boot)."
echo " Inspect: ssh $DEVICE_HOST 'journalctl -u ivi-homescreen -b'"
[[ "$DO_RESTART" -eq 1 ]] || echo " Pass --restart to start it now."
}
# ── Main ─────────────────────────────────────────────────────────────────
phase0_preflight
phase1_locate
phase2_display_info
if [[ "$PREPARE_ONLY" -eq 1 ]]; then
log "prepare-only: toolchain located + libdisplay-info ready; exiting"
exit 0
fi
phase3_emit
phase4_build
phase5_report
phase6_deploy
log "done"
+1559
View File
File diff suppressed because it is too large Load Diff
+227
View File
@@ -0,0 +1,227 @@
#!/usr/bin/env bash
# Copyright 2026 Toyota Connected North America
#
# Assembles a Pi-ready Flutter bundle from the current Flutter app
# directory. Run from the root of a Flutter project (where pubspec.yaml
# lives).
#
# Two paths:
#
# 1. WITHOUT FLUTTER_WORKSPACE — the bundle is debug-mode only
# (kernel_blob.bin / JIT). Wonderous and other GPU-bound apps
# may fail to render on Pi-class hardware in debug. Useful for
# quick smoke / desktop testing only. The script warns loudly.
#
# 2. WITH FLUTTER_WORKSPACE set — invokes
# $FLUTTER_WORKSPACE/flutter_workspace.py --create-aot
# with QEMU_LD_PREFIX + GEN_SNAPSHOT pre-configured to cross-
# compile Dart to aarch64 AOT via the workspace's prebuilt
# arm64 gen_snapshot. Stages the produced libapp.so.release
# into <bundle>/lib/libapp.so. The resulting bundle is
# Runtime=release and renders reliably under DRM/KMS.
#
# Prerequisites (both paths):
# - `flutter build bundle` must have been run (or `flutter run` which
# does it implicitly). The script verifies build/flutter_assets exists.
# - Flutter engine artifacts (libflutter_engine.so, icudtl.dat) at
# $ENGINE_BUNDLE (defaults under FLUTTER_WORKSPACE).
#
# Prerequisites (AOT path only):
# - FLUTTER_WORKSPACE points at a workspace-automation checkout with:
# flutter_workspace.py
# create_aot.py
# flutter/engine/src/flutter/prebuilts/linux-arm64/dart-sdk/bin/utils/gen_snapshot
# - Cross-build sysroot at $XC_SYSROOT (defaults to
# $XDG_CACHE_HOME/ivi-homescreen-xc/sysroot/$PIOS, PIOS=trixie —
# same sysroot build_pi.sh creates).
#
# Usage:
# cd /path/to/flutter/app
# flutter build bundle # debug
# /path/to/ivi-homescreen/scripts/build_pi_bundle.sh [/dev/dri/cardN]
#
# # Or for the AOT / release bundle (recommended for Pi):
# export FLUTTER_WORKSPACE=/mnt/raid10/workspace-automation
# /path/to/ivi-homescreen/scripts/build_pi_bundle.sh [/dev/dri/cardN]
#
# Env overrides:
# PIOS sysroot variant: bookworm|trixie (default trixie)
# XC_SYSROOT explicit sysroot path (overrides $PIOS-derived)
# GEN_SNAPSHOT explicit gen_snapshot path
# ENGINE_BUNDLE path with lib/libflutter_engine.so + data/icudtl.dat
# (skips FLUTTER_WORKSPACE derivation)
# CONFIG_TEMPLATE path to a config.toml to seed the bundle's config
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_DIR="$(dirname "$SCRIPT_DIR")"
die() { echo "error: $*" >&2; exit 1; }
log() { echo "==> $*"; }
# ── Configurable paths ───────────────────────────────────────────────────
PIOS="${PIOS:-trixie}"
XC_ROOT="${IVI_XC_ROOT:-${XDG_CACHE_HOME:-$HOME/.cache}/ivi-homescreen-xc}"
XC_SYSROOT="${XC_SYSROOT:-$XC_ROOT/sysroot/$PIOS}"
# ENGINE_BUNDLE may also be set directly (skips the FLUTTER_WORKSPACE check).
if [[ -z "${ENGINE_BUNDLE:-}" ]]; then
[[ -n "${FLUTTER_WORKSPACE:-}" ]] \
|| die "set FLUTTER_WORKSPACE or ENGINE_BUNDLE before running"
ENGINE_BUNDLE="${FLUTTER_WORKSPACE}/flutter-engine/bundle-debug-x64"
fi
CONFIG_TEMPLATE="${CONFIG_TEMPLATE:-${FLUTTER_WORKSPACE:-}/desktop-homescreen/config.toml}"
DRM_DEVICE="${1:-/dev/dri/card0}"
BUNDLE_DIR=".desktop-homescreen"
# ── FLUTTER_WORKSPACE warning (when unset) ───────────────────────────────
if [[ -z "${FLUTTER_WORKSPACE:-}" ]]; then
cat <<'WARN' >&2
################################################################################
## ##
## WARNING: FLUTTER_WORKSPACE is not set. ##
## ##
## Without it, this script can only produce a DEBUG bundle (JIT, ##
## kernel_blob.bin). On Pi-class hardware, debug-mode Flutter apps ##
## often fail to render — the Dart code runs but no frames make it ##
## to the panel. The kiosk service appears active but the display ##
## stays black (with the cursor visible on drm-kms-egl). ##
## ##
## For a RELEASE bundle (AOT, libapp.so) that renders reliably on Pi: ##
## ##
## export FLUTTER_WORKSPACE=/path/to/workspace-automation ##
## $0 [drm_device] ##
## ##
## When set, this script: ##
## • invokes $FLUTTER_WORKSPACE/flutter_workspace.py --create-aot ##
## • cross-compiles Dart to aarch64 via the workspace's arm64 ##
## gen_snapshot under qemu-user against the cached PiOS sysroot ##
## • stages libapp.so.release into <bundle>/lib/libapp.so ##
## ##
################################################################################
WARN
fi
# ── Validation ───────────────────────────────────────────────────────────
[[ -f pubspec.yaml ]] || die "run from a Flutter project root (no pubspec.yaml)"
[[ -d build/flutter_assets ]] || die "build/flutter_assets missing; run: flutter build bundle"
[[ -f "$ENGINE_BUNDLE/lib/libflutter_engine.so" ]] || die "engine not found at $ENGINE_BUNDLE/lib/libflutter_engine.so"
[[ -f "$ENGINE_BUNDLE/data/icudtl.dat" ]] || die "icudtl.dat not found at $ENGINE_BUNDLE/data/icudtl.dat"
# ── Assemble ─────────────────────────────────────────────────────────────
rm -rf "$BUNDLE_DIR"
mkdir -p "$BUNDLE_DIR/data" "$BUNDLE_DIR/lib"
# Engine artifacts.
cp "$ENGINE_BUNDLE/lib/libflutter_engine.so" "$BUNDLE_DIR/lib/"
cp "$ENGINE_BUNDLE/data/icudtl.dat" "$BUNDLE_DIR/data/"
# Flutter assets — copy rather than symlink so the bundle is self-contained
# and survives being moved or copied to a different directory (e.g., the
# vkms harness copies it to a tmpdir). For hot-reload workflows, use
# `flutter run -d desktop-homescreen` which manages the symlink itself.
cp -r build/flutter_assets "$BUNDLE_DIR/data/flutter_assets"
# Config — use the template if it exists, else generate a minimal one.
if [[ -f "$CONFIG_TEMPLATE" ]]; then
cp "$CONFIG_TEMPLATE" "$BUNDLE_DIR/config.toml"
else
cat > "$BUNDLE_DIR/config.toml" <<EOF
[global]
app_id = "homescreen"
[view]
width = 1920
height = 1080
fullscreen = true
EOF
fi
# Pin drm_device into the config.
if grep -q '^\[view\]' "$BUNDLE_DIR/config.toml"; then
# Insert after [view]
sed -i "/^\[view\]/a drm_device = \"$DRM_DEVICE\"" "$BUNDLE_DIR/config.toml"
else
printf '\n[view]\ndrm_device = "%s"\n' "$DRM_DEVICE" >> "$BUNDLE_DIR/config.toml"
fi
# ── AOT cross-compile (release-mode bundle) ──────────────────────────────
#
# Only runs when FLUTTER_WORKSPACE is set. Mirrors the manual command:
#
# QEMU_LD_PREFIX=$XC_SYSROOT \
# GEN_SNAPSHOT=$FLUTTER_WORKSPACE/flutter/engine/src/flutter/prebuilts/linux-arm64/dart-sdk/bin/utils/gen_snapshot \
# python3 $FLUTTER_WORKSPACE/flutter_workspace.py --create-aot --app-path $(pwd)
#
# flutter_workspace.py respects a pre-set GEN_SNAPSHOT (≥ the commit that
# introduces the "Honoring caller-set" hint) and uses it for AOT compile.
# The arm64 gen_snapshot binary runs under qemu-user via binfmt_misc,
# finding its dynamic linker via QEMU_LD_PREFIX → sysroot.
BUNDLE_RUNTIME="debug"
if [[ -n "${FLUTTER_WORKSPACE:-}" ]]; then
GEN_SNAPSHOT="${GEN_SNAPSHOT:-$FLUTTER_WORKSPACE/flutter/engine/src/flutter/prebuilts/linux-arm64/dart-sdk/bin/utils/gen_snapshot}"
WORKSPACE_PY="$FLUTTER_WORKSPACE/flutter_workspace.py"
[[ -x "$GEN_SNAPSHOT" ]] \
|| die "gen_snapshot not executable: $GEN_SNAPSHOT (set GEN_SNAPSHOT to override)"
[[ -f "$WORKSPACE_PY" ]] \
|| die "flutter_workspace.py not found at $WORKSPACE_PY"
[[ -d "$XC_SYSROOT" ]] \
|| die "sysroot not found: $XC_SYSROOT (run scripts/build_pi.sh --prepare-only --pios $PIOS, or set XC_SYSROOT)"
# create_aot.py needs `which flutter` to resolve (for the SDK
# version check) and PUB_CACHE to be set. The workspace ships its
# own Flutter SDK + isolated pub cache under .config/flutter_workspace
# — wire both up so the operator doesn't have to source setup_env.sh
# first.
AOT_PATH="$FLUTTER_WORKSPACE/flutter/bin:$PATH"
AOT_PUB_CACHE="${PUB_CACHE:-$FLUTTER_WORKSPACE/.config/flutter_workspace/pub_cache}"
[[ -x "$FLUTTER_WORKSPACE/flutter/bin/flutter" ]] \
|| die "flutter SDK not found at $FLUTTER_WORKSPACE/flutter/bin/flutter"
log "running flutter_workspace.py --create-aot"
echo " QEMU_LD_PREFIX=$XC_SYSROOT"
echo " GEN_SNAPSHOT=$GEN_SNAPSHOT"
echo " PUB_CACHE=$AOT_PUB_CACHE"
PATH="$AOT_PATH" \
PUB_CACHE="$AOT_PUB_CACHE" \
QEMU_LD_PREFIX="$XC_SYSROOT" \
GEN_SNAPSHOT="$GEN_SNAPSHOT" \
python3 "$WORKSPACE_PY" --create-aot --app-path "$(pwd)"
if [[ -f "libapp.so.release" ]]; then
log "staging libapp.so.release → $BUNDLE_DIR/lib/libapp.so"
cp libapp.so.release "$BUNDLE_DIR/lib/libapp.so"
# AOT bundles must NOT ship kernel_blob.bin — its presence makes
# the embedder pick the debug code path even though libapp.so +
# a release engine are also present.
if [[ -f "$BUNDLE_DIR/data/flutter_assets/kernel_blob.bin" ]]; then
rm -f "$BUNDLE_DIR/data/flutter_assets/kernel_blob.bin"
echo " (removed kernel_blob.bin — release bundles use AOT only)"
fi
BUNDLE_RUNTIME="release"
else
echo "WARN: libapp.so.release not produced by create_aot.py;" >&2
echo " bundle stays debug-mode." >&2
fi
fi
echo
log "bundle assembled at $(pwd)/$BUNDLE_DIR"
log " runtime : $BUNDLE_RUNTIME"
log " drm_device: $DRM_DEVICE"
echo
echo "Run on host with:"
echo " $REPO_DIR/cmake-build-debug-clang/shell/homescreen -b $BUNDLE_DIR -d"
echo
echo "Provision onto a PiOS SD card:"
echo " $SCRIPT_DIR/build_pi.sh --pios $PIOS --skip-build --device /dev/sdX \\"
echo " --provision --bundle \$(pwd)/$BUNDLE_DIR"
+1301
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More