How avocado.yaml is read
The load pipeline
Section titled “The load pipeline”Every command that reads avocado.yaml (or whatever -C/--config points at) runs the same steps, in this order:
- Parse the YAML. The CLI uses
serde_yaml0.9, which follows YAML 1.2. See YAML 1.2 rules below. - Compose. The
avocado.yamlof every fetched extension (source: { type: package | git | path }) is merged into your config:- The extension’s own
extensions.<name>block is always merged. It’s found by exact name, then by the name with a target suffix stripped, then, if the fetched file defines exactly one extension, that one. It’s deep-merged into yours, and your keys win on conflicts: the fetched file only fills in keys you didn’t set. - An
sdk.compile.<section>comes in when one of the extension’s packages refers to it (compile: <section>), or whensource.includematches it. - Everything else comes in only if
source.includematches it:sdk.packages.<pkg>,provision_profiles.<profile>,rootfs,initramfs. For example, a fetched extension’s ownsdk.packagesnever reach your SDK unless you includesdk.packages.*. Where both files define the same entry, yours wins. distro,default_target,supported_targetsand the base SDK settings (sdk.image,sdk.container_args) always come from your file. An extension can never override them.
- The extension’s own
- Template. Every
{{ ... }}in every string, including mapping keys, is resolved. See Templating. - Type-check the sections that have a fixed shape:
distro,sdk,kernel,rootfs,initramfs,permissions,runtimes.<name>,signing_keys,connect,repos. - The
extensionssection, and some runtime keys, are not type-checked. Each command reads the keys it cares about straight from the YAML when it needs them.
Unknown keys are silently ignored
Section titled “Unknown keys are silently ignored”Nothing in the CLI rejects, or even warns about, a key it doesn’t recognize. This applies at every level. A typo quietly does nothing:
runtimes: dev-local: board: qemuarm64 # ignored: the key is `target_board`extensions: app: enable_service: # ignored: the key is `enable_services` - app.serviceIn the first case, {{ avocado.target.board }} then falls back to the target name, so a Jetson build of dev-local would pull avocado-bsp-jetson-orin-nano-devkit rather than avocado-bsp-qemuarm64.
The only places that do reject unknown keys:
- The
version: { file, key, format }block on extensions. - Mixing the two forms of a named-or-single section (below).
To catch typos, validate with the JSON Schema published by this site. It’s stricter than the CLI on purpose.
Named-or-single sections
Section titled “Named-or-single sections”kernel, rootfs, initramfs and permissions each accept two shapes. The CLI tells them apart by looking at the keys:
# Single form: the keys are config fields. The CLI stores it under the name "default".kernel: package: kernel-image version: '*'
# Named form: no key is a config field, so every key is an entry name.kernel: yocto-6-6: { package: kernel-image, version: '6.6.*' } lts: { package: kernel-image, version: '>= 6.12' }The rules:
- If any top-level key matches a field name, the whole block is treated as the single form.
- A mix of field names and other keys is a hard error. This is one of the few typo checks the CLI has.
target-<name>:andkernel-<spec>:keys are ignored when counting. They’re overrides, not entry names.- Runtimes refer to entries by name (
kernel: yocto-6-6), or define one inline (kernel: { cmdline_extra: ... }). A runtime with no reference uses the entry nameddefault. If there is nodefaultand the map has exactly one entry, that entry is used.
The field names the CLI counts are: package, version, compile, install, image, cmdline, cmdline_extra for kernel. For rootfs and initramfs, they’re packages, dependencies, filesystem, overlay, image, post_install, permissions. For permissions, they’re users, groups.
Aliases
Section titled “Aliases”These spellings are accepted and mean the same thing:
| You can write | Means |
|---|---|
runtime: |
runtimes: |
provision: |
provision_profiles: |
distro.version |
distro.release |
dependencies: (in sdk, sdk.compile.<s>, rootfs, initramfs) |
packages: |
source: { type: repo } |
source: { type: package } |
Package entries
Section titled “Package entries”Every packages: map uses the package name as the key. The value can be:
| Value | Meaning |
|---|---|
'*' |
Any version. The lock pins whatever was installed first. |
'1.2.3' |
That version |
{ version: '1.2.3' } |
Same as above |
{ compile: <section>, install: <script> } |
Not from the feed. It’s built by sdk.compile.<section>, then install copies it into the extension. Extensions only. Both keys are required: in 1.0.0-rc.5, ext build never runs an install script that has no compile. (At least one official reference uses the install-only form.) |
{ extensions: <name> } (optionally with vsn: or config:) |
Legacy extension-to-extension dependency. It’s logged and not installed. Use depends_on instead. |
Any other object, for example { ver: '1.0' }, is silently skipped. The package isn’t installed, and no error is raised.
Package keys are also where {{ avocado.kernel.version }} is substituted. See Kernel modules in extensions.
YAML 1.2 rules
Section titled “YAML 1.2 rules”serde_yaml 0.9 follows YAML 1.2. YAML 1.1 habits from Ansible or older tools will bite you:
yes,no,on,offare strings, not booleans.image: { verity: yes }is rejected: that key requires a real boolean and says so. Most other boolean keys (for examplereload_service_manager, orenabledin a runtime’s extension list) just ignore a non-boolean and use their default.- Quote your versions. An extension
version: 1.10is a float. The CLI converts it through a float to an integer, so it becomes"1".version: 1.0.0happens to work because it isn’t a valid number. Always writeversion: '1.10'. release: 2024is fine. That field accepts an integer or a string.
- Every script, overlay and file path is relative to the source directory. That’s
src_dirif you set it (itself relative to the config file), otherwise the directory containing the config file. - Inside the SDK container, the source directory is
/opt/src. Scripts are run asbash '<relative path>', so write paths inside them relative to the source directory, as the generatedcompile.shexamples do. For a fetched extension, the CLI first changes into that extension’s tree. - For fetched extensions, paths in the extension’s own
avocado.yamlare relative to that extension’s tree, not yours. avocado.yamlis the default config name, and-C/--configchanges it. Most commands also look foravocado.locknext to the config.
cli_requirement
Section titled “cli_requirement”cli_requirement: ">=0.41.0" is a semver requirement, checked on every load. A running CLI that doesn’t satisfy it refuses to run.
Pre-releases get special treatment. The CLI first tries its exact version (so =1.0.0-rc.1 can pin a release candidate), then tries again with the pre-release tag stripped. So 1.0.0-rc.5 satisfies >=1.0.0, even though strict semver says it shouldn’t.