32blogby Studio Mitsu

Yocto bbappend: A Practical Guide with 5 Patterns

Learn how to customize existing Yocto recipes using bbappend files. Covers naming rules, variable operations, and 5 real-world patterns based on Scarthgap 5.0 LTS.

by omitsu9 min read

This article contains affiliate links.

On this page

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 pull on meta-poky won't touch your customizations in meta-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.

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.

bash
# 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.

bash
# 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.

bash
# This also works (+= auto-inserts a space)
SRC_URI += "file://my-patch.patch"

Removing Values (:remove)

bash
DISTRO_FEATURES:remove = "bluetooth wifi"

Overriding Values

bash
# 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.

bash
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

This single line has three critical details.

  1. Use := (immediate expansion): ${THISDIR} refers to the directory containing the current file. With deferred expansion (=), it would resolve to the .bb file's directory instead
  2. The trailing colon : is required: FILESEXTRAPATHS is a colon-separated list. Without the colon, paths merge and break
  3. 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.

bash
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.

bash
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
bash
# 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
bash
# 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
bash
# 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.

bash
# 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.

bash
EXTRA_OECONF:append = " --enable-my-feature"

Pattern 5: Add Dependencies

Add build-time or runtime dependencies.

bash
# 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

bash
# 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

bash
# 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.

bash
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-appends and bitbake-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: