# Yocto Best Practises

**URL:** <https://hub.mender.io/t/yocto-best-practises/5830>\
**Category:** Yocto Project\
**Created:** [May 9, 2023, 1:40pm UTC](https://hub.mender.io/t/yocto-best-practises/5830 "2023-05-09T13:40:44Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![TheYoctoJester](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/theyoctojester/32/1444_2.png) [@TheYoctoJester](https://hub.mender.io/u/TheYoctoJester)\
**Post date:** [May 9, 2023, 1:40pm UTC](https://hub.mender.io/t/yocto-best-practises/5830/1 "2023-05-09T13:40:44Z")

</div>

## Introduction

This tutorial will show some practises that have been found useful when setting up a build environment and maintaining itl

 ![LF_17_02_Yocto-Badge-Update_Participant_Final](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/1X/758c60e0e8309c4dc2519392b78668e7396c15bd.png)

## Version notes

This tutorial targets the following Yocto Project versions:

| Yocto Project | Tutorial applies | Maintenance |
| --- | --- | --- |
| nanbield (4.3) | :test_works: | :test_works: development |
| mickledore (4.2) | :test_works: | :test_works: current stable |
| langdale (4.1) | :test_works: | :test_works: stable |
| kirkstone (4.0) | :test_works: | :test_works: LTS |
| honister (3.4) | :test_works: | :test_fails: EOL |
| hardknott (3.3) | :test_workaround: [1](#footnote1) | :test_fails: EOL |
| gatesgarth (3.2) | :test_workaround: [2](#footnote2) | :test_fails: EOL |
| dunfell (3.1) | :test_workaround: [3](#footnote3) | :test_works: LTS |
| zeus (3.0) | :test_fails: [4](#footnote4) | :test_fails: EOL |
| warrior (2.7) | :test_fails: [4](#footnote4) | :test_fails: EOL |
| thud (2.6) | :test_fails: [4](#footnote4) | :test_fails: EOL |
| sumo (2.5) | :test_fails: [4](#footnote4) | :test_fails: EOL |
| rocko (2.4) | :test_fails: [4](#footnote4) | :test_fails: EOL |

1. Support for the `:`-override syntax was added to `hardknott` in the 3.3.3 patch release.  
2. Support for the `:`-override syntax was added to `gatesgarth` master only, no patch release.  
3. Support for the `:`-override syntax was added to `dunfell` in the 3.1.11 patch release.  
4. See the [EOL versions](#eolversions) appendix.

## Preliminary notes

This post aims to collect best practices around setting up, architecting and maintaining a [Yocto Project](https://yoctoproject.org) based build. They are by no means mandatory to follow or hard rules, but strategies that have proven successful in a number of real life projects.

Note: code/directory listings do not necessarily appear in alphabetical order or as listed by the shell, but arranged for best understanding.

# Base: Work directory

Typically, a work directory for a build consists of multiple layers and at least one build directory. As a general rule, active nesting should be avoided.

A very simple example looks like that:

```auto
my-directory
./poky
./poky/meta
./poky/meta-poky
./poky/meta-yocto-bsp
./poky/…
./build

```

Effectively, it is the result of executing the bare minimum setup:

```auto
mkdir my-directory
cd my-directory
git clone git://git.yoctoproject.org/poky.git
source poky/oe-init-build-env

```

A more real life example therefore might look like this:

```auto
my-directory
./poky
./poky/meta
./poky/meta-poky
./poky/meta-yocto-bsp
./poky/…
./meta-openembedded/meta-oe
./meta-openembedded/meta-python
./meta-openembedded/…
./meta-raspberrypi
./meta-mender/meta-mender-core
./meta-mender/meta-mender-demo
./meta-mender/meta-mender-raspberrypi
./meta-mender/…
./build

```

Adding layers to the build should be done using the `bitbake-layers` tool:

```auto
bitbake-layers add-layer ${path to layer}

```

In the above example, while being in the `build` directory, `meta-oe` would be added like this:

```auto
bitbake-layer add-layer ../meta-openembedded/meta-oe

```

**all following code snippets will expect a similar hierarchy, and unless noted otherwise, assume that `build` is the current working directory**

Using `bitbake-layers` for such operations is recommended for some reasons:

- the path is checked
- dependencies as defined in the `LAYERDEPENDS` variable of a layer are verified

# Avoid stacking up things in `local.conf`

When starting a project build it is very tempting to get going quickly, and making small incremental changes through the `local.conf` file.

## Create a layer early (…and create a layer often)

You can create and add your `myproject` layer like this:

```auto
bitbake-layers create-layer ../meta-myproject
bitbake-layers add-layer ../meta-myproject

```

The layer should also be put under revision control early on, preferably by using git.

## Build a custom image

As tempting as it is to throw `IMAGE_INSTALL` and `CORE_IMAGE_EXTRA_INSTALL` operations into `local.conf`, it makes revision control unnecessarily hard. Especially when trying to trim down a bloated demo image from a vendor, creating a custom image is definitely the better choice. You can start

out like this:

```auto
mkdir -p ../meta-myproject/recipes-myproject/images
cp ../poky/meta/recipes-core/images/core-image-base.bb ../meta-myproject/recipes-myproject/images/myproject-image.bb

```

Now you have a custom image that you can build with `bitbake myproject-image`, and start adding your application and packages.

## Create a custom distribution

Images are “just” recipes, which means that they have the sometimes surprising property of not being able to affect global properties. The probably

most prominent example is the init manager choice:

```auto
INIT_MANAGER += "systemd"

```

will have the desired effect in `local.conf`, but not in `myproject-image.bb`.

**Remember:** as it is possible to build recipes directly without targetting an image, any information that is inside an image would not be available

when building the recipe directly, resulting in different build output depending on how the recipe build was initiated. To avoid this inconsistency, recipes can never affect other recipes - their infomation is _local_ - only configuration information is _global_.

The correct place to put settings that have operating system wide effects is the `distro` configuration. For getting started, the easiest way is basing off `poky`.

```auto
mkdir -p ../meta-myproject/conf/distro
cat << EOF >> ../meta-myproject/conf/distro/mydistro.conf
require conf/distro/poky.conf
DISTROOVERRIDES = "poky"
EOF

```

To enable it, you can either prefix the call to `bitbake`:

```auto
DISTRO=mydistro bitbake myproject-image

```

or change the `DISTRO` setting in your `local.conf`, replacing `poky`:

```auto
DISTRO ?= "mydistro"

```

This gives you a custom distribution that behaves just like poky. You can start adding your modifications and settings in `../meta-myproject/conf/distro/mydistro.conf`. As your project evolves, you will probably gradually change things more and more, so its a good idea to check back into the file after some time and see if the original `require` is still needed. Also, if you make nontrivial changes it is advisable to change the reported [`DISTRO_NAME`](https://docs.yoctoproject.org/ref-manual/variables.html#term-DISTRO_NAME).

## Append, don’t modify

Layers that you do not own and maintain should be treated as immutable. Do not modify anything in there.

Why is that? When it comes to version control of your build (see below), you should rely on defined states of the layers upstream. Those defined states, usually in form of git hashes, enable reproducibility of your build. Any modification in an upstream layer therefore means that you either lose reproducility, or have to maintain your own fork. Neither is desirable.

The correct approach to change the behaviour of a layer outside of your control is to use an append. Those are denoted by the `.bbappend` file suffix.

This mechanism is commonly used in vanilla `poky` and `meta-openembedded` already. To see all the `.bbappend`s that are currently active in your build, use the `bitbake-layers` tool:

```auto
bitbake-layers show-appends

```

The name of your `bbappend` has to match the original recipe, including the version. If you want it to be more flexible, then you can use `%` as a wildcard in the version part.

Thus you can change most parts of recipe behaviour, such as variable assignments, adding patches, or injecting additional operations adjacent to tasks, using the same syntax and mechanisms as in the recipe.
