Baking Our First Poky-Based System
Let’s get our hands dirty! In this chapter, we will understand the basic concepts involved in the Poky workflow. We will cover the steps to download, configure, and prepare the Poky build environment and bake something usable. The steps covered here are common for testing and development. They will give us some experience using Poky and a taste of its capabilities.
Preparing the build host system
The use of macOS as a host system is possible. Still, it involves using the CROss PlatformS (CROPS) framework, which leverages Docker, allowing the use of foreign operating systems, including macOS. For more information, you can refer to the Setting Up to Use CROss PlatformS (CROPS) section from the Yocto Project Development Tasks Manual (https://docs.yoctoproject.org/4.0.4/dev-manual/start.html#setting-up-to-use-cross-platforms-crops).
Next, we will provide the necessary information to start the build host system preparation.
Using Windows Subsystem for Linux (WSLv2)
You can set up a Linux distribution on Windows if you are a Windows user. WSLv2 is only available for Windows 10+ builds greater than 18917. WSLv2 allows development using the Yocto Project. You can install the Linux distribution from the Microsoft Store.
Please refer to the Setting Up to Use Windows Subsystem For Linux session (https://docs.yoctoproject.org/4.0.4/dev-manual/start.html#setting-up-to-use-windows-subsystem-for-linux-wslv2) from the Yocto Project Development Tasks Manual (https://docs.yoctoproject.org/4.0.4/dev-manual/index.html). Once you have WSLv2 set up, you can follow the next sections as if you were running on a native Linux machine.
Preparing a Linux-based system
The process needed to set up our host system depends on the Linux distribution we use. Poky has a set of supported Linux distributions. Let’s suppose we are new to embedded Linux development. In that case, it is advisable to use one of the supported Linux distributions to avoid wasting time debugging issues related to the host system support.
If you use the current release of one of the following distributions, you should be good to start using the Yocto Project on your machine:
To confirm whether your version is supported, it is advisable to check the official documentation online in the Required Packages for the Build Host section (https://docs.yoctoproject.org/4.0.4/ref-manual/system-requirements.html#required-packages-for-the-build-host).
If your preferred distribution is not in the preceding list, it doesn’t mean it is not possible to use Poky on it. Your host development system must meet some specific versions for Git, tar, Python, and GCC. Your Linux distributions should provide compatible versions of those base tools. However, there is a chance that your host development system does not meet all these requirements. In that case, you can resolve this by installing a buildtools tarball that contains these tools, as detailed in Required Git, tar, Python, and GCC Versions (https://docs.yoctoproject.org/4.0.4/ref-manual/system-requirements.html#required-git-tar-python-and-gcc-versions).
We must install a few packages on the host system. This book provides instructions for Debian and Fedora, our preferred distributions, which we will look at next. The set of packages for other supported distributions can be found in the Yocto Project Reference Manual (https://docs.yoctoproject.org/4.0.4/ref-manual/system-requirements.html#required-packages-for-the-build-host).
$ sudo apt install 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 pylint3 xterm python3-subunit mesa-common-dev zstd liblz4-tool
$ sudo dnf install gawk make wget tar bzip2 gzip python3 unzip perl patch diffutils diffstat git cpp gcc gcc-c++ glibc-devel texinfo chrpath ccache perl-Data-Dumper perl-Text-ParseWords perl-Thread-Queue perl-bignum socat python3-pexpect findutils which file cpio python python3-pip xz python3-GitPython python3-jinja2 SDL-devel xterm rpcgen mesa-libGL-devel perl-FindBin perl-File-Compare perl-File-Copy perl-locale zstd lz4
Downloading the Poky source code
After we have installed the required packages on our development host system, we can download the current LTS version (at the time of writing) of Poky source code using Git, with the following command:
$ git clone https://git.yoctoproject.org/poky -b kirkstone
Learn more about Git at https://git-scm.com.
Figure 2.1 – The content of the poky directory after downloading
Preparing the build environment
$ source oe-init-build-env [build-directory]
[build-directory] is an optional parameter for the name of the directory where the environment is configured. If it is empty, it defaults to
[build-directory] parameter is the place where we perform the builds.
The output from
source oe-init-build-env build displays some important configurations such as the file location, some project URLs, and some common targets, such as available images. The following figure shows an output example:
Figure 2.2 – Output of the source oe-init-build-env build command
Knowing the local.conf file
When we initialize a build environment, it creates a file called
build/conf/local.conf. This config file is powerful, since it can configure almost every aspect of the build process. We can set the target machine and the toolchain host architecture to be used for a custom cross-toolchain, optimize options for maximum build time reduction, and so on. The comments inside the
build/conf/local.conf file are excellent documentation and a reference of the possible variables and their defaults. The minimal set of variables that we probably want to change from the default is the following:
MACHINE ??= "qemux86-64"
MACHINE variable is where we determine the target machine we wish to build. At the time of writing, Poky supports the following machines in its reference BSP:
beaglebone-yocto: This is BeagleBone, which is the reference platform for 32-bit ARM
genericx86: This is generic support for 32-bit x86-based machines
genericx86-64:This is generic support for 64-bit x86-based machines
edgerouter: This is EdgeRouter Lite, which is the reference platform for 64-bit MIPS
The machines are made available by a layer called
meta-yocto-bsp. Besides these machines, OpenEmbedded Core, inside the
meta directory, also provides support for the following Quick Emulation (QEMU) machines:
qemuarm: This is the QEMU ARMv7 emulation
qemuarmv5: This is the QEMU ARMv5 emulation
qemuarm64: This is the QEMU ARMv8 emulation
qemumips: This is the QEMU MIPS emulation
qemumips64: This is the QEMU MIPS64 emulation
qemuppc: This is the QEMU PowerPC emulation
qemuppc64: This is the QEMU PowerPC 64 emulation
qemux86-64: This is the QEMU x86-64 emulation
qemux86: This is the QEMU x86 emulation
qemuriscv32: This is the QEMU RISC-V 32 emulation
qemuriscv64: This is the QEMU RISC-V 64 emulation
Extra BSP layers available from several vendors provide support for other machines. The process of using an extra BSP layer is shown in Chapter 11, Exploring External Layers.
local.conf file is a convenient way to override several global default configurations throughout the Yocto Project’s tools. Essentially, we can change or set any variable – for example, adding additional packages to an image file. Changing the
build/conf/local.conf file is convenient; however, the source code management system usually does not track temporary changes in this directory.
Building a target image
$ ls meta*/recipes*/*images/*.bb
All the recipes provide images that are a set of unpacked and configured packages, generating a filesystem that we can use with hardware or one of the supported QEMU machines.
Next, we can see the list of most commonly used images:
core-image-minimal: This is a small image allowing a device to boot. It is handy for kernel and bootloader tests and development.
core-image-base: This console-only image provides basic hardware support for the target device.
core-image-weston: This image provides the Wayland protocol libraries and the reference Weston compositor.
core-image-x11: This is a basic X11 image with a terminal.
core-image-sato: This is an image with Sato support and a mobile environment for mobile devices that use X11. It provides applications such as a terminal, editor, file manager, media player, and so on.
core-image-full-cmdline: A console-only image with more full-featured Linux system functionality installed.
There are other reference images available from the community. Several images support features, such as Real Time,
initramfs, and MTD (flash tools). It is good to check the source code or the Yocto Project Reference Manual (https://docs.yoctoproject.org/4.0.4/ref-manual/index.html) for the complete and updated list.
The process of building an image for a target is straightforward. But first, we need to set up the build environment using
source oe-init-build-env [build-directory] before using BitBake. To build the image, we can use the template in the following command:
Figure 2.3 – How to build a recipe using BitBake
We will use
MACHINE = "qemux86-64" in the following examples. You can set it in
For example, to build
core-image-full-cmdline, run the following command:
$ bitbake core-image-full-cmdline
Running images in QEMU
We can use hardware emulation to speed up the development process, as it enables a test run without involving any actual hardware. Fortunately, most projects have only a tiny portion that is hardware-dependent.
QEMU is a free, open source software package that performs hardware virtualization. QEMU-based machines allow testing and development without real hardware. ARMv5, ARMv7, ARMv8, MIPS, MIPS64, PowerPC, PowerPC 64, RISC-V 32, RISC-V 64, x86, and x86-64 emulations are currently supported. We will go into more detail about QEMU usage in sw, Speeding Up Product Development through Emulation – QEMU.
$ runqemu <machine> <zimage> <filesystem>
<machine> is the machine/architecture to be used as
qemux86-64, or any other supported machine. Also,
<zimage> is the path to a kernel (for example,
<filesystem> is the path to an
ext4 image (for example,
filesystem-qemux86-64.ext4) or an NFS directory. All parameters in the preceding call to
<filesystem> are optional. Just running
runqemu is sufficient to launch the image in the shell where the build environment is set, as it will automatically pick up the default settings from building the environment.
So, for example, if we run
runqemu qemux86-64 core-image-full-cmdline, we can see something similar to that shown in the following screenshot:
Figure 2.5 – The QEMU screen during the Linux kernel boot
Figure 2.6 – The QEMU screen during user login
We can log in to the
root account using an empty password. The system behaves as a regular machine, even when executed inside the QEMU. The process to deploy an image in real hardware varies, depending on the type of storage used, the bootloader, and so on. However, the process of generating the image is the same. We explore how to build and run an image in real hardware in Chapter 15, Booting Our Custom Embedded Linux.
In this chapter, we learned the steps needed to set up Poky and get our first image built. Then, we ran that image using
runqemu, which gave us a good overview of the available capabilities. In the next chapter, we will introduce Toaster, a human-friendly interface for BitBake. We will use it to build an image and customize it further.