Yocto: Part 9 – Customising images by adding your recipes

Welcome to part 9 in this series that we are doing on Yocto! In the previous parts, we started from scratch, learnt to build basic images for QEMU and Raspberry Pi machines, learnt how to created a new layer and write bitbake recipes for it. You can check out all of these posts using the links below!

Yocto: Part 1 – A Definitive Introduction

Yocto: Part 2 – Setting up Ubuntu host

Yocto: Part 3 – Build & run your first ever image!

Yocto: Part 4 – Building a basic image for Raspberry Pi

Yocto: Part 5 – Creating & adding a new layer to your image

Yocto: Part 6 – Understanding and creating your first custom recipe

Yocto: Part 7 – Writing recipes for tarballs (local and remote)

Yocto: Part 8 – Writing recipes that fetch from a Git repository

In this part, talk about bring our work done in parts 5 to 8 and customise a pre-existing image by adding our recipes to the image build. There are multiple ways to do this – we shall explore the most common methods.

Strategy for a custom image

The strategy for developing a custom image is pretty simple actually. You should take something that already exists and then add your secret sauce to it. There are a number of basic image recipes already within poky, open-embedded and the meta-layers provided to you by your machine providers. Make use of them! In a nutshell, the strategy can be visualised like this.

A simple visualisation of our strategy

This is much more time-saving, safe and future-proof than building an image from scratch because there are just so many things that can go wrong. For example, you may miss some essential packages that can break your build or even worse – the image builds but the system runs into a wall upon boot!

Bottomline – whenever feasible, don’t create a new image…. customise an existing one!

There are multiple methods to add your recipes to an existing image or build configuration. Let us take a look at the most common approaches starting with the easiest.

[Easiest] Method 1 – Customise the build configuration (edit local.conf file)

This is probably the easiest way to customise an image.

The build configuration can be edited by modifying the local.conf located in the build directory’s conf/ directory. But please note – this method only allows you to add packages and is not as flexible as creating your own customised image. The variable changes done in local.conf are applied to all builds equally and hence affect all images. If this is not acceptable to you i.e. you want the additional packages to be a part of only a particular image, then you will need to explicitly specify the image into which you want to add the packages.

To add a custom package to your image using the local.conf file, you can use the IMAGE_INSTALL variable with the _append operator. For example, to add the recipe we created in our last post to the build, we can add the following to the local.conf file.

IMAGE_INSTALL_append = " hwgit"

Use of the syntax is important – specifically, the space between the quote and the package name, which is hwgit in this example. This space is required since the _append operator does not add the space.

Furthermore, you must use _append instead of the += operator (recommended on some resources available online) if you want to avoid ordering issues. As shown in its simplest use, IMAGE_INSTALL_append affects all images. However, it is possible to extend the syntax so that the variable applies to a specific image only. For example, if you want to add a package to only a particular image (say core-image-minimal), the using IMAGE_INSTALL_append as below.

IMAGE_INSTALL_append_pn-core-image-minimal = " hwgit"

The above change to local.conf will add hwgit to the core-image-minimal image only. By the way, you can add packages using a similar approach through the CORE_IMAGE_EXTRA_INSTALL variable. If you use this variable, only core-image-* images are affected.

[Easier] Method 2 – Writing an image recipe based on an existing recipe

This is another very convenient and rather clean method of building a custom image.

The method is pretty simple – we create a new image recipe (.bb file), specify the image that we want to base our custom image on and then specify the new packages that we want to add to it.

Let us take our meta-ke layer that we have used in our previous posts – here, here, here and here. We create a new folder inside meta-ke called images and create a new recipe named ke-core-image-minimal.bb that looks like this.

# We base this recipe on core-image-minimal core image
require recipes-core/images/core-image-minimal.bb

# Adding a description is optional but often helps the user understand the purpose of the image
DESCRIPTION = "This is a customized version of the core-image-minimal image available in poky - this contains dev packages and installs the custom hello-world recipes present in meta-ke."

# We specify here the additional recipes to be added to the build
IMAGE_INSTALL += "hwlocal hwgit"

NOTE: We have used IMAGE_INSTALL variable directly here as we don’t have any ordering risk here. Also, we have not provided the white-space here unlike the IMAGE_INSTALL_append usage above as the += operation takes care of adding that for us.

That’s it – you can now build your custom ke-core-image-minimal.bb image!

[Easy] Method 3 – Customising the image recipe by adding to it

There may be cases when you want to modify an existing core image but cannot create a custom recipe .bb file due to reusability or legacy reasons. In such cases, instead of creating a brand new .bb file, you can create a .bbappend file with the same name as the core recipe that you wish to add to or modify. Bitbake has a facility to provide bbappend files that are a good way to append metadata to an existing configuration.

Let us say, we cannot create ke-core-image-minimal.bb as we did above in method 2. But, we still need to add hwgit and hwlocal to our core-image-minimal builds. We will create a core-image-minimal.bbappend in our meta-ke/images folder that looks something like below.

IMAGE_INSTALL += "hwlocal hwgit"

NOTE: This is a very simple example – but .bbappend files can become very complex when building complex images. The trick to keep things simple is to choose a suitable base image that is as close to your final custom image as possible.

Now, you can bake your custom image without changing the name of the base recipe but still having your custom packages inside the image.

Summary

In this post, we looked at three different ways to quickly add custom packages to your image build. There are some more approaches as well but these are pretty common, easy to implement and are in line with our core strategy to use the layered nature of Yocto to our advantage!

Which method did you like from methods 1, 2 and 3 above and why? Or do you use a different method altogether? Do let us know in the comment box!

See you in the next post!

Leave a Reply