mirror of
https://github.com/toyota-connected/emb_cli.git
synced 2026-06-21 07:19:37 -07:00
docs(cross): document + demonstrate app-layer extends
Add a README subsection ("Layered manifests: extends, board → project → app")
covering both extends forms (<board> and <dir>#<target>) and the merge rules,
with project and app manifest snippets.
Add examples/cross/app-extends.emb.yaml: an app target that extends the rpi
family file's rpi5-bookworm target (which extends the board) and overlays an
app-specific dev package — a real three-layer chain. A cross_command test
--dry-runs it so it stays valid.
Signed-off-by: Joel Winarske <joel.winarske@gmail.com>
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
"libglib",
|
||||
"libgstreamer",
|
||||
"libinput",
|
||||
"libnl",
|
||||
"libpipewire",
|
||||
"libsecret",
|
||||
"libsystemd",
|
||||
|
||||
@@ -589,6 +589,54 @@ emb cross . --target local # …the same, explicit (or --target host)
|
||||
emb cross . --target rpi5 --build
|
||||
```
|
||||
|
||||
#### Layered manifests: `extends` (board → project → app)
|
||||
|
||||
emb ships a **board library** — hardware/OS definitions for known boards under
|
||||
its own `boards/` directory (e.g. `rpi5-bookworm`: triple, toolchain version,
|
||||
sysroot image, partition, cpu tuning, the base GUI stack). A manifest pulls one
|
||||
in with `cross.extends` so a project never re-spells hardware facts:
|
||||
|
||||
```yaml
|
||||
# ivi-homescreen/.emb/raspberry-pi.emb.yaml — the PROJECT layer
|
||||
cross:
|
||||
targets:
|
||||
rpi5-bookworm:
|
||||
extends: rpi5-bookworm # ← emb board (hardware/OS)
|
||||
backends: { drm-kms-egl: { BUILD_BACKEND_DRM_KMS_EGL: 'ON' } }
|
||||
augment: [ { pkg: libdisplay-info, min: "0.2.0", build: meson } ]
|
||||
sysroot: { dev_packages: [ libgstreamer1.0-dev ] } # added to the board's
|
||||
```
|
||||
|
||||
`extends` takes two forms:
|
||||
|
||||
| Form | Resolves to |
|
||||
|---|---|
|
||||
| `<board>` | a target in emb's board library (the **hardware** layer) |
|
||||
| `<dir>#<target>` | a target in another emb project at `<dir>` (the **project** layer) |
|
||||
|
||||
The second form lets an **app** build on a project (e.g. ivi-homescreen) and add
|
||||
only what is app-specific — typically **plugin configuration**, which depends on
|
||||
the plugins the app ships, not on the embedder or the board:
|
||||
|
||||
```yaml
|
||||
# my-flutter-app/.emb/app.emb.yaml — the APP layer
|
||||
# (ivi-homescreen checked out alongside the app)
|
||||
cross:
|
||||
targets:
|
||||
rpi5-bookworm:
|
||||
extends: '../ivi-homescreen#rpi5-bookworm' # ← project target (→ board)
|
||||
defines: { DISABLE_PLUGINS: 'OFF', PLUGINS_DIR: '../ivi-homescreen-plugins/plugins' }
|
||||
sysroot: { dev_packages: [ libnl-3-dev ] }
|
||||
```
|
||||
|
||||
The chain collapses **app ⊕ project ⊕ board** with the same merge rules at every
|
||||
layer: nested maps deep-merge; `cpu_flags` and `backends` **replace** (each is a
|
||||
complete statement); `sysroot.dev_packages` **union** (each layer adds to the
|
||||
stack below it). `<dir>` is resolved relative to the extending manifest's project
|
||||
root (the `.emb/` parent, else the file's directory); cross-project reference
|
||||
cycles are rejected. The board library location can be overridden with
|
||||
`EMB_BOARDS_DIR` (it otherwise ships with emb).
|
||||
|
||||
#### Reproducible builds (`emb.lock`)
|
||||
|
||||
A cross resolve pins what it actually used to **`emb.lock`** at the project root,
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# App layer demo — a Flutter app that builds on a project (board → project → app).
|
||||
#
|
||||
# `extends: <ref>#<target>` pulls in raspberry-pi-family.emb.yaml's rpi5-bookworm
|
||||
# target — which itself `extends` the rpi5-bookworm board — then overlays only
|
||||
# what is app-specific. Here that's one extra plugin -dev package, merged onto
|
||||
# the project + board sysroot stack; a real app would typically also set its own
|
||||
# plugin config (DISABLE_PLUGINS / PLUGINS_DIR). Hardware (toolchain, image, cpu)
|
||||
# comes from the board; backends/augment from the project.
|
||||
#
|
||||
# emb cross app-extends.emb.yaml --target rpi5-bookworm --dry-run
|
||||
#
|
||||
# In a real layout the app and the project live in separate repos checked out
|
||||
# side by side, so the ref is a directory, e.g.:
|
||||
# extends: '../ivi-homescreen#rpi5-bookworm'
|
||||
id: my-flutter-app
|
||||
type: app
|
||||
supported_archs: [arm64]
|
||||
supported_host_types: [ubuntu, fedora]
|
||||
|
||||
cross:
|
||||
targets:
|
||||
rpi5-bookworm:
|
||||
extends: 'raspberry-pi-family.emb.yaml#rpi5-bookworm'
|
||||
sysroot:
|
||||
dev_packages: [libnl-3-dev] # an app plugin dep, added to the stack
|
||||
@@ -326,6 +326,21 @@ void main() {
|
||||
}
|
||||
});
|
||||
|
||||
test(
|
||||
'--dry-run plans the app-extends example (app → project → board)',
|
||||
() async {
|
||||
final app = p.join('examples', 'cross', 'app-extends.emb.yaml');
|
||||
final code = await run([
|
||||
'cross',
|
||||
'--dry-run',
|
||||
'--target',
|
||||
'rpi5-bookworm',
|
||||
app,
|
||||
]);
|
||||
expect(code, ExitCode.success.code);
|
||||
},
|
||||
);
|
||||
|
||||
// Every shipped example must parse -> dispatch -> plan with no side effects:
|
||||
// this validates all of the listed use cases hermetically.
|
||||
test('--dry-run plans every example manifest', () async {
|
||||
|
||||
Reference in New Issue
Block a user