Europe Union
Published: 26/10/2023

Nailing It with Yocto Project: Crafting Your Custom Linux Masterpiece!

Are you tired of settling for generic, off-the-shelf Linux distributions that make you feel like you bought furniture from a specific Swedish retailer with unpronounceable names? So, my fellow tech-tinkerers, it’s time to put on your creative carpenter’s hats and explore the world of the Yocto Project—a woodworking shop for the digital era!

The Yocto Project allows you to custom-build your Linux image like a genuine craftsman of the embedded world, just like a master carpenter painstakingly picks the perfect wood and makes bespoke furniture with accuracy. So grab your virtual tool belt and get ready to hammer out your very own personalized Linux masterpiece!

Rafał Mikołajczyk
Rafał Mikołajczyk Embedded C Engineer

About me

I specialize in creating efficient applications on limited hardware, excelling in real-time system software development and cross-platform programming. My expertise encompasses electronics, design principles, and leveraging various programming languages. I bring dedication, collaborative skills, and analytical thinking to every project.
ornament ornament

Understanding Yocto Project:

To put it simply, the Yocto Project assists developers in creating their own customized version of Linux for small devices such as smart appliances, industrial machinery, and other embedded systems. It enables them to develop a compact and optimized Linux distribution that includes only the components required for the device’s functionality, resulting in an efficient and lightweight device. This customization capacity makes it a popular choice for developers working on a variety of embedded projects, as it allows them to have more control over the software running on their devices and ensuring it satisfies certain requirements.

The four primary reasons I chose the Yocto project:

  • Developers can create Linux versions for a variety of hardware architectures, guaranteeing that their software runs smoothly across several platforms. This adaptability is critical in the embedded and IoT domains, where devices frequently use a variety of CPUs and hardware configurations.
  • Yocto employs a layered architecture in which custom layers can be added to the build process, allowing developers to integrate their own programs, customizations, and drivers while still benefiting from the shared resources offered by Yocto’s core layers.
  • Yocto comes with a completely automated build mechanism that speeds up the process of creating the Linux distribution. Yocto’s build tools handle the intricacies of cross-compilation and dependency management, allowing for a speedier and more efficient development process.
  • The Yocto Project has a huge and active development and contributor community. This community offers helpful support, documentation, and knowledge sharing, allowing developers to troubleshoot problems, find solutions, and learn from the experiences of others.

In essence, both the Yocto Project and carpentry involve a combination of creativity, expertise, customization, and practicality to develop optimal and useful final products that answer unique demands and settings. The joy and satisfaction of transforming raw materials into something useful and unique arises in both woodworking and building a customized Linux image.

Gathering Your Tools:

We’ll need certain tools to get started with Yocto. I built my example project on a Windows machine, but you can use Linux or MacOS instead. We will use virtualization, thus we will only need vscode and Docker Desktop app.

https://www.docker.com/products/docker-desktop/
https://code.visualstudio.com

Another optional supplementary tool that will make transferring ready images easier in my situation (Windows) is balenaEtcher. You can donwload it from here: https://etcher.balena.io/#download-etcher.

Building Your First Project:

Now, let’s dive into the step-by-step tutorial 🙂

Step 1 – Blueprinting (Setting Up Environment):

We will be using devcontainer, more info about you can find here:

Create project directory and inside such structure:

.
|-- .devcontainer
|   `-- devcontainer.json
|   `-- Dockerfile.ubuntu

Devcontainer

Here You can see my devcontainer.json file:

and Dockerfile: 

This example shows how to create a virtual volume, which is especially useful on Windows and MacOS, because case sensitive partitions are disabled by default (we can’t compile Linux without a case sensitive file system). As a result, all created artifacts will remain on the virtual volume. Volume can be accessed via the DockerDesktop app.

Containers will be produced based on dockerfiles (as in this example) or ready images, depending on your requirements. When devcontainer.json is complete, we can begin using it by typing ‘code.’ within the working directory to launch vscode. Vscode after your permission will generate a container and attach to it automatically. We can now work remotely by using vscode to change source and configuration files, and our terminal is also linked to our Docker container.

Step 2 – Selecting the Lumber (Choosing Layers):

Choosing Yocto layers is similar to selecting the right wood for a woodworking project. Each layer adds specific components to your Linux image, just as each wood type adds distinct qualities to a piece of furniture. Do you need a solid foundation? Choose a hardwood layer. Do you require a polished user interface? Choose an elegant veneer layer. The final look, feel, and functionality of your digital creation are defined by your layer selection, just as it is by material selection. Yocto documentation will now be your friend, but remember to choose your linux version wisely – it’s a requirement for a lot of layers created by the community.

In this tutorial, I used ‘kirkstone,’ the most recent release of poky with LTS support.

So inside vscode open terminal and navigate to your workdir and type:

After clonning our workdir will look like this:

.
├── meta-openembedded
├── meta-raspberrypi
└── poky-kirkstone

Create build directory

Following that, our working directory should have been enriched with a new build folder :

.
├── build
├── meta-openembedded
├── meta-raspberrypi
└── poky-kirkstone

Adding layers to yocto

Inside build folder call:

And the output should be:

At this point, we have everything we need to begin configuring and generating the base Yocto image.

Step 3 – Cutting of the Pieces (Configure the Image):

After we’ve carefully selected all of our materials and set up our virtual workbench, it’s time to put on our carpenter’s thinking cap. We’re configuring our Yocto recipes and specifying the size and components of our dream piece of furniture, our customized Linux image, just like a carpenter plans the joints and measures the dimensions. Let’s make it as strong, functional, and beautiful as we can!

Configure image – Yocto

We will configure core-image-base image, it is a basic minimal image just a console. Open build/conf/local.conf file and edit / add options:

We select our target machine’s name, followed by the download directory where all sources will be downloaded. By configuring SSTATE_DIR, we give Yocto a location to cache all packages, making future work faster. EXTRA_IMAGE_FEATURES is in charge of extra features embedded within the distribution (in my case, an ssh server). Finally, the variable CORE_IMAGE_EXTRA_INSTALL will collect all extra apps; I included my favorite command line notepad called ‘nano’.

Check build configuration

result:

Fetch all packages needed to generate image

Configure wifi

To enable wifi from device startup, edit the configuration file wpa-supplicant.conf located at poky-kirkstone/meta/recipes-connectivity/wpa-supplicant/wpa_supplicant.conf-sane to look like this. MYSSID and MY-SECURE_PASSKEY must be entered.

spec: https://w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf

After we have edited the configuration file, we must create a start-up script to start the wpa-supplicant service with our configuration. Add the following lines to the file start-wifi.sh in poky-kirkstone/meta/recipes-core/initscripts/initscripts-1.0/start-wifi.sh:

Because we are not using a DHCP client in this example, the IP address is static. Must be appropriate for your local network.

To incorporate our changes, we must now modify the bitbake init scripts. Edit the following section in poky-kirkstone/meta/recipes-core/initscripts/initscripts_1.0.bb:

Step 4 – Assembling the Pieces (Building the Image):

Finally, after all of our customization, we can generate the image. It will take some time because the kernel and all libraries and apps must be compiled, so please be patient…

The raw disk image is core-image-base-raspberrypi0-wifi.wic.bz2, which can be found in the directory tmp/deploy/images/raspberrypi0-wifi/.

The WIC file can be flashed directly to an SD card or an eMMC:

  • Extract the WIC file:

Dump image to the SD Card at /dev/sdb

Or use Raspberry Pi Imager or balenaEtcher to flash it. https://etcher.balena.io

After successfully building and flashing the device, connect power to it and wait for it to connect to your local wifi. Attempt to connect via ssh with device:

Note: Because the default attribute “debug-tweaks” in the section ‘EXTRA_IMAGE_FEATURES’@build/conf/local.conf is added, the root user does not have a password when connecting via ssh.

Finishing Touches:

