A .bbappend file is Yocto's mechanism for customizing existing recipes without modifying the original .bb file. It appends your changes to the recipe at parse time, keeping upstream updates and your customizations completely separate.
Never edit a .bb file directly — your changes will be wiped out the next time you pull updates from upstream.
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. The FILESEXTRAPATHS variable controls the file search path.
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 (introduced in Honister)
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 — both the unexpanded and expanded forms, along with the exact file and line number for each operation.
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?
FAQ
Can I use inherit in a bbappend file?
Officially, inherit is only supported in .bb and .bbclass files. While it may work in practice in some cases, the BitBake User Manual does not list .bbappend as a valid location for inherit. If the class you need isn't already inherited by the original recipe, modify the .bb file directly or create a new recipe.
What's the difference between :append and +=?
Both add values, but :append is an override-style operator that fires after all += assignments. :append does not insert a space automatically — you must add one. += inserts a space and is evaluated during parsing. In bbappend files, :append is preferred because it reliably fires after the original recipe's assignments.
Can I have multiple bbappend files for the same recipe?
Yes. If multiple layers each have a bbappend for the same recipe, BitBake applies them in the order layers are listed in bblayers.conf. The last layer's bbappend wins for conflicting variable assignments. Use bitbake-layers show-appends to check the order.
How do I override a variable set in the original recipe?
Use a simple assignment (=). Since bbappend content is appended after the original recipe, a plain = in the bbappend will override whatever the .bb file set. For variables that are additive (like SRC_URI), use :append instead so you don't lose the original values.
Does the directory structure inside my layer matter?
Yes. The bbappend must be in the same relative path as the original recipe. If the recipe is at meta-poky/recipes-core/busybox/busybox_1.36.1.bb, your bbappend should be at meta-mylayer/recipes-core/busybox/busybox_%.bbappend. BitBake matches by recipe name, not by directory, but following the same structure is a strong convention that makes layers readable.
What happens if my bbappend targets a recipe that doesn't exist?
By default, BitBake silently ignores orphaned bbappend files. To catch this, add BB_DANGLINGAPPENDS_WARNLEVEL = "error" to your local.conf. This makes BitBake fail with an error when a bbappend has no matching recipe — very useful for catching stale bbappend files after recipe removals or renames.
Can I delete a file that the original recipe installs?
Yes. Use do_install:append() with rm to remove files after the original do_install runs.
do_install:append() {
rm -f ${D}${bindir}/unwanted-binary
}
Alternatively, use the PACKAGES and FILES variables to exclude files from the final package without deleting them from the build directory.
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.
Related articles: