Advent of Embedded Linux — Day 3: Build Yocto Image + Custom Package

Day 3 — Build Yocto Image + Custom Package

Overview

Today, you’ll learn how to use Yocto Project with kas (KAS is an Awesome Setup tool) to build a complete embedded Linux distribution. Yocto Project is an industry-standard build system used by many embedded Linux developers.

Why Use kas?

While Yocto Project can be used with traditional BitBake commands, kas provides several advantages:

You’ll build a minimal RISC-V image for QEMU and create your own custom package that gets included in the final image. This hands-on experience will teach you the fundamentals of Yocto recipes, layers, and the build process.

What You Will Do

Step-by-Step Guide

Prerequisites

Install the required packages on Ubuntu 22.04:

sudo apt update
sudo apt install -y gawk wget git-core diffstat unzip texinfo \
    gcc-multilib build-essential chrpath socat cpio python3 \
    python3-pip python3-pexpect xz-utils debianutils iputils-ping \
    python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev \
    pylint3 xterm python3-subunit mesa-common-dev zstd liblz4-tool

Install kas using pipx (recommended for isolated Python package installation):

# Install pipx if not already installed
sudo apt install -y pipx
pipx ensurepath

# Install kas
pipx install kas

Verify kas installation:

kas --version

Step 1: Create Your Yocto Project Workspace

Set up your workspace directory:

mkdir -p ~/advent/day-03
cd ~/advent/day-03

Step 2: Create a Custom Layer

Create your own layer to add a custom package using the bitbake-layers tool. First, we’ll need to set up a temporary build environment to use bitbake-layers, or you can create the layer structure manually. For this guide, we’ll use bitbake-layers create-layer:

cd ~/advent/day-03

# Create the layer using bitbake-layers
# Note: You may need a temporary build environment for this command
# Alternatively, create the layer structure manually
bitbake-layers create-layer meta-advent

# Create the recipe directory structure
cd meta-advent
mkdir -p recipes-hello/helloworld/files

Create our source file helloworld.c

#include <stdio.h>

int main(void) {
    printf("Hello World\n");
    printf("Welcome to Advent of Embedded Linux\n");
    return 0;
}

Create the helloworld_0.1.bb recipe

SUMMARY = "simple hello world application"
LICENSE = "CLOSED"
LIC_FILES_CHKSUM = ""

SRC_URI = "file://helloworld.c"

S = "${UNPACKDIR}"

do_compile () {
        # Specify compilation commands here
        ${CC} ${LDFLAGS} helloworld.c -o helloworld
}

do_install () {
        # Specify install commands here
        install -d ${D}${bindir}
        install -m 0755 helloworld ${D}${bindir}
}

Step 3: Create the kas Configuration File

cd meta-advent
mkdir kas

Create the kas/hello-yocto.yml file that defines your build configuration:

header:
  version: 14
machine: qemuriscv64
distro: poky
target: core-image-minimal
repos:
  bitbake:
    url: https://git.openembedded.org/bitbake
    branch: master
    layers:
      bitbake: disabled
  openembedded-core:
    url: https://git.openembedded.org/openembedded-core
    branch: master
    layers:
      meta:
  meta-yocto:
    url: https://git.yoctoproject.org/meta-yocto
    branch: master
    layers:
      meta-poky:
  meta-openembedded:
    url: https://git.openembedded.org/meta-openembedded
    branch: master
    layers:
      meta-oe:
  meta-riscv:
    url: https://github.com/riscv/meta-riscv.git
    branch: master
  meta-advent:
    path: ..
    layers:
      .:
local_conf_header:
  qemuriscv64: |
    EXTRA_IMAGE_FEATURES = "empty-root-password allow-empty-password allow-root-login"
    KERNEL_DANGLING_FEATURES_WARN_ONLY = "1"
    IMAGE_INSTALL:append = " helloworld"

This kas configuration:

Step 4: Build and Boot the Image

Kas will clone the necessary repositories, set up the build environment, build the image, and boot it in QEMU:

cd ~/advent/day-03

# Build the image and boot it in QEMU
kas shell hello-yocto.yml -c "runqemu snapshot nographic"

This single command will:

  1. Clone all required repositories (if not already present)
  2. Set up the build environment
  3. Build the core-image-minimal image (this will take 30-60 minutes on first build)
  4. Boot the image in QEMU using snapshot mode

The first build will take significant time as it builds:

Subsequent builds will be faster due to caching.

Step 5: Test Your Custom Package

Once the system boots, login with root (no password required). Then test your custom package:

helloworld

You should see:

Hello World
Welcome to Advent of Embedded Linux

Custom Layer

You can find the source code to the build configuration and the meta-advent layer here: meta-advent

Expected Outcome

After completing this challenge, you should have:

  1. A working Yocto Project build environment using kas
  2. A complete embedded Linux distribution built for RISC-V
  3. Your own custom layer (meta-advent) with a package recipe
  4. A custom program (helloworld) included in the final image
  5. A bootable system running in QEMU with your custom package
  6. Root login enabled without password

When you boot the system and run helloworld, you should see:

Hello World
Welcome to Advent of Embedded Linux

Verification steps:

You’ve learned:

Extras