Setting up the System

Setting up the system to build the first image

A Yocto project is notoriously hungry. The more resources you can give it, the easier life will be.

While it is possible to build a project with WSL2 on Windows, having a Linux host reduces the friction. All the examples here are based on Debian.

Build Host

  • A system with at least 100 GB of free disk space
  • Fast I/O, because it noticeably improves build performance
  • At least 16 GB of RAM
  • More RAM and more CPU cores if you want faster builds
  • A supported recent Linux distribution such as Debian, Ubuntu, openSUSE, Red Hat, or Fedora
  • Core build tools including Git 1.8.3.1+, tar 1.28+, Python 3.8+, gcc 8+, and GNU make 4.0+

Build Tools

These are the packages you should install on your build host:

sudo apt install bc gawk wget git diffstat unzip texinfo gcc \
    build-essential chrpath socat cpio python3 python3-pip \
    python3-pexpect xz-utils debianutils iputils-ping \
    python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev \
    python3-subunit mesa-common-dev zstd liblz4-tool file \
    locales libacl1 libncurses-dev libssl-dev

sudo locale-gen en_US.UTF-8

Setting up the Project

The structure you set up now affects the whole experience of working with the Yocto Project.

Create a Shared Directory

A Yocto project caches a lot of data so that later builds can reuse it.

  • Downloaded source files
  • Build state and artifacts

Downloads

Yocto builds components from source, so it caches downloaded files to save time and bandwidth the next time they are needed.

Shared State Cache

There are many steps in a full build, for example:

  • Download the source
  • Configure
  • Compile
  • Install

The result of each of these steps is saved in the shared state cache, or sstate, so it can be reused where appropriate.

Reuse

It makes good sense to share these caches between projects. If project A has already downloaded busybox, for example, then project B should be able to reuse that download instead of fetching it again.

The same idea applies to the state cache. If several projects share the same board family or common packages, they can often reuse build steps and reduce build time significantly.

As a result, it is usually best to keep the cache outside the main project directory so it can be shared by multiple projects.

mkdir -p ~/yocto/shared

Create the Project Directory

Your Yocto project will become a complete working environment, so it is a bad idea to keep it directly in your home directory. A separate working directory keeps things much easier to manage.

A simple pattern is:

~/wip/<project_name>

Initialise the Project

mkdir -p ~/wip/my_project

cd ~/wip/my_project
git init

Create the directories to hold your layers

mkdir -p layers/project
mkdir layers/third-party

Understanding Layers

A layer is just a collection of Yocto metadata grouped together for convenience.

That metadata may include:

  • recipes
  • append files
  • machine configuration
  • distro configuration
  • classes
  • configuration fragments
  • patches
  • image recipes

Each layer gives BitBake another set of files to search when resolving how the system should be built.

Why Layers Matter

Layers help you keep different responsibilities separate.

A healthy Yocto project usually separates:

  • upstream vendor or community layers
  • your own board or BSP layer
  • your own distro or policy layer
  • your own application or product layer

This makes it easier to answer questions like:

  • is this change ours or upstream?
  • what can be upgraded safely?
  • where should a new recipe live?
  • where should a project-specific patch be stored?

Typical Layer Structure

A project often ends up looking something like this:

You do not have to use exactly these names, but the separation is useful.

Common Project Layers

meta-my-bsp usually contains machine configuration, kernel changes, bootloader settings, and board-specific patches.

meta-my-distro usually contains distribution policy, image defaults, overrides to standard packages, and system-wide behaviour.

meta-my-software usually contains recipes for your own applications and software components.

That keeps hardware concerns, policy concerns, and application concerns from being mixed together.

Clone the Initial Layers

BitBake - The Build Tool

git clone https://git.openembedded.org/bitbake layers/third-party/bitbake

OpenEmbedded Core

git clone -b scarthgap git://git.openembedded.org/openembedded-core \
	layers/third-party/meta-openembedded-core

Create a Start Script

