When you need to customize an existing recipe in Yocto, never edit the .bb file directly. Your changes will be wiped out the next time you pull updates from upstream.
Instead, use .bbappend files. They "append" to the original recipe, so your customizations survive upstream updates.
This guide covers bbappend from the basics to 5 practical patterns, based on Yocto Scarthgap 5.0 LTS.
What Is a bbappend File
A .bbappend file appends variables and tasks to a .bb recipe that lives in another layer.
The mechanism is straightforward. When BitBake loads a recipe, it checks for matching .bbappend files and appends their content to the end of the recipe before processing. This means settings in the .bbappend can override the original recipe.
meta-poky/recipes-example/someapp/someapp_1.0.bb ← original recipe
meta-mylayer/recipes-example/someapp/someapp_%.bbappend ← your additions
This separation matters for two reasons.
- Coexistence with upstream: Running
git pullonmeta-pokywon't touch your customizations inmeta-mylayer - Change visibility: You can see which layers modify what with
bitbake-layers show-appends
For layer creation, see the layer creation guide.
File Naming Rules
The bbappend filename must match the target recipe's filename.
Exact Version Match
someapp_1.0.bbappend → applies only to someapp_1.0.bb
someapp_1.1.bbappend → applies only to someapp_1.1.bb
If the version doesn't match exactly, the bbappend is silently ignored.
Using the % Wildcard (Recommended)
Updating the bbappend filename every time the recipe version changes is tedious. The % wildcard matches any version.
someapp_%.bbappend → applies to someapp_1.0.bb, someapp_2.3.bb, etc.
Verifying Your bbappend
Check that your bbappend is recognized with these commands.
# List all bbappend files and their target recipes
bitbake-layers show-appends
# Show all versions of a specific recipe (useful for version mismatch debugging)
bitbake-layers show-recipes someapp
Variable Operations
The most common operations in bbappend files are adding values to variables and overriding them.
Appending Values (:append)
:append adds a value to the end of a variable. You must include a leading space. Unlike +=, :append does not insert a space automatically.
# Correct (leading space)
SRC_URI:append = " file://my-patch.patch"
# Wrong (no space — merges with the previous value and breaks)
SRC_URI:append = "file://my-patch.patch"
You can also use +=, which auto-inserts a space, but :append is preferred because it's more explicit.
# This also works (+= auto-inserts a space)
SRC_URI += "file://my-patch.patch"
Removing Values (:remove)
DISTRO_FEATURES:remove = "bluetooth wifi"
Overriding Values
# Complete override
SOME_VARIABLE = "new-value"
FILESEXTRAPATHS — Search Path for Additional Files
When your bbappend adds files (patches, config files, etc.), you need to tell BitBake where to find them.
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
This single line has three critical details.
- Use
:=(immediate expansion):${THISDIR}refers to the directory containing the current file. With deferred expansion (=), it would resolve to the.bbfile's directory instead - The trailing colon
:is required: FILESEXTRAPATHS is a colon-separated list. Without the colon, paths merge and break - Use
:prepend: Ensures your path is searched before the default paths
Extending Tasks
You can add processing to recipe tasks (do_install, do_configure, etc.) with bbappend.
do_install:append() {
install -d ${D}${sysconfdir}
install -m 0644 ${WORKDIR}/myconfig.conf ${D}${sysconfdir}/
}
:append adds to the end of the task. The original task processing is preserved.
Use :prepend to add processing before the original task.
do_configure:prepend() {
# Runs before the original do_configure
cp ${WORKDIR}/my-makefile ${S}/Makefile
}
5 Practical Patterns
Here are five real-world use cases for bbappend files.
Pattern 1: Apply a Patch
The most basic use case. Apply a bug fix or feature patch to upstream source code.
Directory structure:
meta-mylayer/
recipes-example/
someapp/
someapp_%.bbappend
someapp/
0001-fix-memory-leak.patch
# someapp_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI:append = " file://0001-fix-memory-leak.patch"
${PN} expands to the package name (someapp in this case). ${THISDIR}/${PN} points to the someapp/ subdirectory next to the bbappend file.
Pattern 2: Add a Configuration File
Deploy a custom configuration file to the target.
meta-mylayer/
recipes-core/
busybox/
busybox_%.bbappend
files/
custom-inittab
# busybox_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " file://custom-inittab"
do_install:append() {
install -m 0644 ${WORKDIR}/custom-inittab ${D}${sysconfdir}/inittab
}
Pattern 3: Add a systemd Service
Add a systemd service file to an existing application for automatic startup. See the systemd auto-start guide for the full recipe walkthrough.
meta-mylayer/
recipes-example/
myapp/
myapp_%.bbappend
files/
myapp.service
# myapp_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " file://myapp.service"
SYSTEMD_SERVICE:${PN} = "myapp.service"
SYSTEMD_AUTO_ENABLE:${PN} = "enable"
FILES:${PN} += "${systemd_system_unitdir}/myapp.service"
do_install:append() {
install -d ${D}${systemd_system_unitdir}
install -m 0644 ${WORKDIR}/myapp.service ${D}${systemd_system_unitdir}/
}
Note: this pattern assumes the original .bb recipe already includes inherit systemd. The inherit directive is only valid in .bb and .bbclass files — it is not officially supported in .bbappend files. If the original recipe doesn't inherit the systemd class, you'll need to modify the recipe itself rather than using a bbappend.
Pattern 4: Change Compile Options
Use PACKAGECONFIG to modify build options for a recipe.
# curl_%.bbappend
# Enable OpenSSL support
PACKAGECONFIG:append = " openssl"
# Disable GnuTLS support
PACKAGECONFIG:remove = "gnutls"
PACKAGECONFIG is an option management mechanism supported by many recipes. Available options are defined in the recipe's .bb file as PACKAGECONFIG[xxx] entries.
For autotools-based recipes, you can also add configure options directly.
EXTRA_OECONF:append = " --enable-my-feature"
Pattern 5: Add Dependencies
Add build-time or runtime dependencies.
# mypackage_%.bbappend
# Build-time dependency
DEPENDS:append = " libssl"
# Runtime dependency (${PN} specifies which package)
RDEPENDS:${PN}:append = " python3"
RDEPENDS requires ${PN} because it's a per-package variable. Without ${PN}, BitBake doesn't know which package the dependency belongs to.
Common Troubleshooting
bbappend Not Being Applied
# Check if the bbappend is recognized
bitbake-layers show-appends | grep someapp
# Check if the layer is registered in bblayers.conf
bitbake-layers show-layers
The most common causes are version mismatch (not using %) and the layer not being registered.
Variable Values Look Wrong
# Scarthgap's recommended debugging command
bitbake-getvar -r someapp SRC_URI
bitbake-getvar -r someapp FILESEXTRAPATHS
bitbake-getvar shows the final value of a variable and which file set it.
File Not Found (do_fetch Error)
Usually a FILESEXTRAPATHS misconfiguration.
- Did you use
:=instead of=? - Did you forget the trailing colon
:? - Does the
files/directory path match what FILESEXTRAPATHS points to?
Wrapping Up
bbappend is the correct way to customize existing recipes in Yocto. The essentials are few.
- Name files
recipename_%.bbappend(use the%wildcard) - For additional files, set
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"(:=and trailing colon required) - Add values with
:append(don't forget the leading space) - Extend tasks with
do_install:append() { ... } - Debug with
bitbake-layers show-appendsandbitbake-getvar
Once you've mastered the basics, consider optimizing your build environment too.
To go deeper into bbappend and recipe customization, these books are excellent references. Yocto Project Customization focuses specifically on custom layer design patterns.