Build a custom Linux for your Rasp Pi with Yocto
Tailor-Made
Yocto is a tool for creating custom Linux images for embedded devices. We'll show you how to create a customized Linux for your Rasp Pi.
Yocto [1] is a distribution builder. The tool helps users create customized images. A custom image is particularly tempting in the embedded environment, where hardware resources are limited.
In the Beginning
Yocto builds images based on recipes. The user can modify the recipe to determine how the system should be structured – you can even specify which compiler will be used for compiling the source code.
Yocto comes with a reference distribution called Poky, which includes many ready-made recipes and is based on OpenEmbedded [2]. A tool called bitbake
lets you combine the Poky layer with a hardware-specific board support layer.
One of Yocto's strengths is the many layers available from the start, including layers from most board manufacturers and also from numerous open source projects. Figure 1 shows the extensive and searchable OpenEmbedded Layer Index [3]. Yocto also has an excellent manual [4] that explains all aspects in detail.
The easiest way to get started with your own image is by downloading poky
and meta-raspberrypi
and cloning the Git repositories (Listing 1). The convention is to place all layers below poky
. It is important to always clone the same branch name of each layer, e.g. Warrior. Warrior is the name of the current Poky version. The layer names usually start with meta-. In fact, Poky contains a large number of meta-* directories, because it consists of several layers.
Listing 1
Cloning Repositories
After cloning, you need to create a suitable environment by running the following command:
source oe-init-build-env
This command also updates the PATH
variable so that the Yocto tools can be called from anywhere. The command creates a build
directory with a conf
subdirectory. conf
contains two interesting files: bblayers.conf
, a list of the layers used, and local.conf
, instructions for Yocto on how to build the image.
In the bblayers.conf
file, edit the line with meta-yocto-bsp
and enter the location of the cloned meta-raspberrypi
layer. In local.conf
, add the following line:
MACHINE ?= "raspberrypi3"
This line tells Yocto which hardware model the build will be for. Look online for a list of the models supported by the Raspberry Pi layer [5].
Initially Minimal
To check if everything is set up correctly, build a core-image-minimal
with the following call from the build
directory:
bitbake core-image-minimal
Do not be put off by the time and space required for this action. Yocto builds an image that contains a small Linux system, as well as all the tools needed to build the distribution, such as a compiler. The next build
call then works incrementally; in other words, later steps do not need to rebuild the tools created in a previous step.
When the build process is done, examine the build
directory. You will find four new subdirectories: cache
, downloads
, sstate-cache
, and tmp
. The most interesting of these subdirectories is tmp
, in which the resulting image takes its place. Below downloads
are downloaded files, and sstate-cache
and cache
serve the build process as cache storage. In more complex scenarios, several computers can share sstate-cache
.
The tmp
directory has a number of subdirectories, one of which is called deploy
. The deploy
directory contains all packages used for the platform and their licenses, as well as the generated image. The core-image-minimal-raspberrypi3.rpi-sdimg
file in the tmp/deploy/images/raspberrypi3/
directory is a link to the last successful build.
With the help of the dd
command, you can easily transfer the image to an SD card. Be very careful with dd
, which overwrites the copy target. Make doubly sure that the correct output device is specified so that you don't accidentally overwrite the operating system.
After plugging in the SD card, search the dmesg
output for messages from the last device added; the name of the device appears in the output. You can then specify the device name in the dd
command using the of=
option:
sudo dd if=core-image-minimal-raspberrypi3.rpi-sdimg of=/dev/mmcblk0 bs=1MB
The if=
option refers to the input file, and bs=
is the block size.
Once the microSD card is ready, you can insert it into a Raspberry Pi, connect the keyboard and monitor, and boot. Afterwards, you can log in as root without a password.
Customizing the Image
Once the basic image is created, you can customize and extend it. This is a three-step process: First, a new layer is created, then you create a recipe for a new application you wish to integrate, and then a new image recipe.
For the first step, the new layer, run the following command in the poky
subdirectory:
bitbake-layers create-layer meta-lm
This command creates the new layer with a sample recipe. Then add this layer to the list in bblayers.conf
, which can either be done manually or with the bitbake-layers
command:
cd <I>Path/to/Build<I> bitbake-layers add-layer ../meta-lm
The new layer doesn't do anything until you add a recipe. In the present case, the recipe is a simple small C program in "Hello World" style: lm-hello.c
(Listing 2).
Listing 2
lm-hello.c
Create a lm-hello
directory below recipes-lm
and remove the sample recipe. In the new lm-hello
directory, you need a lm-hello_1.0.bb
file with the contents of Listing 3. The file extension bb
stands for BitBake Recipe; the underscore in the filename must be followed by a version number, which will be used later when bitbake
builds a package based on the recipe.
Listing 3
lm-hello_1.0.bb
The file itself consists of variable declarations and functions. The variables SUMMARY
and SECTION
act as metadata describing the content. LIC_FILES_CHKSUM
contains an MD5 checksum of the license file to ensure that the content has not changed since the recipe was written.
A reference to the source code follows, here in the form of a URI (SRC_URI
) and a specific revision (SRCREV
) of a Git repository. In this way, different versions of a recipe can exist, each referring to a different revision. The version number of the package is specified by PV
; in this case, the number comes from the version identifier in the filename.
The following lines apply to settings for the build process. The lm-hello
project is based on a makefile. Yocto can use a variety of build systems, including CMake, Autotools, and custom files. To support them, the file exports the variables EXTRA_OEMAKE
and TARGET_CC_ARCH
. These variables ensure that the right compiler with the right flags is used.
Whenever bitbake
processes a recipe, it goes through a series of steps. This recipe can use default values for most of these steps, except for the installation step. It needs a custom function that first creates a bin
directory (${bindir}
) below the stage area (${D}
), where it then installs the binary of lm-hello
.
As soon as the recipe is prepared, you can test it outside an image with bitbake
:
cd Path/to/Build bitbake lm-hello
The result is a package instead of an image. This package can be found at build/tmp/deploy/rpm
.
Two things are particularly noteworthy. First, even the simplest recipe always produces three packages at once: An installation package without an appendix in the filename, a development package with dev
in the name, and a debug package identifiable by dbg
in the name.
Second, the packages are always located in a CPU-specific subdirectory of build/tmp/deploy/rpm
(in the example, this is cortexa7t2hf_neon_vfpv4
) and not in a subdirectory named after the board. This means that the package can be used on all computers with the same CPU. The bitbake -g
option will help you find dependencies associated with the package. (See the box entitled "Finding Dependencies.")
Finding Dependencies
A manifest file attached to a Yocto image contains a list of all included packages, along with their version numbers and architecture details.
For example, the core-image-minimal-raspberrypi3.rpi-sdimg
image has a core-image-minimal-raspberrypi3.manifest
file. The file contains a line for the lm-hello
package, and it says:
lm-hello cortexa7t2hf_neon_vfpv4 1.0+git0 +6c2970ab52
To find the dependencies for the package, use the bitbake
command with the -g
option:
bitbake -g lm-hello
This command creates two files, task-depends.dot
and recipe-depends.dot
. The first file describes the order in which Yocto executes the bitbake
tasks, and the second describes the dependencies between the recipes. The .dot
files can be rendered to PNGs but are not quickly readable. For the lm-hello
package, there are more than 400 dependencies. If you repeat the exercise for lm-image-minimal
, you get more than 6,000 dependencies.
You can search the .dot
files for information. If, for example, you filter out all rows starting with lm-hello
, you see a result like the one in Listing 4. From this information, you can deduce that lm-hello
depends on the packages listed on the right. The remaining lines include headers that are not deployed, as well as the C library and other run-time dependencies of the C program.
Listing 4
Filtered Files
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
System76 Refreshes Meerkat Mini PC
If you're looking for a small form factor PC powered by Linux, System76 has exactly what you need in the Meerkat mini PC.
-
Gnome 48 Alpha Ready for Testing
The latest Gnome desktop alpha is now available with plenty of new features and improvements.
-
Wine 10 Includes Plenty to Excite Users
With its latest release, Wine has the usual crop of bug fixes and improvements, along with some exciting new features.
-
Linux Kernel 6.13 Offers Improvements for AMD/Apple Users
The latest Linux kernel is now available, and it includes plenty of improvements, especially for those who use AMD or Apple-based systems.
-
Gnome 48 Debuts New Audio Player
To date, the audio player found within the Gnome desktop has been meh at best, but with the upcoming release that all changes.
-
Plasma 6.3 Ready for Public Beta Testing
Plasma 6.3 will ship with KDE Gear 24.12.1 and KDE Frameworks 6.10, along with some new and exciting features.
-
Budgie 10.10 Scheduled for Q1 2025 with a Surprising Desktop Update
If Budgie is your desktop environment of choice, 2025 is going to be a great year for you.
-
Firefox 134 Offers Improvements for Linux Version
Fans of Linux and Firefox rejoice, as there's a new version available that includes some handy updates.
-
Serpent OS Arrives with a New Alpha Release
After months of silence, Ikey Doherty has released a new alpha for his Serpent OS.
-
HashiCorp Cofounder Unveils Ghostty, a Linux Terminal App
Ghostty is a new Linux terminal app that's fast, feature-rich, and offers a platform-native GUI while remaining cross-platform.