Every layer you build eventually boils down to five file types that BitBake understands. Get this
vocabulary solid and the rest of Yocto stops feeling like magic. This lecture is part of a
free linux kernel development course and free embedded systems course
track, and it’s the piece students skip most often — then get stuck later wondering why a
.bbappend silently did nothing or why do_compile ran before
do_configure finished.
bbappend
bbclass
recipe tasks
do_fetch do_compile
free linux kernel development course
What You Will Learn
- The five metadata file types BitBake parses and what each is for
- include vs require and when to use each
- How a recipe becomes a graph of named tasks
- Listing, running, and targeting individual tasks with -c
- Fetching sources for one recipe vs an entire dependency tree
Prerequisites
This lecture assumes you already have a registered custom layer (covered in the previous lecture)
and a working Poky build environment. No prior BitBake internals knowledge is required.
The Five Metadata File Types
BitBake doesn’t treat all metadata the same way — each file extension has a distinct purpose, and
mixing them up is one of the fastest ways to confuse a build:
| Extension | Purpose | Example |
|---|---|---|
| .bb | A recipe — builds one unit of software: fetch, configure, compile, install | ep-greet_1.0.bb |
| .bbappend | Extends or overrides an existing .bb of the same root name, from another layer | ep-greet_%.bbappend |
| .inc | Shared fragments included by several recipes, via include or require | ep-common.inc |
| .bbclass | Reusable build logic inherited by recipes with the inherit keyword | autotools.bbclass |
| .conf | Configuration variables governing the whole build, not tied to one recipe | local.conf |
include vs require
Both pull the contents of another file into the current one at parse time, and the difference is
purely about failure behavior. require somefile.inc aborts the parse with an error if the
file is missing — use it for anything the recipe genuinely cannot build without. include silently continues if the file isn’t found — use it for optional, environment-
somefile.inc
specific tweaks that shouldn’t break a build when absent.
# Fails the parse if ep-common.inc is missing — this recipe truly needs it
require ep-common.inc
# Silently skipped if not present — safe optional customization
include ${PN}-site.inc
Classes: Shared Behavior, Not Shared Data
Where .inc files share variable definitions, .bbclass files share
behavior — task definitions and functions. Every recipe implicitly inherits
classes/base.bbclass, which is why even the simplest recipe already has working
do_fetch, do_unpack, and do_build tasks without you writing any
of them. Explicit inheritance layers on top of that:
inherit pkgconfig
inherit systemd
pkgconfig.bbclass and systemd.bbclass each add the tasks, variables, and
packaging logic specific to their concern, without every recipe author reimplementing them.
│
▼
inherit autotools (adds do_configure, do_compile, do_install)
│
▼
ep-greet_1.0.bb (recipe overrides / adds do_install)
│
▼
ep-greet_%.bbappend (another layer tweaks SRC_URI or a task)
│
▼
Final task graph BitBake executes
Tasks: The Unit BitBake Actually Executes
A recipe is really a named collection of tasks written in Python or shell:
do_fetch, do_unpack, do_patch, do_configure,
do_compile, do_install, do_package, and more. Running plain
bitbake <recipe> executes the default task, do_build, which depends on
(and therefore triggers) the whole chain up to it.
You can see exactly which tasks a given recipe defines without running any of them:
$ bitbake -c listtasks ep-greet
do_build
do_clean
do_compile
do_configure
do_deploy
do_fetch
do_install
do_package
do_patch
do_unpack
...
Targeting a Single Task with -c
The -c flag lets you run one task in isolation, dropping the do_ prefix.
This is invaluable when you only want to inspect one stage without running a full build:
# Just fetch the source, don't build anything yet
$ bitbake -c fetch ep-greet
# Re-run only compilation after a source change
$ bitbake -c compile ep-greet
# Wipe this recipe's build output and start fresh
$ bitbake -c cleansstate ep-greet
fetch vs fetchall
-c fetch downloads sources for exactly the recipe you named. On a large image target
like core-image-minimal, that recipe has dozens of dependencies, and you often want every
source available before going offline — that’s what fetchall is for:
# Only ep-greet's own source
$ bitbake -c fetch ep-greet
# ep-greet plus every recipe it depends on, transitively
$ bitbake -c fetchall core-image-minimal
fetchall is the command to run before a flight, a client site visit, or any situation
where you need a fully mirrored source cache before losing network access.
Real-World Use Case: Debugging a Stuck Build
When a build hangs or fails deep in a dependency you don’t recognize, resist the urge to blow away
the whole build directory. Instead, isolate the task:
$ bitbake -c listtasks <suspect-recipe>
$ bitbake -c compile -f <suspect-recipe> # -f forces a re-run even if "up to date"
This turns a mystery full-image failure into a five-second, single-recipe, single-task repro loop —
the difference between a two-minute fix and a fifteen-minute one on a slow machine.
Common Mistakes
Using include when you meant require
A silently-missing include can leave a recipe half-configured with no error at parse time — the
failure surfaces confusingly later, during a task that needed the missing variable.
Naming a bbappend wrong
A .bbappend only attaches if its root name and version match the target recipe
(ep-greet_%.bbappend matches any ep-greet_*.bb). A typo means it’s parsed but
never applied, with no error.
Forgetting -f when re-running a task
BitBake skips tasks it considers already up to date via its sstate cache. If you edited a recipe’s
do_compile function directly and expect it to re-run, you often need -f.
Best Practices
- Use require for anything the recipe cannot function without
- Put shared task logic in a .bbclass, not copy-pasted across recipes
- Run fetchall before any offline or bandwidth-constrained work session
- Reach for listtasks before guessing which -c target you need
Summary and Key Takeaways
- Five metadata types: .bb, .bbappend, .inc, .bbclass, .conf — each with a distinct job
- require fails loudly on a missing file; include fails silently
- A recipe’s real content is its task graph, inherited from base.bbclass upward
- -c targets one task; fetchall pulls an entire dependency tree’s sources
Conclusion
Once you can name what kind of file you’re looking at and predict which tasks a recipe will run, half
the mystery goes out of debugging Yocto builds. The next lecture in this
free linux device drivers course series puts this vocabulary to work by writing a
complete custom recipe from scratch.
Frequently Asked Questions
What’s the actual difference between a .bb and a .bbappend?
A .bb is a complete, standalone recipe. A .bbappend can only modify an existing .bb of the same
root name from another layer — it can’t exist on its own.
Do I need to define do_fetch myself in every recipe?
No — every recipe implicitly inherits classes/base.bbclass, which already provides working
do_fetch, do_unpack, and do_build tasks.
Can one recipe have multiple .bbappend files from different layers?
Yes, and they apply in layer-priority order, each able to further modify what the previous one set.
Why did bitbake -c fetch not download my dependencies?
By design — fetch only pulls the named recipe’s own source. Use fetchall to pull an entire
dependency tree’s sources at once.
What happens if I run a task BitBake thinks is already done?
It’s skipped via the sstate cache. Force a re-run with the -f flag alongside -c.
Is .conf metadata tied to a specific recipe?
No — .conf files define build-wide variables (machine, distro, local overrides) that apply across
every recipe in the build, not to one package.
Keep Building With EmbeddedPathashala
This lecture is part of a completely free embedded Linux course covering toolchains, bootloaders,
kernel porting, root filesystems, and build systems from first principles.

2 Comments