Changing Yocto Recipes

How to change an existing recipe

Sooner or later you will find a recipe that is almost what you need.

Maybe a vendor recipe builds the right application, but you need to add a patch. Maybe an upstream recipe installs a default configuration file, but your product needs a different one. Maybe the recipe needs an extra dependency for your board or image.

The tempting thing is to open the original .bb file and edit it directly.

Editing an upstream or vendor recipe directly makes upgrades painful. Your change is mixed into someone else’s layer, so it is easy to lose when the layer is updated. It also makes it harder to see which parts of the build are project customisation and which parts came from upstream.

The recommended Yocto pattern is:

  • leave the original .bb recipe alone
  • create a .bbappend file in your own layer
  • put your extra files, patches, and metadata into that append

That keeps your project changes visible, reviewable, and easier to carry forward.

What a .bbappend File Does

A .bbappend file is BitBake metadata that is added to an existing recipe.

It does not build a separate recipe. It extends a .bb recipe that BitBake has already found.

For example, if another layer provides:

example_1.2.bb

then your layer can provide:

example_1.2.bbappend

When BitBake parses example_1.2.bb, it also applies matching append files. The final recipe is the combination of the original recipe plus the changes from the append.

The filename is important. BitBake matches the append to the recipe by recipe name and version.

Exact version match:

example_1.2.bbappend -> example_1.2.bb

Wildcard version match:

example_1.%.bbappend -> example_1.2.bb, example_1.3.bb, etc
example_%.bbappend   -> example_1.2.bb, example_2.3.bb, etc

Use an exact version when the change is known to only work with that recipe version. Use % when the change should apply across recipe version updates.

Where Appends Live

Put .bbappend files in your own layer, using the same broad recipe category as the recipe you are extending.

Given that you will normally be changing existing packages, then they would tend to live in the BSP layer if they are to do with board bring-up (TF-A, U-Boot, kernel, etc) or the Distro layer for most other recipes.

The path normally mirrors the original recipe structure:

upstream layer:
  meta-vendor/recipes-apps/example/example_1.2.bb

your layer:
  meta-my-software/recipes-apps/example/example_1.2.bbappend

This mirroring is not for BitBake. It also helps humans. When someone looks at your layer, they can quickly see which upstream recipe your append modifies.

The layer’s conf/layer.conf must include .bbappend files in BBFILES. The layers created earlier use the standard pattern:

BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
            ${LAYERDIR}/recipes-*/*/*.bbappend"

That means this path is found:

meta-my-software/recipes-apps/example/example_%.bbappend

The layer must also be enabled in conf/bblayers.conf. If the layer is not in BBLAYERS, BitBake will ignore the layer and not see the append at all.

Checking That BitBake Found the Append

Before debugging the contents of a .bbappend, first check that BitBake can see it.

Show enabled layers:

bitbake-layers show-layers

Show recipes and the layer that provides them:

bitbake-layers show-recipes example

Show all append files that BitBake has discovered:

bitbake-layers show-appends

For a specific recipe, it is often easier to use:

bitbake-layers show-appends example

You should expect to see your .bbappend path listed against the recipe it is modifying. If it is not listed, BitBake is not applying it.

You can also inspect the final value of a variable after all recipe and append metadata has been processed:

bitbake-getvar -r example SRC_URI
bitbake-getvar -r example DEPENDS

This is useful because it shows both the final value and where the value was set or changed.

Common Things to Change

Most .bbappend files are small. They usually adjust variables, add files, apply patches, or extend an existing task.

Adding or Overriding Variables

You can set a variable if your project needs a different value:

SUMMARY = "Example application with project customisations"

Only do this when you really want to replace the value. For list-style variables, you normally extend the existing value instead.

Using :append, :prepend, and :remove

Use :append to add to the final value:

PACKAGECONFIG:append = " ssl"

Remember that :append does not add a space for you. For space-separated lists, include the leading space:

RDEPENDS:${PN}:append = " bash"

${PN} means the main package name for this recipe. If the recipe is example_1.2.bb, then ${PN} is normally example.

Use :prepend when the new value must come first:

EXTRA_OECONF:prepend = "--enable-project-mode "

Use :remove to remove an item that came from the original recipe or another layer:

PACKAGECONFIG:remove = "x11"

Adding and Removing Dependencies

DEPENDS is for build-time recipe dependencies. Use it when the recipe needs headers, libraries, or tools while building:

DEPENDS:append = " openssl"
DEPENDS:remove = "libx11"

RDEPENDS:${PN} is for runtime package dependencies. Use it when the installed package needs another package on the target:

RDEPENDS:${PN}:append = " bash"
RDEPENDS:${PN}:remove = "busybox-syslog"

Extending SRC_URI

SRC_URI lists the inputs for the recipe. A .bbappend can add more inputs, such as patches or local files:

SRC_URI:append = " \
    file://0001-change-default-message.patch \
    file://example.conf \
"

Files listed with file:// must be somewhere BitBake knows to search. In a normal recipe, BitBake automatically searches the recipe’s own files/ directory. In a .bbappend, the extra files are in your layer, so you normally extend the search path too.

Using FILESEXTRAPATHS

This is the common pattern:

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

or

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}$:"

${THISDIR} is the directory containing the file currently being parsed. In this case, it is the directory containing your .bbappend.

${PN} is the package name which allow for the common usa case of having the files located in a directory with the same name as the recipe. This is especially useful when you have multiple recipes in the same directory and you want to separate out the additional files.

If your append is:

meta-my-software/recipes-apps/example/example_%.bbappend

then:

${THISDIR}/files

points to:

meta-my-software/recipes-apps/example/files

and

${THISDIR}/${PN}

points to:

meta-my-software/recipes-apps/example/example

Extending an Existing Task

You can add commands to an existing task without replacing the whole task.

For example, to install an extra configuration file:

do_install:append() {
    install -d ${D}${sysconfdir}/example
    install -m 0644 ${UNPACKDIR}/example.conf ${D}${sysconfdir}/example/example.conf
}

This runs after the original recipe’s do_install() task.

${UNPACKDIR} is the recipe’s unpack area. Local files from SRC_URI, such as file://example.conf, are available there after fetch and unpack have completed.

Complete Worked Example

In this example, an upstream layer already provides an application recipe:

meta-vendor/recipes-apps/hello-recipe/hello-recipe_1.0.bb

We want to keep the vendor recipe unchanged, but add a project configuration file from our own layer.

Create this layout in meta-my-distro:

Create the directory:

mkdir -p meta-my-distro/recipes-apps/hello-recipe/hello-recipe

Create hello-recipe/hello-recipe.conf:

message=Hello from the project layer

Create hello-recipe_%.bbappend:

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"

SRC_URI:append = " file://hello-recipe.conf"

do_install:append() {
    install -d ${D}${sysconfdir}/hello-recipe
    install -m 0644 ${UNPACKDIR}/hello-recipe.conf ${D}${sysconfdir}/hello-recipe/hello-recipe.conf
}

What this does:

  • FILESEXTRAPATHS tells BitBake to also search your append’s hello-recipe/ directory
  • SRC_URI:append adds the local configuration file to the recipe inputs
  • do_install:append() installs the file after the original recipe has installed its own files

Now check that the append is active:

bitbake-layers show-layers
bitbake-layers show-appends hello-recipe

You should see meta-my-software in the layer list, and you should see hello-recipe_%.bbappend listed as an append for hello-recipe.

Build the recipe:

bitbake hello-recipe

If you want to inspect just the install stage while debugging:

bitbake -c install hello-recipe

The staged file should appear under the recipe work directory, usually in a path like:

tmp/work/<machine>/hello-recipe/1.0/image/etc/hello-recipe/hello-recipe.conf

After the package is included in an image and the image is rebuilt, the file should appear on the target as:

/etc/hello-recipe/hello-recipe.conf

Complete Patch Example

Bitbake recognises any file ending in .patch as a patch file and will automatically try and apply that to the source.

Patch files work the same way as other local files - put them in a subdirectory, add that directory to FILESEXTRAPATHS, and list the patch in SRC_URI.

Layout:

meta-my-distro/
  recipes-apps/
    hello-recipe/
      hello-recipe_%.bbappend
      hello-recipe/
        0001-print-project-message.patch

Append:

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}$:"

SRC_URI:append = " file://0001-print-project-message.patch"

Patch:

From: Example Developer <developer@example.com>
Date: Thu, 13 Aug 2026 10:00:00 +0000
Subject: [PATCH] Print project message

---
 hello-recipe.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hello-recipe.c b/hello-recipe.c
index 1111111..2222222 100644
--- a/hello-recipe.c
+++ b/hello-recipe.c
@@ -1,6 +1,6 @@
 #include <stdio.h>
 
 int main(void)
 {
-    puts("hello from upstream");
+    puts("hello from the project layer");
     return 0;
 }

When you build the recipe, BitBake applies patches listed in SRC_URI during do_patch, before configure and compile tasks run.

If the patch fails, run:

bitbake -c patch hello-recipe

Then inspect the patch log under the recipe work directory:

tmp/work/<machine>/hello-recipe/1.0/temp/log.do_patch

Common Mistakes

The .bbappend Filename Does Not Match

If the recipe is:

hello-recipe_1.0.bb

then these match:

hello-recipe_1.0.bbappend
hello-recipe_%.bbappend

This does not match:

hello_recipe_1.0.bbappend

BitBake is strict about recipe names. A small filename difference means the append is ignored or BitBake reports that no matching recipe exists.

The Layer Is Not Enabled

Your append can be perfectly written and still do nothing if the layer is not in conf/bblayers.conf.

Check:

bitbake-layers show-layers

Add the layer if it is missing:

bitbake-layers add-layer ../meta-my-software

FILESEXTRAPATHS Points to the Wrong Place

This is the usual form:

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

Common problems include:

  • forgetting the trailing :
  • using = instead of := when ${THISDIR} is involved
  • putting the file in a different directory from the one you added to the search path

The File or Patch Is Not in SRC_URI

Putting a file in files/ is not enough. BitBake also needs to know that the recipe uses it.

This file:

files/hello-recipe.conf

also needs:

SRC_URI:append = " file://hello-recipe.conf"

The same applies to patches:

SRC_URI:append = " file://0001-print-project-message.patch"

Editing the Original Recipe Instead

Editing the upstream .bb recipe may look faster at the start, but it creates a maintenance problem. The next time you update the vendor or community layer, you have to rediscover and reapply your local changes.

Keep product changes in your own layer. Use .bbappend files when the recipe already exists and you only need to adjust it. Write a new .bb recipe when you are adding a new software component.

Summary

A .bbappend is the normal way to modify an existing recipe from your own layer.

The important habits are:

  • do not edit upstream or vendor recipes directly
  • match the .bbappend filename to the recipe name and version
  • keep appends and local files in your own layer
  • use FILESEXTRAPATHS:prepend := "${THISDIR}/files:" when adding files beside an append
  • list every local file and patch in SRC_URI
  • use :append, :prepend, and :remove to adjust existing metadata
  • use bitbake-layers show-appends and bitbake-getvar -r to check what BitBake actually sees