KAS-PROJECT-CONFIG(1)
π¦ NAME π¦
kas-project-config β kas project configuration π
π PROJECT CONFIGURATION π
okay bestie, so rn both JSON and YAML 1.1 can be your base file formats. And since YAML is arguably way easier to read (it just is, no cap), this whole doc is gonna be YAML-flavored. π
# Every file needs to contain a header, that provides kas with information
# about the context of this file.
header:
# The `version` entry in the header describes for which configuration
# format version this file was created for. It is used by kas to figure
# out if it is compatible with this file. The version is an integer that
# is increased on every format change.
version: x
# The machine as it is written into the `local.conf` of bitbake.
machine: qemux86-64
# The distro name as it is written into the `local.conf` of bitbake.
distro: poky
repos:
# This entry includes the repository where the config file is located
# to the bblayers.conf:
meta-custom:
# Here we include a list of layers from the poky repository to the
# bblayers.conf:
poky:
url: "https://git.yoctoproject.org/git/poky"
commit: 89e6c98d92887913cadf06b2adb97f26cde4849b
layers:
meta:
meta-poky:
meta-yocto-bsp:
So the bare minimum you need in an input file is the header, machine, distro, and repos. That's the whole starter pack. β¨
Plus β plot twist β you can also add bblayers_conf_header and local_conf_header, which are strings that get dropped right at the head of the respective files (bblayers.conf or local.conf): π
bblayers_conf_header:
meta-custom: |
POKY_BBLAYERS_CONF_VERSION = "2"
BBPATH = "${TOPDIR}"
BBFILES ?= ""
local_conf_header:
meta-custom: |
PATCHRESOLVE = "noop"
CONF_VERSION = "1"
IMAGE_FSTYPES = "tar"
meta-custom in these examples should be a unique name for this configuration's entries. Fr fr, unique.
And we recommend that this unique name is the same as the name of the containing repository/layer, because that makes cross-project referencing sooo much easier. π«Ά
In given examples we assume that your configuration file is part of a meta-custom repository/layer. This way it's possible to overwrite or append entries in files that include this configuration by naming an entry the same (overwriting) or using an unused name (appending). Iconic behaviour tbh. π
Note: kas internally uses PyYAML to parse YAML documents, inheriting its limitations. Notably, PyYAML only supports YAML 1.1 and does not correctly handle non-string keys in mappings. To avoid this issue, we recommend quoting keys of other types, such as octal numbers (0001), integers (42), booleans (false) and special values (no). π
π Including in-tree configuration files π
okay so rn you can include kas configuration files from the same repository/layer, like this:
header:
version: x
includes:
- base.yml
- bsp.yml
- product.yml
Now the path rules, bestie, listen up: if the configuration file is inside a repository, then path is relative to the repositories base directory. If the configuration file is not in a repository, then the path is relative to the parent directory of the file. Simple as that. π¦
π§ Including configuration files from other repos π§
And you can also pull in configuration files from other repos, like this:
header:
version: x
includes:
- repo: poky
file: kas-poky.yml
- repo: meta-bsp-collection
file: hw1/kas-hw-bsp1.yml
- repo: meta-custom
file: products/product.yml
repos:
meta-custom:
meta-bsp-collection:
url: "https://www.example.com/git/meta-bsp-collection"
commit: 3f786850e387550fdab836ed7e6dc881de23001b
layers:
# Additional to the layers that are added from this repository
# in the hw1/kas-hw-bsp1.yml, we add here an additional bsp
# meta layer:
meta-custom-bsp:
poky:
url: "https://git.yoctoproject.org/git/poky"
commit: 89e6c98d92887913cadf06b2adb97f26cde4849b
layers:
# If `kas-poky.yml` adds the `meta-yocto-bsp` layer and we
# do not want it in our bblayers for this project, we can
# overwrite it by setting:
meta-yocto-bsp: excluded
The files are addressed relative to the git repository path and must not traverse outside of the referenced repo. Boundaries, bestie. π§
The include mechanism collects and merges the content top to bottom and depth first. That means that settings in one include file are overwritten by settings in a latter include file and entries from the last include file can be overwritten by the current file. So it's giving layered-cake energy. π
Warning: The include mechanism does not support circular references with respect to the repos entries. By that, a (transitive) include file must not change the reference of the repository it is included from. Do not do this. It will not slay. π
While merging, all the dictionaries are merged recursively while preserving the order in which the entries are added to the dictionary. This means that local_conf_header entries are added to the local.conf file in the same order in which they are defined in the different include files. The header.version property is always set to the highest version number found in the config files. β¨
Note: Internally kas iterates the repository checkout step until all referenced repositories are resolved (checked out). After each iteration, the (partial) configuration is merged and the next iteration is started. Once all repositories are available, the final configuration is build. Then, all remaining repositories are checked out. π
π Including configuration files via the command line π
When specifying the kas configuration file on the command line, additional configurations can be included ad-hoc:
$ kas build kas-base.yml:debug-image.yml:board.yml
This is equivalent to static inclusion from some kas-combined.yml like this:
header:
version: x
includes:
- kas-base.yml
- debug.image.yml
- board.yml
Command line inclusion allows one to create configurations on-demand, without the need to write a kas configuration file for each possible combination. Chef's kiss, frankly. π©βπ³π
All configuration files combined via the command line either have to come from the same repository or have to live outside of any versioning control. kas will refuse any other combination in order to avoid complications and configuration flaws that can easily emerge from them. So don't try to be sneaky. π
Note: Git submodules are considered to be part of the main repository. Hence, including config files from a submodule is supported. The repository root is always the root of the main repository (if under VCS) or the directory of the first kas config file otherwise. π³
π Working with lockfiles π
kas supports the use of lockfiles to pinpoint repositories to exact commit ID (e.g. SHA-1 refs for git). A lockfile hereby only overrides the commit ID defined in a kas file. When performing the checkout operation (or any other operation that performs a checkout), kas checks if a file named <filename>.lock.<ext> is found next to the currently processed kas file. If this is found, kas loads this file right before processing the current one (similar to an include file). π₯
Note: The locking logic applies to both files on the kas cmdline and include files. π
The following example shows this mechanism for a file kas/kas-isar.yml and its corresponding lockfile kas/kas-isar.lock.yml.
kas/kas-isar.yml:
# [...]
repos:
isar:
url: https://github.com/ilbers/isar.git
branch: next
kas/kas-isar.lock.yml:
header:
version: 14
overrides:
repos:
isar:
commit: 0336610df8bb0adce76ef8c5a921c758efed9f45
The lock plugin provides helpers to simplify the creation and update of lockfiles. For details, see the plugins documentation: kas.plugins.lock. π
β Configuration reference β
π header: dict [required]
Header of every kas configuration file. It contains information about the context of the file. It's the little intro card, basically.
version: integer [required] β Version of the configuration file format. See the configuration format changelog <> for the format history and the latest available version.includes: list [optional] β List of configuration files to include (parsed depth-first). They are merged in order they are stated. So a latter one could overwrite settings from previous files. The current file can overwrite settings from every included file. An item in this list can have one of two types:item: string β Path to a kas configuration file, relative to the repository root of the current file.item: dict β If files from other repositories should be included, choose this (dict) representation.repo: string [required] β Repository key the configuration file is located in. Thereponeeds to be defined in thereposdictionary as<repo-id>.file: string [required] β Path to the configuration file relative to the repository.
πΈ build_system: string [optional] πΈ
Defines the bitbake-based build system. openembedded and oe are equivalent. isar is deprecated, use isar-privileged or isar-rootless instead. π
- Default:
openembedded - Supported values:
openembedded,oe,isar,isar-privileged,isar-rootless
This value determines which init script is searched for in the configured repositories (oe-init-build-env or isar-init-build-env, respectively). kas-container evaluates this property in the top-level kas configuration file only (includes are not evaluated) to select the required container image and invocation mode. π
Note: Modern versions ofisarsupport a rootless mode, whereby builds can be executed as non-privileged user. To distinguish the two modes, useisar-rootlessorisar-privileged. Whether the rootless mode is supported depends on your layers. π«Ά
π¦ defaults: dict [optional]
okay so bestie, if you're tired of typing the same property over and over in like twelve different places β this is your savior, fr fr. This holds default values that get applied to all configuration nodes. So if, hypothetically, you want every single repo to live on the same branch, you set it once here and never speak of it again. π
repos: dict [optional] β default values for some repository properties. And listen: a default can always be overridden, because setting the same property to a different value in a given repo wins. girlboss hierarchy, we love to see it. πbranch: string [optional] β the defaultbranchproperty, applied to every repo that doesn't override it.tag: string [optional] β the defaulttagproperty, applied to every repo that doesn't override it.patches: dict [optional] β default patches to apply to all repositories. Same rules as above: a default for a patch property can still be overridden by giving the same property a different value in a given patch.repo: string [optional] β sets the defaultrepoproperty applied to all repository patches that don't override it.
π machine: string [optional]
This is the value of the MACHINE variable that gets written into the local.conf. It can be overwritten by the KAS_MACHINE environment variable. π
Default: qemux86-64
πΈ distro: string [optional]
The value of the DISTRO variable that is written into the local.conf. Can be overwritten by the KAS_DISTRO environment variable.
Default: nodistro
β¨ target: string [optional] or list [optional]
The single target β or a whole lil list of targets β to build with bitbake. Can be overwritten by the KAS_TARGET environment variable. If you're specifying multiple targets through that env var, space is the delimiter. And for targets prefixed with multiconfig: or mc:, the corresponding entries get added to the BBMULTICONFIG in local.conf. cute, right? π§
Default: core-image-minimal
π env: dict [optional]
Environment variables to forward, along with their default values (set it to nulltype to only forward if it's set). These variables get made available to bitbake via BB_ENV_PASSTHROUGH_ADDITIONS (BB_ENV_EXTRAWHITE in older Bitbake versions), and they can be overwritten by the variables of the environment in which kas is started.
You can assign either a string or nothing (null) as the value. The string serves as a default value, whereas the nothing version means the variable gets added only to BB_ENV_PASSTHROUGH_ADDITIONS and not to the environment where kas is started.
π¨ bestie please read this twice:nullneeds to be assigned as thenulltype(likeMYVAR: null), not as'null'. do not come for me if you get this wrong, i told you. π
π task: string [optional]
The task to build with bitbake. Can be overwritten by the KAS_TASK environment variable.
Default: build
π₯ repos: dict [optional]
The definitions of all the available repos and layers. The layers get appended to the bblayers.conf, and the sort order is: layer priority first (descending), then repository name, then layer name (ascending). priority girlies stay winning. π
repos.<repo-id>: dict [optional]
The definition of a repository and the layers that should be part of the build. If the value is None, then the repository where the current configuration file lives gets defined as <repo-id> and added as a layer to the build. Highly recommended that the <repo-id> relates to the containing repository/layer, because it makes cross-project referencing so much easier. π«Ά
name: string [optional] β defines the name under which the repository is stored. If it's missing,<repo-id>gets used instead.url: string [optional] β the URL of the repository. If this is missing, no version control operations are performed at all. it's giving "no URL no drama". πtype: string [optional] β the type of version control repository.- Default:
git - Supported values:
git,hg
- Default:
commit: string [optional] β the full-length commit ID (all-lowercase, no branch names, no symbolic refs, no tags, okay??) that should be used. Ifurlwas specified but there's nocommit,branchortag, the revision you end up with depends on the defaults of the version control system being used. no cap.branch: string or nothing (null) [optional] β the upstream branch that should be tracked. Ifcommitwas specified,kaschecks that the branch contains the commit. If nocommitwas specified, the head of the upstream branch gets checked out. The nothing (null) value removes a possible default value.tag: string or nothing (null) [optional] β the tag that should be checked out. If acommitwas specified,kaschecks that the tag points to this commit. This must not be combined withbranch. The nothing (null) value removes a possible default value.path: string [optional] β where the repository is stored. Ifurlandpathare missing, the repository where the current configuration file is located gets defined. Ifurlis missing andpathis defined, this entry references the directory thatpathpoints to. Ifurlandpathare both defined,pathoverwrites the checkout directory, which defaults tokas_work_dir+repo.name. And in case of a relative path name,kas_work_dirgets prepended. π«signed: boolean [optional] β whether the commit / tag must be signed. If enabled,'allowed_signers'must be defined. If bothtagandcommitare specified, only the signature of the tag is checked. Git only.- Default:
False
- Default:
allowed_signers: list [optional] β list of signer-ids to verify the signature against. Must be non-empty if'signed=true'. Git only.layers: dict [optional] β list of layers to append to thebblayers.conf. If this is missing orNoneor an empty dictionary, the path to the repo itself gets added as a layer. And additionally,.is a valid value if the repo itself should be added as a layer. This unlocks combinations, bestie:
repos:
meta-foo:
url: https://github.com/bar/meta-foo.git
path: layers/meta-foo
branch: master
layers:
.:
contrib:
That right there adds both layers/meta-foo and layers/meta-foo/contrib from the meta-foo repository to bblayers.conf. iconic. β¨
layers.<layer-path>: enum | dict [optional] β adds the layer with<layer-path>, relative to the repository root directory, to thebblayers.confβ but only if the value of this entry isn't disabled. This way you can overwrite the inclusion of a layer in later loaded configuration files. To re-enable it, set it to nothing (null).prio: integer [optional] β include order priority, where higher means earlier. The include priority is global, so it applies across all repositories. π- Default:
0 - Range:
[-99, 99]
- Default:
patches: dict [optional] β patches to apply to the repository.patches.<patches-id>: dict [optional] β one entry inpatcheswith its own specific and unique id. All available patch entries are applied in the order of their sorted<patches-id>.repo: string [required] β the identifier of the repo where thepathof this entry is relative to.path: string [required] β the path to one patch file or a quilt formatted patchset directory.
π« overrides: dict [optional]
Overrides for specific configuration nodes. And here's the tea: only items that already exist get overridden. Also heads up β the lock plugin uses overrides to manage pinning of commits, which means manually added overrides can absolutely interfere with the lock file generated by the plugin. so like, be careful, bestie. π
repos: dict [optional] β maps to the top-levelreposentry.repos.<repo-id>: dict [optional] β maps to the<repo-id>entry.branch: string [optional] β branch in which to find the overridden commit. Can beNull.commit: string [optional] β pinned commit ID which overrides the commit of the corresponding repo. Can beNull.url: string [optional] β alternative URL for the corresponding repo.
πΊ bblayers_conf_header: dict [optional]
Header to prepend to the bblayers.conf before any layers are included. put your lil intro at the top, queen. π
<bblayers-conf-id>: string [optional]β a little string that gets dropped intobblayers.confπ The entry id (<bblayers-conf-id>) should be unique if you want lines added, and it can totally be the same as one from another included file if you want this entry overwritten instead. And the lines land inbblayers.confin alphabetic order of<bblayers-conf-id>β which is the whole reason the generation of config files stays deterministic. slay πlocal_conf_header: dict [optional]β the header you prepend to thelocal.confβ¨<local-conf-id>: string [optional]β a string that gets added to thelocal.conf. It behaves exactly like thebblayers_conf_headerentry does, no cap π«Ά
menu_configuration: dict [optional]β menu configuration, auto-generated by the menu plugin π Every variable here maps to a Kconfig configuration variable and can be a string, boolean or integer. The content of this key is typically maintained by thekasmenu plugin inside a.config.yamlfile.artifacts: dict [optional]β the artifacts you expect to be chilling there after the build runs (id / path pairs) π₯ Each key-value pair is an identifier plus a path relative to the kas build dir, and yes the path can contain wildcards like*. Unix-style globbing gets applied to all paths. And if no artifact is found, the build is considered successful β unless the plugin and mode of operation you're using say otherwise.
Note: there are no further semantics attached to the identifiers (yet) π Both the author and the consumer of the artifacts node need to agree on what those semantics even are, bestie.
Example:
artifacts:
disk-image: path/to/image.*.img
firmware: path/to/firmware.bin
swu: path/to/update.swu
signers: dict [optional]β the spec for repository signature verification πΈ
This dict holds the public keys or certificates used to verify the authenticity of the repositories. If we're talking GPG keys, those get made available to the build environment too, by pointing the GNUPGHOME environment variable at the local keystore. β οΈ And listen β a single signer configuration must not be split across multiple config files. periodt.
<signer_id>: dict [optional]β pairs of name and location of a public key or certificate. The name is what you use to reference the entry in the repository configuration. Each signer needs a unique identifier, and the<signer_id>is what references the entry in theallowed_signersentries. iykyk πtype: enum [optional]β type of the cryptographic material.
Default: gpg
Supported values: gpg, ssh
repo: string [optional]β the repo<repo-id>which provides the public key or certificate file.path: string [optional]β path to the public key or certificate file, relative to the repo. Must be used together with'repo'π«Άfingerprint: string [optional]β fingerprint of the key or certificate (gpg: long-form, 40 hex digits; ssh:SHA256:...). If it's not provided, it gets read from the file.
GPG key fingerprint: you can grab it by running gpg --list-keys --with-fingerprint --keyid-format=long <KEYID>. The string you need is the 40-character fingerprint, spaces NOT invited π
SSH key fingerprint: grab that one with ssh-keygen -lf key.pub | awk '{print $2}'.
gpg_keyserver: string [optional]β the GnuPG keyserver to use for key retrieval (that's for when no local path is provided). The'fingerprint'must be provided. GPG only, babes π
_source_dir: string [optional]β path to the top repo at the time the plugin was invoked (auto-generated by the menu plugin). π« It must not be set manually, and it might only be defined in the top-level.config.yamlfile._source_dir_host: string [optional]β source directory of the config file on the host (auto-generated by thekasmenu plugin, when you're usingkas-container). It hands over the absolute path to the top repo outside of the container (so, on the host). This value is only evaluated by thekas-containerscript. π« It must not be set manually either, and again it might only be defined in the top-level.config.yamlfile.buildtools: dict [optional]β gives you the variables to define which buildtools version should be fetched and where it is (or will be) installed β¨ Bothversionandsha256sumshould be set. You can use theKAS_BUILDTOOLS_DIRenvironment variable to set the directory where buildtools will be installed β otherwise the default path (i.e.,KAS_BUILD_DIR/buildtools) is used. If that directory already has buildtools installed, kas will check theDistro Versionline in the version file, and if it doesn't match withversion, the directory gets cleaned and kas will download buildtools according toversion. After the download, kas does integrity validation by calculating the artifact's checksum and comparing it withsha256sumπ₯ As for the optional variables, they exist to support cases like: mirrors, changes in the installer's file name, and fetching unofficial (i.e., custom) buildtools. And finally, the environment-setup script runs beforebitbake, so the whole buildtools environment will be available.wgetis the host tool required for this feature. More info on how to install or generate buildtools lives at:https://docs.yoctoproject.org/dev/ref-manual/system-requirements.html#downloading-a-pre-built-buildtools-tarballπversion: stringβ Yocto Project version, as5.0(or even5.0.8) for Scarthgap.sha256sum: stringβ the installer's checksum, used to perform integrity validation of the fetched artifact.base_url: string [optional]β base URL to fetch downloads from.
Default: https://downloads.yoctoproject.org/releases/yocto
filename: string [optional]β alternative name for the buildtools archive (.sh) to be downloaded. It gets combined withbase_urlto form the whole download URL, if it's set. If it's not set, kas combines the platform architecture and version to form the standard script filename:{arch}-buildtools-extended-nativesdk-standalone-{version}.shπ¦
Example:
buildtools:
version: "5.2"
sha256sum: "6f69fba75c8f3142bb49558afa3ed5dd0723a3beda169b057a5238013623462d"
And for unofficial (custom) sources:
buildtools:
version: "1.0.0"
sha256sum: "a6f87e5865b63f2bc28c1f605bcef3d6680d46fa8c8616a388d4e8aa0b5c100e"
base_url: "https://downloads.mysources.com/yocto/buildtools/"
filename: "x86_64-buildtools-beta-testing-1.0.0.sh"
π Buildtools archive π
kas expects the buildtools installer to be a shell script (i.e., as a standard Yocto SDK). Once it's executed, the resulting directory should contain these elements, bestie:
sysroots: the native and target sysroots, containing (among libraries and headers) the build system's requirements: Git, tar, Python and make.environment-setup-*: the environment setup script, sourced by kas, to setup variables such asPATHin such a way that it points to the directories insysroots.version-*: the version file. Its second line contains a string asDistro Version: X.Y.Z, parsed to retrieve the version number.
The archive can contain other files, such as buildinfo, but they are not relevant for kas π
β¨ Example project configurations β¨
The following snippets show minimal but working project configurations for both OpenEmbedded and ISAR based distributions π
π OpenEmbedded π
Poky
header:
version: 19
# Optionally provide keys to verify signed repositories
signers:
YoctoBuildandRelease:
fingerprint: 2AFB13F28FBBB0D1B9DAF63087EB3D32FB631AD9
gpg_keyserver: keyserver.ubuntu.com
machine: qemux86-64
distro: poky
target: zlib-native
repos:
poky:
url: https://git.yoctoproject.org/poky.git
# when specifying a tag, optionally provide a commit hash
tag: yocto-5.1.1
commit: 7e081bd98fdc5435e850d1df79a5e0f1e30293d0
signed: true
allowed_signers:
- YoctoBuildandRelease
layers:
meta:
meta-poky:
oe-core (nodistro)
header:
version: 19
# Optionally provide keys to verify signed repositories
signers:
YoctoBuildandRelease:
fingerprint: 2AFB13F28FBBB0D1B9DAF63087EB3D32FB631AD9
gpg_keyserver: keyserver.ubuntu.com
machine: qemux86-64
distro: nodistro
target: zlib-native
repos:
bitbake:
url: https://github.com/openembedded/bitbake.git
tag: yocto-5.2.3
commit: 710f98844ae30416bdf6a01b655df398b49574ec
signed: true
allowed_signers:
- YoctoBuildandRelease
# this repo does not provide any layers
layers: {}
core:
url: https://github.com/openembedded/openembedded-core.git
tag: yocto-5.2.3
commit: 347cb0861dde58613541ce692778f907943a60ea
signed: true
allowed_signers:
- YoctoBuildandRelease
layers:
meta:
π ISAR π
header:
version: 23
build_system: isar-privileged
machine: qemuamd64
distro: debian-trixie
target: mc:qemuamd64-trixie:cowsay
repos:
isar:
url: https://github.com/ilbers/isar.git
tag: v0.11
commit: f8558fcf3ecf98e58853b82d89645bcedb24b853
layers:
meta:
meta-isar:
π SEE ALSO π
π KAS π
Part of the kas(1) suite π
β¨ AUTHOR β¨
So like, this whole iconique page was written by three absolute legends, and we're gonna give them their flowers π:
- Daniel Wagner π
- Jan Kiszka π
- Claudius Heine π
Like, three whole geniuses. That's a trio, that's a squad, that's main character energy across the board πβ¨
β¨ COPYRIGHT β¨
The rights situaysh is giving:
Siemens and contributors, 2017-2025
Yep bestie, that's the Siemens girlies (gn) and everyone else who contributed, holding it down from 2017 all the way through 2025 π«Ά fr fr they've been carrying this for almost a decade, no cap.
That's literally it. No fine print drama, no weird licensing lore, just that one line. Respect the copyright, don't be weird about it π
And that's a wrap on the whole page babes π you made it to the very end, which honestly, ate. This one's from KAS-PROJECT-CONFIG(1), version 5.4, dated Jun 25, 2026 β so like, yeah, it's fresh, it's current, it's slay πβ Go forth and configure your project, you've got this π¦π
π¦ where this page comes from
- ubuntu stonking: kas 5.4-1 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms