Reference Advanced 20 min read

Yocto & BitBake: Essential Commands for Embedded Linux

Master Yocto Project and BitBake commands. Build custom Linux images, create recipes, manage layers, and debug embedded builds with practical examples.

OceanSoft Solutions
yoctobitbakeembeddedlinuxopenembedded
bitbake@yocto:~

What is Yocto?

The Yocto Project is an open-source collaboration for creating custom Linux distributions for embedded systems. Key components:

  • BitBake — Task executor and scheduler (like make on steroids)
  • OpenEmbedded — Build framework with metadata
  • Poky — Reference distribution
  • Layers — Collections of recipes and configurations
  • Recipes — Instructions to build packages (.bb files)

Getting Started

# Clone Poky (reference distribution)
git clone git://git.yoctoproject.org/poky
cd poky

# Checkout a stable branch (e.g., kirkstone)
git checkout kirkstone

# Initialize build environment
source oe-init-build-env

# Build a minimal image
bitbake core-image-minimal

BitBake Basics

Building Images

# Build minimal console image
bitbake core-image-minimal

# Build image with SSH and basic tools
bitbake core-image-base

# Build full image with X11
bitbake core-image-sato

# Build SDK for cross-compilation
bitbake -c populate_sdk core-image-minimal

Building Individual Packages

# Build a specific package
bitbake busybox
bitbake linux-yocto
bitbake u-boot

# Build only the recipe (no dependencies)
bitbake -b ../meta/recipes-core/busybox/busybox_1.35.0.bb

Recipe Tasks

BitBake executes tasks in order. Common tasks:

# Fetch sources
bitbake busybox -c fetch

# Unpack sources
bitbake busybox -c unpack

# Patch sources
bitbake busybox -c patch

# Configure build
bitbake busybox -c configure

# Compile
bitbake busybox -c compile

# Install to staging
bitbake busybox -c install

# Package
bitbake busybox -c package

# Deploy to image
bitbake busybox -c deploy

Cleaning and Rebuilding

# Clean build directory (keeps downloads)
bitbake busybox -c clean

# Clean everything including downloads
bitbake busybox -c cleanall

# Clean and rebuild
bitbake busybox -c cleansstate
bitbake busybox

# Force rebuild from scratch
bitbake -f busybox

Inspecting Recipes

oe-pkgdata-util

# Find which recipe provides a file
oe-pkgdata-util find-path /usr/bin/curl

# List files in a package
oe-pkgdata-util list-pkg-files curl

# Find package that contains a file
oe-pkgdata-util lookup-pkg curl

# List all packages from a recipe
oe-pkgdata-util list-pkgs -p curl

bitbake-layers

# Show all layers
bitbake-layers show-layers

# Show recipes in a layer
bitbake-layers show-recipes

# Find a recipe
bitbake-layers show-recipes | grep busybox

# Add a layer
bitbake-layers add-layer ../meta-mylayer

# Remove a layer
bitbake-layers remove-layer ../meta-mylayer

# Check layer compatibility
bitbake-layers show-overlayed

bitbake Environment

# Show full environment for a recipe
bitbake -e busybox | less

# Find specific variable
bitbake -e busybox | grep ^SRC_URI=
bitbake -e busybox | grep ^WORKDIR=

# Show all variables for an image
bitbake -e core-image-minimal | grep ^IMAGE_INSTALL=

Kernel Development

Kernel Configuration

# Open kernel menuconfig
bitbake linux-yocto -c menuconfig

# Save config as defconfig
bitbake linux-yocto -c savedefconfig

# View kernel config diff from default
bitbake linux-yocto -c diffconfig

# Generate config fragment
# (Useful for layer customizations)
bitbake linux-yocto -c kernel_configme

Kernel Development Workflow

# Enter kernel development shell
bitbake linux-yocto -c devshell

# Rebuild kernel only (after manual changes)
bitbake linux-yocto -C compile

# Deploy kernel without full image rebuild
bitbake linux-yocto -c deploy

Image Types

# Common image formats configured in local.conf
IMAGE_FSTYPES = "tar.bz2 ext4 wic"

# Create UBI image (for NAND flash)
IMAGE_FSTYPES = "ubi ubifs"

# Create JFFS2 image
IMAGE_FSTYPES = "jffs2"

# WIC image (partition layout)
IMAGE_FSTYPES = "wic wic.bmap"

UBI/UBIFS for NAND Flash

# In local.conf or image recipe
MKUBIFS_ARGS = "-m 2048 -e 126976 -c 2047"
UBINIZE_ARGS = "-m 2048 -p 128KiB -s 2048"

# Build UBI image
bitbake core-image-minimal
# Output: tmp/deploy/images/machine/core-image-minimal-machine.ubi

Using devtool

devtool simplifies recipe development:

# Modify existing recipe (extracts source for editing)
devtool modify busybox

# Build modified recipe
devtool build busybox

# Create patch and update recipe
devtool finish busybox ../meta-mylayer

# Create new recipe from source
devtool add myapp https://github.com/user/myapp.git

# Reset devtool workspace
devtool reset busybox

Important Variables

# In conf/local.conf

# Target machine
MACHINE = "raspberrypi4"

# Distribution
DISTRO = "poky"

# Number of parallel tasks
BB_NUMBER_THREADS = "8"

# Number of parallel make jobs
PARALLEL_MAKE = "-j 8"

# Extra packages to include
IMAGE_INSTALL:append = " vim curl wget"

# Package format
PACKAGE_CLASSES = "package_ipk"

# Download directory (shared across builds)
DL_DIR = "/opt/yocto/downloads"

# Shared state cache
SSTATE_DIR = "/opt/yocto/sstate-cache"

# Build artifacts
TMPDIR = "${TOPDIR}/tmp"

Creating a Custom Layer

# Create layer structure
bitbake-layers create-layer ../meta-mylayer
cd ../meta-mylayer

# Structure:
# meta-mylayer/
# ├── conf/
# │   └── layer.conf
# ├── recipes-example/
# │   └── example/
# │       └── example_0.1.bb
# └── README

# Add layer to build
cd ../build
bitbake-layers add-layer ../meta-mylayer

Example Recipe

# meta-mylayer/recipes-myapp/myapp/myapp_1.0.bb
SUMMARY = "My custom application"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=..."

SRC_URI = "https://example.com/myapp-${PV}.tar.gz"
SRC_URI[sha256sum] = "..."

inherit autotools

# Or for simple Makefile projects:
inherit cmake

Debugging Builds

# Verbose output
bitbake -v busybox

# Debug output
bitbake -D busybox

# Very debug
bitbake -DD busybox

# Show what would be built
bitbake -n busybox

# Show task dependencies
bitbake -g busybox
# Creates task-depends.dot

# Enter shell in build directory
bitbake busybox -c devshell

# Continue after failure
bitbake -k core-image-minimal

# Parse only (check for errors)
bitbake -p

Tips & Best Practices

  • Use shared download and sstate directories across builds
  • Create a custom layer for all modifications
  • Use :append and :remove instead of overwriting variables
  • Keep local.conf minimal; put customizations in layers
  • Use recipe version suffixes for multiple versions
# Good: Append to variables
IMAGE_INSTALL:append = " vim"

# Bad: Override entire variable
IMAGE_INSTALL = "packagegroup-core-base vim"

# Use bbappend for modifications
# meta-mylayer/recipes-core/busybox/busybox_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " file://my-config.cfg"

Resources

Need help with embedded Linux development? Contact us for consulting.