Introduction
This is a high-level tutorial and the intention is not to cover the Yocto Project in depth. If you are interested in detailed information, we recommend that you read the Yocto Project Mega-Manual.
This tutorial will provide overview of what target images are within the Yocto project. We will try to cover some common use-cases and best practices by looking at the available example images and we will also go trough how to create custom images.
Prerequisites
To follow this tutorial, you will need:
- A configured Yocto environment. Please take a look at one of the following if you do not have this prepared:
- Enough Free Memory: Your development host should have at least 50 GBytes of free disk space for building images.
Images
The end goal for anyone using the Yocto Project should be to create a Linux distributions that is customized to match your product(s) requirements. The Yocto Project provides Poky, which is a reference embedded Linux distribution and a starting point to kick start your journey and should not be considered something that is complete.
Images are a central concept within the Yocto Project and essential to the definition of a Linux distribution. By creating a custom image you would have taken the first step to create a custom Linux distribution that is modeled for your product(s) requirements.
There are plenty reference images that one can inspect and derive your work from. To retrieve a list of available image recipes provided by poky
we can run:
find ../sources/poky/meta -name *-image-*.bb
These images are considered reference images, and the intention is not modify them and instead derive custom images from them. The most common approach is to derive a custom image from the core-image-base.bb
, and this would have been a bottom-up approach as the core-image-base.bb
only defines the essentials to get a hardware device to boot with.
Scope
For the sake of this tutorial lets set a couple of requirements that we want to accomplish on our target device.
We want to create two custom images:
- one for development (unsecure!)
- one for production
On the production image we would like to have the following packages installed:
- inotify-tools
inotify-tools is a C library and a set of command-line programs for Linux providing a simple interface to inotify. These programs can be used to monitor and act upon filesystem events
Additionally the development image should have the following features/packages:
- SSH server running on the device
- gdb, gdbserver and strace installed on the device
- evtest, i2c-tools, ethtool, fbset, memtester
- these are all applications useful during testing debugging various parts of the device
- our development image will only have a root user and no password required for login (unsecure!)
Building images
When using the Yocto Project, you will spend most of your time building images. The easiest way of starting a build is running,
bitbake core-image-base
NOTE! If this is the first time you are building an image in your Yocto Project environment, this can take several hours to complete depending on the resources available on your machine.
Once the image build has completed you will see a message similar to below (number of tasks might differ),
NOTE: Tasks Summary: Attempted 4923 tasks of which 5 didn't need to be rerun and all succeeded.
We should now have build artifacts available in tmp/deploy/images/*/
, and we can check by running:
ls -alh tmp/deploy/images/*/
Depending on which device you are targeting in your Yocto Project environment, the content of this directory can vary a lot but usually this contains:
- Bootloader binaries (u-boot.bin etcβ¦)
- Linux kernel binaries (kernel image and dtb)
- Root filesystem images (
core-image-base-*.ext4
) - Disk images for device provisionsing (
*.sdcard
,*.img
,*.sdimg
)
In this tutorial we are mostly interested in the root filesystem images, so lets take a closer look at this. Earlier we ran the command bitbake core-image-base
to build our image, but right now it is unclear what that image actually included.
We can inspect what packages where installed in the final rootfs image by running:
cat tmp/deploy/images/*/core-image-base-*.manifest
Above command will list all the packages and their respective versions that where installed in our root filesystem image (core-image-base-*.ext4
). What is installed in the image is typically defined in the target image recipe. In our case it is core-image-base.bb
and we can inspect the image recipe by running the following:
cat ../sources/poky/meta/recipes-core/images/core-image-base.bb
It might come as a surprise to new users that the actual content of core-image-base.bb
is quite sparse:
SUMMARY = "A console-only image that fully supports the target device \
hardware."
IMAGE_FEATURES += "splash"
LICENSE = "MIT"
inherit core-image
They key takeaway from above output is the following line:
inherit core-image
Which tells us that the definition of what actually gets installed is defined in the core-image.bbclass
. The core-image.bblcass
is common code for generating core reference images, and majority of image recipes will be derived from this bbclass.
I would recommend you to inspect the content of core-image.bbclass
:
cat ../sources/poky/meta/classes/core-image.bbclass
The content of core-image.bbclass
introduces some new concepts and I will try to covered some of them here,
IMAGE_FEATURES
The core-image.bbclass
implements the mapping of strings in the global variable IMAGE_FEATURES to predefined packagegroups.
What IMAGE_FEATURES allows us to do is to change the content of the core-image-base.bb
image without editing the file, and we can simply add pre-defined features to the global variable IMAGE_FEATURES. This also allows us to create definitions of IMAGE_FEATURES that will be applicable to all images that are derived from the core-image.bbclass
.
The following example will make sure that an SSH server is installed and it will use the dropbear application to satisfy this (alternative is ssh-server-openssh
):
echo 'IMAGE_FEATURES += "ssh-server-dropbear"' >> conf/local.conf
List of available IMAGE_FEATURES and a small description can be found in the Yocto Mega Manual - Image features section.
packagegroups
The name is self-explanatory and it is very common to group packages that together serve a common purpose in to something called packagegroup
. One example would be the packagegroup-core-boot
which is used in core-image.bbclass
. The description of the packagegroup-core-boot
is:
The minimal set of packages required to boot the device
Which means that by including packagegroup-core-boot
in your image you will get the essentials installed to boot the device. You can inspect the definition of packagegroup-core-boot.bb
:
cat ../sources/poky/meta/recipes-core/packagegroups/packagegroup-core-boot.bb
The packagegroup-core-boot
contains some advanced logic that I will not try to cover in this tutorial and it is instead left as an exerciser to the reader to explore this further.
IMAGE_INSTALL
Image recipes set IMAGE_INSTALL to specify the packages to install into an image through image.bbclass. Additionally, βhelperβ classes such as the core-image.bbclass
class exist that can take lists used with IMAGE_FEATURES and turn them into auto-generated entries in IMAGE_INSTALL in addition to its default contents.
Working with custom images
Create a custom layer
To be able to proceed with this tutorial we first must create a custom layer that will contain any custom modifications or additions. Please note that the tutorials on this site will re-use this layer and if you have already created this structure by following another tutorial you can skip this step.
Create a new layer called meta-stargazer
using the bitbake-layers
helper application:
bitbake-layers create-layer ../sources/meta-stargazer
This will create a basic structure in meta-stargazer
directory:
../sources/meta-stargazer/
βββ conf
β βββ layer.conf
βββ COPYING.MIT
βββ README
βββ recipes-example
βββ example
βββ example_0.1.bb
3 directories, 4 files
Include the layer in our Yocto Project environment:
bitbake-layers add-layer ../sources/meta-stargazer
Creating custom images
Create location where we will put our custom image recipe:
mkdir -p ../sources/meta-stargazer/recipes-core/images/
There is no hard requirement on the actual location of image recipe but it is a fairly common practice to put it in recipes-core/images
. Another common practice is to use the meta layer suffix as the parent directory, and in our case that would be recipes-stargazer/images/
.
Create the βproductionβ image per our defined requirements:
cat <<- 'EOF' > ../sources/meta-stargazer/recipes-core/images/stargazer-image.bb
SUMMARY = "Stargazer production image"
IMAGE_FEATURES += "splash"
LICENSE = "MIT"
inherit core-image
CORE_IMAGE_EXTRA_INSTALL = "inotify-tools"
EOF
Create the βdevelopmentβ image per our defined requirements:
cat <<- 'EOF' > ../sources/meta-stargazer/recipes-core/images/stargazer-dev-image.bb
SUMMARY = "Stargazer development image"
inherit core-image
require stargazer-image.bb
IMAGE_FEATURES += "ssh-server-dropbear tools-debug debug-tweaks"
CORE_IMAGE_EXTRA_INSTALL += "ethtool evtest fbset i2c-tools memtester"
EOF
The resulting structure and content of meta-stargazer
should look like this:
tree ../sources/meta-stargazer/
../sources/meta-stargazer/
βββ conf
β βββ layer.conf
βββ COPYING.MIT
βββ README
βββ recipes-core
β βββ images
β βββ stargazer-dev-image.bb
β βββ stargazer-image.bb
βββ recipes-example
βββ example
βββ example_0.1.bb
There is one additional optimization we can make to the current layout, and that is grouping our βtest applicationsβ in a packagegroup. This makes it easier to create additional variants of images, and reusing packagegroups across them.
Create directory for packagegroups:
mkdir -p ../sources/meta-stargazer/recipes-core/packagegroups/
It is a common practice to put the packagegroups
directory along side the images
directory in your layer structure.
Create stargazer-packagegroup-testapps.bb
:
cat <<- 'EOF' > ../sources/meta-stargazer/recipes-core/packagegroups/stargazer-packagegroup-testapps.bb
DESCRIPTION = "Stargazer test application packagegroup"
SUMMARY = "Stargazer packagegroup - tools/testapps"
PACKAGE_ARCH = "${MACHINE_ARCH}"
inherit packagegroup
RDEPENDS_${PN} = " \
ethtool \
evtest \
fbset \
i2c-tools \
memtester \
"
EOF
Update the stargazer-dev-image.bb
recipe to utilize the newly created stargazer-packagegroup-testapps
:
cat <<- EOF > ../sources/meta-stargazer/recipes-core/images/stargazer-dev-image.bb
SUMMARY = "Stargazer development image"
inherit core-image
require stargazer-image.bb
IMAGE_FEATURES += "ssh-server-dropbear tools-debug debug-tweaks"
CORE_IMAGE_EXTRA_INSTALL += "stargazer-packagegroup-testapps"
EOF
The resulting structure and content of meta-stargazer
should look like this:
tree ../sources/meta-stargazer/
../sources/meta-stargazer/
βββ conf
β βββ layer.conf
βββ COPYING.MIT
βββ README
βββ recipes-core
β βββ images
β β βββ stargazer-dev-image.bb
β β βββ stargazer-image.bb
β βββ packagegroups
β βββ stargazer-packagegroup-testapps.bb
βββ recipes-example
βββ example
βββ example_0.1.bb
Now we should be able to run the following to build our production image:
bitbake stargazer-image
and we should be able to run the following to build our development image:
bitbake stargazer-dev-image
Conclusion
In this tutorial we have covered the basics of how to customize and create images using the Yocto Project in the hopes that it will help you get started quickly without need of digging to deep in Yocto Project internals. The layer that we created (meta-stargazer
) an populated during this tutorial can be used a starting point for your own custom application/distribution layer.
Additionally you can find a very detailed explanation of the whole image building process in the Yocto Mega Manual - Bitbake section.
For further reading visit:
- Yocto Mega Manual - 2.2. The Yocto Project Layer Model
- Yocto Mega Manual - 2.5. Reference Embedded Distribution (Poky)
- Yocto Mega Manual - 7.1. Understanding and Creating Layers
- Yocto Mega Manual - 7.2 Customizing Images
If this tutorial was useful to you, please press like, or leave a thank you note to the contributor who put valuable time into this and made it available to you. It will be much appreciated!