Yocto has layers, like Ogres and onions. Each layer brings a new set of tools, functions or configuration to the table. A custom image usually means putting together a whole stack of them, five, ten, or even more layers. Keeping all of them in sync? That’s where things can get messy, unless the right tools are used.

Keep the layers in sync, but why?#

The meta-layers of Yocto are complex constructs - each one has multiple branches, typically one per Yocto release, and each branch comes with a shitload of commits. In practice, only the LTS (long term support) and actively maintained branches receive ongoing updates. At the moment, the LTS Yocto releases are Kirkstone (until Apr. 2026) and Scarthgap (util April 2026).

When assembling a custom distribution, it’s essential to treat the layer setup as a consistent snapshot in time, all layers should be pinned to compatible commits from the same release branch and roughly the same point in time.

Introducing: repo#

The solution to the synchronization problem is called repo - a repository management tool build on top of Git. Similar to git submodules, repo can fetch specific branches and commits of multiple meta-layers, and does all of it based on a configuration file manifest.xml. repo was created by Google to help with the management of the Android and Yocto repositories and slowly is becoming the standard tool for putting Yocto distributions together. Many popular vendors like NXP or STM already use it.

Install Instructions#

repo is a python script at its core and can be installed as such simply by downloading a single file from google. The script will then take care of creating a repo environment by fetching the rest of the resources.

# manual install
mkdir -p ~/.bin
PATH="${HOME}/.bin:${PATH}"
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
chmod a+rx ~/.bin/repo

That’s not the only option though. repo is available in most of the package managers of the popular Linux distributions.

Debian / Ubuntu

sudo apt-get install repo

Gentoo

sudo emerge dev-vcs/repo

Repo Manifest#

The previously mentioned repo manifest file serves as the foundation of a custom Yocto distribution. The manifest itself must be hosted in a Git repository. A common best practice is to align the manifest’s branch names with Yocto release names - for example, use branches like kirkstone or scarthgap to reflect the corresponding Yocto version.

For the purpose of this blog and to exercise repo skills, I made a simple project on github with a manifest for a Raspberry Pi-based Yocto distribution: rpi-manifest. This repository contains the complete manifest used in this example, and the rest of the article walks through the process of building it step by step Synthax and Structure

Manifests are always XML files. Are you thinking messy tags and never ending indentations? Well, that should not be the case here, as the indentations are rather shallow, but tags are real and it’s possible to use them efficiently. The manifest starts with a line stating the XML version and encoding - standard XML stuff:

<?xml version="1.0" encoding="UTF-8"?>

then, the tag opening the manifest meta-layer configuration follows

<manifest>
# manifest content goes here
</manifest>

repo manifest files have a syntax rich in keywords like revision, remote, fetch, path, project and a few more, which are described in detail in the Manifest Format documentation provided by Google. As this article is based on my own work experience, only the syntax options I have personally used are introduced below.

Remote

The tag remote assigns a name to a git URL - think of it as a shortcut to that URL. Intuitively, the name is defined with the name attribute, and the URL itself with fetch. The URL should point to the location of a parent project or a group, which members are specified further down with the project tags.

<remote name="yp"          fetch="https://git.yoctoproject.org"/>

Project

project tag describes a git repository to be cloned. A few attributes go along with it, to provide the detailed info about how the repository should be cloned.

  • name - name of the git project. The value of this attribute is appended to the URL specified in the remote attribute, followed by .git.

  • remote - the parent URL of the requested git project. This could be either the group URL or user main workspace, just like in the remote tag. What’s more is that the remote tags can be referenced here, by passing the remote tag name value, this is later expanded into the full URL.

  • path - the destination path of the cloned project, the path is relative to the top directory of the repo client. Usually the format is "sources/<project-name>"

  • revision - name of the Git branch the manifest wants to track for this project, a commit hash should also work.

  • upstream - according to the docs it does not differ that much from revision, but to my understanding it should be set to the fetched branch name.

<project name="poky" remote="yp" path="sources/poky" revision="792d18b4cb2451b00280641403e6eaf37bd6e53f" upstream="scarthgap" />
<project name="meta-raspberrypi" remote="rpi" path="sources/meta-raspberrypi" revision="8e9ec2685a902038d1d6ad20f0821ee5655432a9" upstream="scarthgap" />
<project name="meta-openembedded" remote="oe" path="sources/meta-openembedded" revision="e8fd97d86af86cdcc5a6eb3f301cbaf6a2084943" upstream="walnascar" />

Linkfile

linkfile tag lives inside the manifest tags and is used to specify symbolic linking to the files provided by the project. The file location in the source git repository is set with src attribute and the target location in the local filetree is specified with dest attribute. Both paths are relative. A single project tag may be a home to multiple linkfile tags.

Fetch the repositories with repo#

Now, that the manifest file is ready and pushed to its git repository, use repo init to create the yocto environment on a local linux machine.

repo init -u https://github.com/anthonio9/rpi-manifest -b scarthgap -m rpi-6.12.25.xml
repo sync

reported output of a successful `repo sync`should be like below:

Syncing: 100% (3/3), done in 1m40.918s
repo sync has finished successfully.

Now, verify the content of the sources directory, make sure it contains all three meta layers.

[antoni@supercomputer sources]$ tree -L 1
.
├── meta-openembedded
├── meta-raspberrypi
└── poky

4 directories, 0 files

CONGRATULATIONS! Yocto sources are fetched!

yay! Yeah, this is it. The most basic repo manifest, but enough to get you started on this Yocto journey :)

Extra stuff#

This was good, but there’s still a lot to learn. In the next chapters of my blog, more steps on Yocto are to be covered, so stay tuned. But if you can’t wait already, then I suggest you learn:

  • How to shallow clone a git repository with repo, to speed up the download times and decrease the used disk space

  • How to configure Yocto build directory, or you could also read my other article that shortly talks about it

I hope this was useful! Thanks for reading, more will come soon.