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
-
ESET Discovers New Linux Malware
WolfsBane is an all-in-one malware that has hit the Linux operating system and includes a dropper, a launcher, and a backdoor.
-
New Linux Kernel Patch Allows Forcing a CPU Mitigation
Even when CPU mitigations can consume precious CPU cycles, it might not be a bad idea to allow users to enable them, even if your machine isn't vulnerable.
-
Red Hat Enterprise Linux 9.5 Released
Notify your friends, loved ones, and colleagues that the latest version of RHEL is available with plenty of enhancements.
-
Linux Sees Massive Performance Increase from a Single Line of Code
With one line of code, Intel was able to increase the performance of the Linux kernel by 4,000 percent.
-
Fedora KDE Approved as an Official Spin
If you prefer the Plasma desktop environment and the Fedora distribution, you're in luck because there's now an official spin that is listed on the same level as the Fedora Workstation edition.
-
New Steam Client Ups the Ante for Linux
The latest release from Steam has some pretty cool tricks up its sleeve.
-
Gnome OS Transitioning Toward a General-Purpose Distro
If you're looking for the perfectly vanilla take on the Gnome desktop, Gnome OS might be for you.
-
Fedora 41 Released with New Features
If you're a Fedora fan or just looking for a Linux distribution to help you migrate from Windows, Fedora 41 might be just the ticket.
-
AlmaLinux OS Kitten 10 Gives Power Users a Sneak Preview
If you're looking to kick the tires of AlmaLinux's upstream version, the developers have a purrfect solution.
-
Gnome 47.1 Released with a Few Fixes
The latest release of the Gnome desktop is all about fixing a few nagging issues and not about bringing new features into the mix.