What is it

The Yocto Project (YP) is an open source collaboration project that helps developers create custom Linux-based systems regardless of the hardware architecture.

Essentially, it is a toolchain used to create customized Linux distributions for specific hardware systems, typically used in embedded systems.

Core Concepts

BitBake

The build tool introduced by the Yocto Project. Similar to tools like make, cmake, and bazel, but specifically designed for tasks like building system images.

Layers

Layers in the Yocto Project serve as the mechanism for modularization.

Typically, a layer contains:

  • All the files required for a specific hardware platform or board configuration.
  • A set of logically independent (and often reusable) files.

These are organized into a layer. A layer often contains multiple recipes.

Recipes

Recipes are similar to Makefiles in make. However, recipes not only handle the process of compiling source code into binaries but also manage tasks like fetching source code (e.g., clone from Git), unpacking, applying patches, configuring the build environment, and packaging software.

There are also special-purpose recipes, such as image recipes, which are used to create final images and include pre-packaged software.

Recipes are typically represented by .bb files and should follow specific naming (name_version.bb) and directory conventions.

Packages

Packages usually refer to the products compiled from the source code specified in a recipe.

Workflow

It is recommended to start with Yocto's official distribution, poky, and gradually add/modify it to create the desired distribution. If you are new to Yocto, it is advisable to first build a poky image and run it in QEMU to get a feel for it.

The build process for the poky project can be found in the official documentation. If your device has internet access, don't forget to configure mirrors as described in the documentation (you may need to install packages like python3-websockets), otherwise, the build process will take an unreasonably long time.

If you prefer using Docker, you can use this Dockerfile.

Downloading Existing Layers

cd poky
git clone <Layer Git URL>
# You may need to enter the cloned repo and switch to the correct branch
cd build
bitbake-layers add-layer ../<Layer Name>

Then, running bitbake core-image-* will produce an image based on the added layers.

Creating Your Own Layer

bitbake-layers create-layer <Layer Name>

This will generate a new layer in the poky directory.

Exporting the SDK

The SDK includes the cross-compilation toolchain, headers, and libraries required for developing applications on the target platform. If you only need to build binaries for a fixed target platform (image), you should use the SDK.

Run:

bitbake <image-name> -c populate_sdk

to create the SDK for the corresponding image.

You can find a .sh file in poky/build/tmp/deploy/sdk, which is the packaged SDK.

You can run this .sh file on another computer1 to use the toolchain without installing poky.

Exporting the Extensible SDK (eSDK)

Compared to the SDK, the Extensible SDK includes the devtool command-line tool, which makes it easier to modify recipes in existing layers of the distribution. If you want to create new layers or modify existing ones, you should use the eSDK.

bitbake <image-name> -c populate_sdk_ext

Similarly, you can run the resulting .sh file on another computer2 to install it. Then, you can use devtool to create and modify layers, as well as directly build images.

SDK vs eSDK

FeatureStandard SDKExtensible SDK
ToolchainYesYes
DebuggerYesYes
Size100+ MBytes1+ GBytes
devtoolNoYes
Build ImagesNoYes
UpdateableNoYes
Sysroot (libraries, headers, etc.)PredefinedDynamically updated
Installed PackagesNoYes
ConstructionPackagesShared State

In short, the standard SDK is mainly for developing binary applications for a fixed image, while the eSDK allows for some degree of image modification.

Recipe Configuration File Syntax and Key Variables

Refer to the official documentation.

Variables

Most of a recipe file consists of setting various variables.

In addition to direct assignments like A = B, you can also:

  • Use A += "B" to concatenate the string in A, a space, and "B". For example:

    A = "A"
    A += "B"
    # Now A is "A B"
    
  • Use .= for direct concatenation without a space:

    A = "A"
    A .= "B"
    # Now A is "AB"
    

    Alternatively, you can use :append =:

    A = "A"
    A:append = "B"
    # Now A is "AB"
    

Functions

BitBake supports functions written in shell and Python. Refer to the official documentation.

The main purpose of functions is to allow .bb files to define tasks. These task functions usually start with do_.

For example:

python foo() {
    bb.plain("second")
}
addtask foo after do_fetch before do_build

This creates a new task foo, which is executed after the fetch task and before the build task.

You can list all tasks in a recipe using bitbake <recipe-name> -c listtasks. Use bitbake <recipe-name> -c <task-name> to execute a specific task. For detailed information on managing tasks with bitbake, see the official documentation.

Inheritance

You can (and often should) inherit existing recipe templates. For example:

inherit cmake

This inherits the cmake template, which includes predefined tasks.

Variables and functions defined after inherit can override those in the template.

Common Variables

For a complete list of predefined variables, see the BitBake documentation and the Yocto documentation. Below are some of the most common ones.

SRC_URI

Specifies the location of the source code for the recipe. It supports fetching code from local files, FTP, Git repositories, web pages, etc.

Example:

SRC_URI = "git://example.com/foo.git;branch=main;name=first \
           git://example.com/bar.git;branch=main;name=second \
           http://example.com/file.tar.gz;name=third"
SRCREV

Specifies the version of the code to use. For example, SRCREV_first = "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15" means using the corresponding commit of foo.

DEPENDS

Specifies the build dependencies of the recipe.

RDEPENDS

Specifies the runtime dependencies of the package.

PACKAGES

Specifies the packages produced by the recipe, used for matching with other packages' RDEPENDS or the final IMAGE_INSTALL.

PN

The recipe name.

PV

The recipe version, e.g., the 0.1 in example_0.1.bb.

PROVIDES

Specifies the packages the recipe promises to produce, used for matching with other packages' DEPENDS.

WORKDIR

The directory where BitBake builds the recipe.

S

Specifies the directory where the source code is downloaded/unpacked/moved.

You may need to set this manually. For example, if SRC_URI = "git://...", you should write:

S = "${WORKDIR}/git"
FILES

Specifies the files to include in the package.

Example: FILES:${PN} += "${bindir}/mydir1 ${bindir}/mydir2/myfile"

IMAGE_INSTALL

Specifies the packages to be directly included in the image.

1

Installing the SDK requires some basic packages like python3, file, and xz-utils. Additionally, build tools like make and cmake are not included in the SDK and need to be installed separately. You can use the env command after setting up the SDK to see what it configures.

2

The eSDK requires more packages than the standard SDK, including diffstat, bzip2, gawk, cpio, gcc, g++, and perl.