BitBake bbappend: Patch Recipes Without Overwriting

Copying an upstream or vendor .bb into your layer and editing it forces a manual re-merge on every version bump. The Yocto Development Tasks Manual says: do not overlay entire recipes—use a .bbappend to extend or override only what you need. A BitBake append shares the same root filename as its matching .bb; its metadata extends or overrides the original recipe.

This post covers only path layout · FILESEXTRAPATHS · priority. The yocto-systemd post is the inherit systemd / SYSTEMD_SERVICE / unit install path (image init) axis. Here the axis is patches, extra files, and variable tweaks without copying the recipe. No invented board stories.

Sources: Understanding and Creating Layers (§3.5 Appending…, §3.6 Prioritizing…), Yocto terms — Append Files.

Where does the path go?

One-line answer: In your layer, place the .bbappend under the same recipes-* subpath and same root filename as the original. Match versions exactly, or put % immediately before .bbappend.

Naming (per docs):

Original recipeAppend exampleMeaning
someapp_3.1.bbsomeapp_3.1.bbappendExact version match
someapp_6.2.bb (any 6.*)someapp_6.%.bbappendCovers minors while major stays 6
(no matching .bb)—BitBake errors at startup. Rename, BBMASK, or drop

Layout sketch (same pattern as the docs’ formfactor example):

meta-mylayer/
  conf/layer.conf
  recipes-bsp/formfactor/
    formfactor_0.0.bbappend          # matches meta/.../formfactor_0.0.bb
    formfactor/                      # directory FILESEXTRAPATHS will point at
      machconfig                 # or a machine subdirectory (below)

Practical checks:

  1. Root name match — foo_1.2.bb ↔ foo_1.2.bbappend. Only the suffix differs.
  2. Version bump — if upstream becomes foo_1.3.bb, rename the append or revisit the % range. Mismatched names are a startup error.
  3. % placement — only immediately before .bbappend (e.g. someapp_6.%.bbappend). Not elsewhere in the path.
  4. Mirror the tree — if upstream lives under recipes-core/base-files/, put your append under the same relative path. Confirm with bitbake-layers show-appends.
  5. Variables only — if you add no file:// files, you can omit FILESEXTRAPATHS and still :append SRC_URI, EXTRA_OECONF, etc. (docs: many appends never extend file search paths).

vs yocto-systemd: that post’s “where do files go?” means ${D}${systemd_system_unitdir} on the image. This section’s “path” means where the .bbappend and files directories live in the metadata tree.

What about FILESEXTRAPATHS?

One-line answer: To make file:// patches and configs resolve from your layer, FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" (or ${BPN}). The important bits are :=, the trailing colon, and :prepend.

Minimal form recommended by the docs:

# meta-mylayer/recipes-bsp/formfactor/formfactor_0.0.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"

Details:

  1. THISDIR — defined by BitBake. Never set it yourself. Expands to the directory that contains the append.
  2. := (immediate) — required because of the THISDIR reference; delayed expansion can mis-resolve the path.
  3. Trailing : — keeps the colon-separated search list intact.
  4. :prepend — puts your directory first in the final search list.
  5. ${PN} vs ${BPN} — the formfactor example uses ${PN}; the best-practices section also shows ${BPN}. When PN carries suffixes, ${BPN} (base name) is often safer. Verify with bitbake -e <recipe> | grep ^FILESEXTRAPATHS=.
  6. Machine-specific files — docs warn: files only under ${THISDIR}/${PN}/ can apply to every machine that includes the layer. Restrict with ${PN}/<machine>/ so FILESOVERRIDES selects them.

Adding extra files (docs’ xserver-xf86-config pattern, generalized):

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

SRC_URI:append:mymachine = " file://extra.conf"

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

Verify:

bitbake-layers show-appends | less
bitbake -e <recipe-name> | grep -E '^FILESEXTRAPATHS='

What about priority?

One-line answer: When multiple layers provide the same recipe name, the higher BBFILE_PRIORITY number wins. Priority also affects the order multiple .bbappend files are applied. A higher-priority layer’s :prepend runs later, so it ends up first in FILESEXTRAPATHS.

In conf/layer.conf:

# bitbake-layers create-layer default is often priority 6
BBFILE_PRIORITY_mylayer = "6"

Summary:

SituationBehavior (docs)
Same recipe name, multiple layersHigher BBFILE_PRIORITY .bb is used
Multiple .bbappends for one recipePriority affects application order
:prepend + file searchHigher-priority prepend applies last → path stays front of list
.conf / .bbclassLayer priority does not currently order these (documented)
Lower PV + higher priorityPossible — higher priority can win with a lower version

Commands:

bitbake-layers show-layers
bitbake-layers show-appends
bitbake-layers show-overlayed

Conflict hygiene:

  1. Do not copy whole .bb files — adjust variables/files via append (best practice).
  2. Set custom-layer priority intentionally vs BSP/distro; confirm with show-layers.
  3. If FILESEXTRAPATHS order looks wrong, inspect -e and tidy priority / overrides.
  4. Orphan appends: rename to match, or BBMASK when you cannot edit them.

FAQ

How is this different from yocto-systemd?

That post is packaging a systemd unit in a recipe and enabling systemd as image init. This post is path layout, FILESEXTRAPATHS, and layer priority for .bbappend without copying upstream .bb. To add a unit onto someone else’s recipe, you usually combine this post’s append with that post’s inherit systemd.

What if FILESEXTRAPATHS is set but the directory is empty?

Prepend alone does not fetch anything. You still need matching SRC_URI file:// entries (and install logic). Otherwise fetch fails or adds nothing.

% or exact version?

Use _.%.bbappend when you want to ride minor bumps. Prefer an exact-version append when a major jump may break your delta—so upgrades force a rename-and-review.

When is copying the whole recipe OK?

Docs best practice: avoid it. If you must fork, accept the merge cost and push deltas back into appends when you can.

Sources