Writing a BitBake Recipe- Embedded Linux Training In Hyderabad

PREV_LEC | NEXT_LEC

Writing a BitBake Recipe
From a single C file to an installed package on your target image
Chapter 6 · Lecture 8
Yocto 6.0 “Wrynose” LTS
18+ min read

This is the lecture where everything in this free linux device drivers course and
build-system track finally clicks: you take a program you wrote yourself, wrap it in a BitBake recipe,
build it, and watch it land inside a bootable image. We’ll build a tiny original utility —
ep-greet — inside the meta-ep-board layer from the earlier lecture, cover
licensing correctly, and finish by adding the package to an image without rebuilding from scratch.

BitBake recipe example
SRC_URI
do_compile do_install
LIC_FILES_CHKSUM
IMAGE_INSTALL_append
free linux device drivers course

What You Will Learn

  • Recipe naming convention and where local source lives
  • The metadata every recipe needs: DESCRIPTION, LICENSE, LIC_FILES_CHKSUM
  • Writing minimal do_compile and do_install tasks
  • Building a single recipe and finding its output package
  • Adding your new package to a target image with IMAGE_INSTALL:append
  • Handling non-open-source licenses safely

Prerequisites

You’ll need the meta-ep-board layer registered and verified (previous lecture) and a
basic grasp of BitBake’s metadata types and task model (the lecture before that). A little C is
helpful but not required — the example program is five lines.

Step 1 — Lay Out the Recipe Directory

Recipe files follow the convention <package-name>_<version>.bb. Local
source that isn’t fetched from a git remote or tarball lives in a files subdirectory next
to the recipe, and BitBake finds it automatically through its default search path:

Custom Recipe Directory Layout
meta-ep-board/
└── recipes-ep/
└── ep-greet/
├── files/
│ └── ep-greet.c
└── ep-greet_1.0.bb

Our example program is deliberately trivial — the point of this lecture is the recipe, not the C:

/* files/ep-greet.c */
#include <stdio.h>

int main(void)
{
    printf("ep-greet: hello from a custom BitBake recipen");
    return 0;
}

Step 2 — Write the Recipe Metadata

Every recipe needs a description, a license, and proof that the license text matches what the
recipe claims — that’s what LIC_FILES_CHKSUM is for. BitBake will refuse to build if the
checksum doesn’t match, catching license text that changed silently upstream:

# ep-greet_1.0.bb
DESCRIPTION = "A minimal original demo package for the EmbeddedPathashala BitBake lecture"
PRIORITY = "optional"
SECTION = "examples"

LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "file://ep-greet.c"
S = "${WORKDIR}"

do_compile() {
    ${CC} ${CFLAGS} ${LDFLAGS} -o ep-greet ep-greet.c
}

do_install() {
    install -d ${D}${bindir}
    install -m 0755 ep-greet ${D}${bindir}
}

SRC_URI tells BitBake where the source lives — file://ep-greet.c makes it
search the recipe’s files directory automatically. S is the directory BitBake
treats as the unpacked source root; for a lone local file it’s just ${WORKDIR}, the
recipe’s private working area. ${D} expands to the staging root for the target image, and
${bindir} to the standard binary directory, /usr/bin, so
install is really writing to ${D}/usr/bin/ep-greet.

Step 3 — Build Just This Recipe

$ bitbake ep-greet

A successful run creates a per-recipe working directory and, more importantly, a real package
artifact you can inspect independently of any image:

$ ls tmp/deploy/rpm/cortexa8hf_vfp_neon/ | grep ep-greet
ep-greet-1.0-r0.cortexa8hf_vfp_neon.rpm

At this point ep-greet is built and packaged, but it isn’t part of any image yet — that
distinction (built vs. installed-in-image) trips up a lot of newcomers.

Step 4 — Add It to an Image Without a Full Recipe Change

The list of packages an image pulls in is controlled by the IMAGE_INSTALL variable.
Rather than editing the image recipe itself, append to it from conf/local.conf — this is
the standard way to pull a package into development builds:

# build/conf/local.conf
IMAGE_INSTALL:append = " ep-greet"

Note the leading space inside the quotes — without it, BitBake would concatenate directly onto the
previous entry with no separator. Rebuild the image and the package is now included:

$ bitbake core-image-minimal
$ tar tf tmp/deploy/images/qemux86-64/core-image-minimal-qemux86-64.tar.bz2 | grep ep-greet
./usr/bin/ep-greet

Handling Non-Open-Source Licenses

By default, BitBake refuses to build anything not explicitly cleared, and commercial or otherwise
restricted licenses need an explicit opt-in in two places — first the recipe declares the flag:

LICENSE_FLAGS = "commercial"

then local.conf explicitly allows it for that specific build:

LICENSE_FLAGS_ACCEPTED = "commercial"

This two-step design exists on purpose — a recipe alone can never silently pull in a restricted
license; the person configuring the build has to consciously accept it.

Real-World Use Case

This exact pattern — a tiny local recipe plus an IMAGE_INSTALL:append — is how most teams add
in-house diagnostic tools, factory test binaries, or provisioning scripts to a product image during
bring-up, before those tools graduate into a properly versioned package with real upstream source
fetched over git or https instead of a local file.

Common Mistakes

Missing the leading space in IMAGE_INSTALL:append

Without it, the appended package name runs together with the last existing entry and BitBake fails
to find either package.

Wrong LIC_FILES_CHKSUM

A mismatched md5 aborts the build immediately with an explicit error — copy the checksum BitBake
reports on first failure rather than guessing.

Forgetting do_install entirely

A recipe that only defines do_compile will build the binary but install nothing — it will never
appear in any image, silently.

Best Practices

  • Keep local demo/test recipes clearly separated in their own recipes-* directory
  • Always set LICENSE and LIC_FILES_CHKSUM, even for trivial internal tools
  • Use IMAGE_INSTALL:append in local.conf for development, and a proper image recipe for production
  • Never accept LICENSE_FLAGS globally — scope it to the specific build that needs it

Summary and Key Takeaways

  • Recipes follow <name>_<version>.bb naming with local source under files/
  • LICENSE and LIC_FILES_CHKSUM are mandatory, not optional, metadata
  • do_compile and do_install are the two tasks a minimal recipe must define
  • Building a recipe and installing it in an image are two separate steps
  • IMAGE_INSTALL:append in local.conf is the fast path for development builds

Conclusion

You’ve now taken a layer, understood BitBake’s metadata model, and written a working recipe end to
end — the complete loop that every real BSP and product image is built from. That closes out the build
systems arc of this free embedded systems course; from here the series moves into
customizing images more deeply, including package selection strategies beyond a single
IMAGE_INSTALL:append line.

Frequently Asked Questions

Do I always need a files/ subdirectory for local source?

Only when SRC_URI uses file://. Recipes pulling from git or https don’t need one — BitBake fetches
the source into WORKDIR directly.

What if my recipe needs configure/autotools instead of a manual do_compile?

Add inherit autotools to the recipe and remove your manual do_compile — the class provides
do_configure, do_compile, and do_install automatically for autotools-based projects.

Why is my package built but missing from the image?

Almost always because it was never added to IMAGE_INSTALL. Building a recipe with bitbake <name>
never automatically pulls it into an image.

Can I use IMAGE_INSTALL:append for a production build?

It works, but production images typically define their own image recipe listing exact package sets
rather than relying on local.conf overrides that aren’t version controlled with the image.

What does the leading space in IMAGE_INSTALL:append actually do?

BitBake’s append syntax concatenates strings with no automatic separator, so the space prevents your
new package name from merging into the previous one.

Is LICENSE_FLAGS only for truly commercial software?

It covers any license the Yocto Project’s default policy considers restricted enough to require
explicit acceptance, not exclusively paid/commercial licenses.

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.

PREV_LEC | NEXT_LEC

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *