Understanding Yocto Project Layers: A Modular Approach to Embedded Systems Development
In the world of embedded systems, flexibility and modularity are key to managing complex projects efficiently. The Yocto Project, a powerful build system for creating custom Linux distributions, embraces this philosophy through the use of layers. These layers are essentially sets of repositories that contain the instructions and metadata required to build a specific target image. By leveraging layers, developers can modularize their projects, reusing and sharing previously developed metadata to streamline the build process.
What Are Yocto Project Layers?
Layers in the Yocto Project can be thought of as building blocks that contain a collection of recipes. These recipes define how to fetch, configure, compile, and package software components needed for the selected target device. By organizing these recipes into layers, Yocto promotes a structured and reusable approach to managing project metadata. This modular design allows developers to:
Reuse Existing Code: By utilizing layers created by others, you can save time and effort, building on the work of the broader Yocto community.
Maintain Modularity: Layers help in isolating different components of a project, making it easier to manage changes and updates.
Facilitate Collaboration: Since layers can be independently maintained, different teams or individuals can work on separate layers without interfering with each other.
Exploring Available Layers
One of the major advantages of using Yocto is the ability to tap into a vast repository of existing layers contributed by the community. These layers cover a wide range of functionalities, from support for different hardware platforms to specific software packages. To explore the available layers, you can visit the following
OpenEmbedded Layer Index: https://layers.openembedded.org/layerindex/branch/master/layers/
This resource provides a comprehensive list of layers available for different versions of Yocto, helping you find exactly what you need for your project.
Checking Layers in Your Yocto Distribution
To get started with layers in Yocto environment, you first need to check which layers are already included in the distribution. Follow these steps:
Set Up the Build Environment:
Begin by navigating to your Yocto project directory, typically referred to as poky. Then, initialize the build environment using the following command:
source oe-init-build-env
Display the Active Layers:
Once environment is set up, you can view the currently active layers in your Yocto distribution by running:
bitbake-layers show-layers
This command will start the BitBake server (if not already running) and list all the layers currently configured in the environment.
Example Output:
The output of the bitbake-layers show-layers command will display something similar to the following:
layer | path | priority |
meta | /home/aaksha/Desktop/Repos/yocto/layers/poky/meta | 5 |
meta-poky | /home/aaksha/Desktop/Repos/yocto/layers/poky/meta-poky | 5 |
meta-yocto-bsp | /home/aaksha/Desktop/Repos/yocto/layers/poky/meta-yocto-bsp | 5 |
Here, the priority is useful when there are two layers and they contain same recipes
Layer priority is used to manage and resolve conflicts when multiple layers provide the same metadata, recipes, or configurations. The priority helps BitBake determine which layer should take precedence when such conflicts occur.
How Priority Works?
- Layer Priority: Each layer can have a priority value assigned in its layer.conf file using the BBFILE_PRIORITY variable. The layer with the higher priority value will override files from layers with lower priority values when there is a conflict.
- Conflict Resolution: If two layers provide the same recipe or configuration file, the one from the layer with the higher priority will be used. If the priorities are equal, Yocto's default behavior will apply, which typically means the file in the layer listed later in the BBLAYERS list takes precedence
Example:
Consider two layers: meta-layerA with a priority of 6 and meta-layerB with a priority of 8. If both layers provide a recipe for package-x, the recipe from meta-layerB will be used because it has a higher priority.
In the provided output, meta, meta-poky, and meta-yocto-bsp all have a priority of 5.
This means that if these layers provide conflicting recipes or configurations, BitBake will use other criteria (like the order in BBLAYERS) to decide which one to use, rather than relying on priority alone.
Why Set Priorities?
- Customization: If you create custom layers (like meta-embedded-related) that override or extend recipes from base layers, you might set a higher priority for your custom layer to ensure changes take precedence.
- Dependency Management: Some layers are designed to extend or modify the behavior of other layers, and their priority is set to ensure this happens correctly.
- Conflict Avoidance: When working with multiple third-party layers, setting priorities can help avoid conflicts and ensure a predictable build.
How to Set Priority?
In the layer.conf of the custom layer (e.g., meta-embedded-related), you set the priority like this:
BBFILE_PRIORITY_meta-embedded-related = "8"
Prerequisites
Follow the well drafted Yocto documentation steps: https://docs.yoctoproject.org/brief-yoctoprojectqs/index.html#building-your-image to build a basic Yocto image with minimal features.
Execution
Shown below are the final demo steps to add a custom Yocto layer to add own psplash screen. PSplash (Plymouth Splash) is a lightweight, simple splash screen utility commonly used in embedded Linux systems to display a graphical boot screen while the system is starting up.
Step 1: Basic Qemu image run using gtk graphic
On building a basic Yocto image using the link mentioned in the prerequisites, you should be able to run the image on Qemu using following command.
sudo qemu-system-x86_64 -kernel bzImage -drive file=core-image-minimal-qemux86-64.rootfs.ext4,format=raw,if=virtio -append "root=/dev/vda rw console=ttyS0" -enable-kvm -m 512 -net nic -net user -display gtk
This verifies the preliminary build is functional and booting up on Qemu
Now, the next step would be to add layer for configuring custom Hogwarts image as splash screen image.
Step 2: Creating meta-yocto-splash-img layer using following commands
Below commands take you inside poky/build directory
cd poky
source oe-init-build-env
Then to create the layer
bitbake-layers create-layer ../meta-yocto-splash-img
Step 3: Creating recipe and adding required files to the custom layer
Then once you see the meta-yocto-splash-img layer inside poky
create a directory here
mkdir -p recipes-core/psplash/files
Then inside files, place custom yocto-custom-splash-img.png image file that is in .png format
Then going back to psplash folder one directory,
create psplash_git.bbappend using command
touch psplash_git.bbappend
Step 4: Updating bbappend file to override default bitbake core contents
The .bbappend file in the Yocto Project is a mechanism for extending or modifying an existing BitBake recipe (.bb file). The .bbappend file allows you to add or override parts of the original recipe without directly modifying the original .bb file. This is particularly useful for customizing recipes provided by upstream layers or for maintaining custom changes separately.
In the demo, Yocto project offers psplash_git.bb bitbake recipe.
Therefore, using psplash_git.bbappend file with below contents, in order to provide the custom image path to the SPLASH_IMAGES variable so that this .bbappend will override the variable in psplash_git.bb file
Also, it is required to prepend the do_install API in psplash_git.bb for storing the custom splash image in the path as shown in the following screenshot. The do_install task in a Yocto Project recipe is responsible for copying and organizing the built files into the appropriate directories within the target root filesystem, setting them up for packaging and deployment.
Step 5: Verifying default layer.conf contents for the newly created custom layer
Then layer.conf contents seem to remain unchanged and the configurations used were the default ones as seen in the below screenshotStep 6: Enabling required dependencies in local.conf file
The local.conf was updated as seen below to enable framebuffers and psplash. The framebuffer provides a simple interface for rendering images and graphics on the display without needing a full graphical environment, making it ideal for showing splash screens during system boot before the full graphical user interface is available.