Rather than typing long initialisation commands every time, create a small start script for the project.

In ~/wip/my_project (where you should be if you are following the instructions), create a script start-yocto.sh

#!/bin/bash --init-file

# Ensure the shared directories exist for caching
mkdir -p ~/yocto/shared > /dev/null 2>&1

source ./layers/third-party/meta-openembedded-core/oe-init-build-env \
  ./build

Make sure it is executable.

Run this script each time you want to build anything. It initialises the environment correctly and drops you into the right build directory.

Run the script now and you will be able to start your first build.

Checkpoint - Files and Directories

bblayers.conf

BitBake only knows about layers that are listed in bblayers.conf.

For example:

BBLAYERS ?= " \
  ${YOCTOROOT}/third-party/meta-openembedded-core/meta \
  ${YOCTOROOT}/third-party/meta-some-vendor \
  ${YOCTOROOT}/project/meta-my-bsp \
  ${YOCTOROOT}/project/meta-my-distro \
  ${YOCTOROOT}/project/meta-my-software \
"

If a layer is not listed there, its metadata will not be available to the build.

layer.conf

Every layer contains a conf/layer.conf file.

That file tells BitBake things such as:

  • where to find recipes
  • where to find .bbappend files
  • which collection name the layer uses
  • compatibility with Yocto releases

You do not need to memorise all of layer.conf immediately, but you should know that it is what makes the directory behave as a proper BitBake layer.

Layer Priority

When multiple layers affect the same metadata, BitBake needs rules to decide how things combine.

Layer priority helps determine which layer wins in certain cases, especially when similarly named metadata exists in more than one place.

You do not need to rely on priority for everyday work, but you should know that it exists and that overlapping metadata between layers can create confusing results.

In practice, good structure is more important than clever priority tricks.

Configure Your Build

To make use of the shared cache, modify your local configuration file, build/conf/local.conf. This file defines local configuration parameters for the build.

The defaults are commented out, so you can add your own values below them.

Find the section for DL_DIR and change it to use your shared directory.

#DL_DIR ?= "${TOPDIR}/downloads"
DL_DIR = "${HOME}/yocto/shared/downloads" 

Do the same for SSTATE_DIR:

#SSTATE_DIR ?= "${TOPDIR}/sstate-cache"
SSTATE_DIR = "${HOME}/yocto/shared/sstate-cache/${MACHINE}"

Then, to keep the first build simple, allow root login:

# INSECURE - DO NOT USE FOR PRODUCTION
EXTRA_IMAGE_FEATURES ?= "allow-empty-password \
    empty-root-password allow-root-login"

Build Your First Image

Create a minimal image with:

bitbake core-image-minimal 

Test the Image

At this point, you have built an image for a QEMU x86-64 target. You can run it with:

runqemu qemux86-64

Login as root with no password.

If you want to learn more about running QEMU, see the Using the Quick EMUlator (QEMU) chapter in the Yocto Project Development Tasks Manual.

Exit QEMU either by clicking the shutdown icon or by typing Ctrl-C in the terminal where you launched QEMU.

Summary

Setting up the project correctly at the beginning makes the rest of the Yocto workflow much easier.

The key concepts from this lesson are:

  • make sure the build host has enough storage, RAM, and the required tools
  • create shared download and sstate cache directories
  • keep the working project in its own clean directory structure
  • clone the core layers needed to start the build
  • separate third-party, BSP, distro, and application metadata into appropriate layers
  • use bblayers.conf to control which layers are active
  • create a startup script so the environment is always initialised consistently
  • update local.conf so the build uses your shared caches
  • build and test a first image in QEMU

Quick quiz: setup

A short review before moving on from the initial build environment.

Question 1 Why is `SSTATE_DIR` useful in a Yocto setup?
Question 2 What is the purpose of `DL_DIR`?
Question 3 What is a sensible first image to build in this lesson?
Question 4 If a layer is not listed in `bblayers.conf`, what happens?