What exactly is a Yocto layer? There are so many meta-xxx directories — what do they all do?
Layers are the most important concept in Yocto — get them right and everything else falls into place. This article explains how layers work and walks you through creating your own, adding external BSP layers, and configuring bblayers.conf.
What Is a Yocto Layer?
A layer is a directory that groups related recipes, configuration files, and patches into a logical module.
Yocto's build system works by stacking multiple layers on top of each other. Each layer can override or extend what's below it. This is what allows you to customize your system without ever touching the upstream source.
A higher-priority layer can override a recipe in a lower-priority layer. If the same recipe exists in multiple layers, the one with the highest priority wins.
Why Are Layers Necessary?
- Reusability — the same layer can be shared across multiple projects
- Maintainability — your changes stay separate from upstream. When you upgrade Poky, your customizations don't get wiped out
- Team collaboration — BSP work, application work, and distro configuration can be owned by different people
- Version control — each layer can live in its own Git repository
Layer Types and Structure
Types of Layers
| Type | Purpose | Examples |
|---|---|---|
| BSP layer | Hardware-specific config for a target board | meta-raspberrypi, meta-ti, meta-intel |
| Distribution layer | Distro-level policies and settings | meta-poky, meta-angstrom |
| Software layer | Collections of additional packages | meta-openembedded, meta-qt5 |
| Custom layer | Your project-specific recipes | meta-mylayer, meta-mycompany |
In your own projects, always create a custom layer and put your recipes and patches there.
Directory Structure
All layers follow the same basic structure:
meta-mylayer/
├── conf/
│ └── layer.conf # Layer configuration (required)
├── COPYING.MIT # License file
├── README # Layer description
├── recipes-bsp/ # BSP recipes
├── recipes-core/ # Core system recipes
├── recipes-example/ # Example recipes
│ └── myapp/
│ ├── myapp_1.0.bb
│ └── files/
├── recipes-kernel/ # Kernel-related recipes
├── recipes-graphics/ # Graphics recipes
└── classes/ # Shared class files (.bbclass)
The recipes-* directory naming is a convention. BitBake automatically discovers recipes inside directories matching this pattern.
Inside layer.conf
conf/layer.conf is the layer's identity card. Without it, Yocto won't recognize the directory as a layer.
# conf/layer.conf
# Add this layer's path to BBPATH
BBPATH .= ":${LAYERDIR}"
# Tell BitBake where to find recipes in this layer
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
# Give this layer a unique collection name
BBFILE_COLLECTIONS += "meta-mylayer"
BBFILE_PATTERN_meta-mylayer = "^${LAYERDIR}/"
# Layer priority (6–10 is typical for custom layers)
BBFILE_PRIORITY_meta-mylayer = "6"
# Which Yocto releases this layer is compatible with
LAYERSERIES_COMPAT_meta-mylayer = "scarthgap"
# Other layers this layer depends on
LAYERDEPENDS_meta-mylayer = "core"
Creating a Custom Layer
Using bitbake-layers (Recommended)
The easiest and most reliable approach is to use the bitbake-layers command.
# Enter the build environment
cd ~/yocto/poky
source oe-init-build-env build
# Navigate to the parent directory and create the layer
cd ..
bitbake-layers create-layer meta-myproject
# Inspect the generated files
ls meta-myproject/
conf COPYING.MIT README recipes-example
cat meta-myproject/conf/layer.conf
Manual Creation
Creating the layer manually is a great way to understand what each piece does.
# Create the directory structure
mkdir -p meta-myproject/conf
mkdir -p meta-myproject/recipes-example/myapp
# Write layer.conf
cat > meta-myproject/conf/layer.conf << 'EOF'
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "meta-myproject"
BBFILE_PATTERN_meta-myproject = "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-myproject = "6"
LAYERSERIES_COMPAT_meta-myproject = "scarthgap"
EOF
Adding a Layer to Your Build
Editing bblayers.conf
# Using the command (recommended)
cd ~/yocto/poky
source oe-init-build-env build
bitbake-layers add-layer ../meta-myproject
# Or edit the file directly
nano conf/bblayers.conf
Example conf/bblayers.conf:
BBLAYERS ?= " \
/home/user/yocto/poky/meta \
/home/user/yocto/poky/meta-poky \
/home/user/yocto/poky/meta-yocto-bsp \
/home/user/yocto/meta-myproject \
"
Absolute paths are the standard practice. bitbake-layers add-layer also inserts absolute paths.
Verifying and Removing Layers
# List all active layers
bitbake-layers show-layers
layer path priority
==========================================================================
meta /home/user/yocto/poky/meta 5
meta-poky /home/user/yocto/poky/meta-poky 5
meta-yocto-bsp /home/user/yocto/poky/meta-yocto-bsp 5
meta-myproject /home/user/yocto/meta-myproject 6
# Remove a layer from the build (files are not deleted)
bitbake-layers remove-layer meta-myproject
Customizing Existing Recipes
When you need to modify an existing recipe, never edit the original file. Use a .bbappend file in your own layer instead. This is Yocto's non-destructive customization pattern. See the bbappend practical guide for details.
Adding an External BSP Layer
Here's a practical example: adding Raspberry Pi support with meta-raspberrypi.
Download the Layers
# Clone into the same parent directory as Poky
cd ~/yocto
git clone -b scarthgap git://git.yoctoproject.org/meta-raspberrypi
# meta-openembedded is a dependency of meta-raspberrypi
git clone -b scarthgap git://git.openembedded.org/meta-openembedded
Add the Layers and Configure
cd ~/yocto/poky
source oe-init-build-env build
# Add meta-oe (required by meta-raspberrypi)
bitbake-layers add-layer ../meta-openembedded/meta-oe
# Add meta-raspberrypi
bitbake-layers add-layer ../meta-raspberrypi
# Verify
bitbake-layers show-layers
Set the target machine in conf/local.conf:
MACHINE = "raspberrypi4-64"
For the full Raspberry Pi build workflow, see the RPi build guide.
OpenEmbedded Layer Index
The community maintains a searchable index of publicly available layers:
https://layers.openembedded.org
Search for things like "raspberrypi", "qt5", or "nodejs" and you'll find layers that provide support. Before writing a recipe from scratch, always check here first.
Commonly Used Layers
| Layer | Purpose |
|---|---|
meta-raspberrypi | Raspberry Pi BSP |
meta-ti | Texas Instruments BSP |
meta-intel | Intel BSP |
meta-openembedded | Extra packages (Python, networking, etc.) |
meta-qt5 / meta-qt6 | Qt5/Qt6 GUI framework |
meta-virtualization | Docker, LXC, etc. |
Common Errors and Fixes
Layer 'xxx' is not compatible
ERROR: Layer xxx is not compatible with the current version
Cause: The LAYERSERIES_COMPAT in layer.conf doesn't match the active Yocto branch.
Fix: Update LAYERSERIES_COMPAT in your layer's layer.conf:
LAYERSERIES_COMPAT_meta-mylayer = "scarthgap"
Layer depends on 'xxx'
ERROR: Layer xxx depends on layer xxx
Cause: A required dependency layer hasn't been added yet.
Fix: Add the dependency layer first with bitbake-layers add-layer.
Wrapping Up
- Always put your recipes in a custom layer — never edit Poky directly
- Use .bbappend to modify existing recipes — keep upstream files untouched
- Name your layers with the
meta-prefix — it's the established convention - Set LAYERSERIES_COMPAT correctly — prevents mysterious compatibility errors
- Keep each layer in its own Git repository — essential for team development
Ready for the next step? Here's where to go from here:
- Writing recipes — package your applications into images
- bbappend practical guide — patterns for customizing existing recipes
- Building Linux for Raspberry Pi — deploy to real hardware
To go deeper into embedded Linux, these books are excellent references.