Now that our Yocto image is complete, it’s time to put it through its paces on our target hardware. Consider it a carpenter’s final inspection, where we inspect every joint and surface for perfection. Let’s face it: not everything in coding or carpentry goes perfectly. Consider our Yocto project to be a finely crafted piece of furniture; we may occasionally encounter wobbly legs or crooked corners. Not to worry! It’s similar to repairing shaky furniture legs. It only takes a shim or a clever twist to get things back on track. And remember that separate Yocto layer we talked about earlier? It’s similar to adding reinforcements to our furniture in order to ensure that our customizations fit snugly and elegantly. So, let us channel our inner carpenter and confront those wobbles. After all, it’s the difficulties that make the end result all the more satisfying!

New custom layer

Finally, we try to refactor our changes and move them to a different layer. As a result, our changes will be independent of Poky and other layer releases. Create new layer:

this will create new directory:

.
├── build
├── meta-openembedded
├── meta-raspberrypi
├── meta-custom-layer  <==
└── poky-kirkstone

New layer can be added manualy to build/conf/bblayers.conf, or we can use bitbake to do it:

Note: bitbake-layers add-layer uses absolute path, that can be unconfortable for future maintenance.

We can check if layer is added by calling:

Witch should outcome as:

New custom recipe

Inside the configuration file of our new layer wildcard entry is added:

All *.bb and .bbappend files in ‘recipes-‘ directories will be parsed.

We previously modified the file wpa_supplicant.conf-sane, so a new file must be provided to replace the original one in poky-kirkstone/meta/recipes-connectivity/wpa-supplicant.

Inside the new layer, we create the following file: meta-custom-layer/recipes-connectivity/wpa-supplicant/wpa-supplicant_%.bbappend (you can start with the current example.bb).

We can see if bitbake parses our append by doing the following:


and the outcome:

Replace default wpa-supplicant.conf

Inside our new recipe create a file structure as below:

meta-custom-layer
.
├── conf
│   └── layer.conf
├── COPYING.MIT
├── README
└── recipes-connectivity
    └── wpa-supplicant
        ├── files
        │   └── wpa_supplicant.conf-sane
        └── wpa-supplicant_%.bbappend

The wpa-supplicant directory stores recipe for replacing wpa_supplicant.conf with files/wpa_suplicant.conf-sane.

wpa-supplicant_%.bbappend:

The parameter ‘SRC_URI’ is expanded with the path to the new file, and the script is appended to the recipe do_install task commands required to copy our file to the correct location. Poky-kirkstone/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant_2.10.bb is the foundation for this script.

Creating start-wifi.sh

Wifi starting script must be placed in our system’s etc directory, which requires changes to recipes-core. Create a new recipe for that as below:

meta-custom-layer
.
├── conf
│   └── layer.conf
├── COPYING.MIT
├── README
├── recipes-connectivity
│    └── wpa-supplicant
│        ├── files
│        │   └── wpa_supplicant.conf-sane
│        └── wpa-supplicant_%.bbappend
└── recipes-core
     └── initscripts
         ├── files
         │   └── start-wifi.sh
         └── initscripts_%.bbappend

So initscripts_%.bbappend look like this:

Conclusion:

And there you have it – a journey that may have felt like woodworking at times, but has resulted in a truly one-of-a-kind digital creation. The Yocto Project is more than a tool; it’s a carpentry-inspired journey into building custom Linux systems. It functions as a chisel, saw, and blueprint all in one.

Remember that your customized Linux image, like a master carpenter’s creation, is a testament to your creativity. You’ve not only learned how to build it from the ground up, but also how to customize it like a pro – with separate, elegant layers that fit seamlessly.

Allow the Yocto Project to be your trusted toolkit as you progress in your tech-savvy carpentry journey. Accept the customization, challenges, and satisfaction that comes with seeing your creation come to life. Your technological workbench is ready for you to create digital masterpieces in the same way that a carpenter brings wood to life. Happy making!

Estimate your project.

Just leave your email address and we’ll be in touch soon
ornament ornament