You want to run a custom Linux on a Raspberry Pi or Jetson. You need a custom Linux distro for an IoT product you're building. But where do you start?
This guide walks you through Yocto Project from scratch — core concepts (Poky, BitBake, layers, recipes), setting up your development environment, building your first Linux image, and verifying it with QEMU.
Yocto has a steep learning curve at first, but once the underlying concepts click, it becomes remarkably flexible and powerful. By the end of this article, you'll have your first custom Linux image up and running.
What Is Yocto Project?
Yocto Project is an open-source project for creating custom Linux distributions tailored to embedded devices.
The key point: Yocto itself is not an OS. Think of it as a toolbox for building Linux systems.
The Problems Yocto Solves
Embedded Linux development comes with a unique set of challenges:
- Limited storage (a few MB to a few GB) — you need to strip out unnecessary packages
- Underpowered CPUs (ARM Cortex-A, etc.) — the system needs to be lightweight
- Specialized hardware (custom drivers) — the kernel needs customization
- Long product lifecycles (some products run for 10+ years) — reproducible builds are essential
Yocto is the de facto standard build system that addresses all of these at once.
Yocto vs. Buildroot vs. OpenWRT
| Yocto | Buildroot | OpenWRT | |
|---|---|---|---|
| Flexibility | Very high | Moderate | Router-focused |
| Learning curve | Steep | Gentle | Gentle |
| Commercial support | Extensive | Limited | Limited |
| Used by | Intel, NXP, TI, Sony | Smaller companies | Network devices |
| Package formats | RPM/DEB/IPK | None | OPKG |
If you're building commercial products or IoT devices, learning Yocto is worth the investment. Nearly every major semiconductor vendor ships their SDK built on Yocto.
Who Uses Yocto?
- Intel — IoT and industrial platforms
- NXP — Official BSP for the i.MX series
- Texas Instruments — Sitara processor family
- Sony — Digital cameras, audio equipment
- Automotive Grade Linux (AGL) — The standard for in-vehicle Linux
The Four Core Concepts of Yocto
To understand Yocto, you need to get comfortable with four fundamental ideas.
Poky (the Reference Distribution)
Poky is Yocto Project's reference implementation — think of it as the starter template.
When you begin with Yocto, you start by downloading Poky. It ships with everything you need: BitBake, the base layers, and sample images.
BitBake (the Build Engine)
BitBake is the engine that actually runs your builds. Instead of Makefiles, it reads "recipes," resolves dependencies, and executes the build tasks in the right order.
# Build a minimal Linux image
bitbake core-image-minimal
# Build just one package
bitbake busybox
# Inspect package metadata
bitbake -e busybox | grep ^PV=
Layers
Layers are directories that group related recipes and configuration. They're what makes Yocto so modular and maintainable.
- meta — OpenEmbedded core layer
- meta-poky — Poky-specific configuration
- meta-raspberrypi — Raspberry Pi BSP
- meta-mylayer — Your own customizations
By stacking layers, you can customize any aspect of the system without touching the base layers. See the layer creation guide for details.
Recipes
Recipes are .bb files that describe how to build a specific piece of software.
# hello-world_1.0.bb
SUMMARY = "Hello World sample application"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://hello.c"
S = "${WORKDIR}"
do_compile() {
${CC} ${CFLAGS} ${LDFLAGS} -o hello ${WORKDIR}/hello.c
}
do_install() {
install -d ${D}${bindir}
install -m 0755 hello ${D}${bindir}
}
Setting Up Your Development Environment
Recommended System Specs
| Minimum | Recommended | |
|---|---|---|
| CPU | 4 cores | 8+ cores |
| RAM | 8 GB | 32 GB+ |
| Disk | 100 GB (SSD preferred) | 300 GB+ |
| OS | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
Installing Required Packages
sudo apt update
sudo apt install -y gawk wget git diffstat unzip texinfo gcc build-essential \
chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils \
iputils-ping python3-git python3-jinja2 python3-subunit zstd liblz4-tool \
file locales libacl1
# Set up locale (en_US.UTF-8 is required)
sudo locale-gen en_US.UTF-8
Downloading Poky
# Create a working directory
mkdir -p ~/yocto && cd ~/yocto
# Clone Poky (scarthgap = LTS branch, supported until April 30, 2028)
git clone -b scarthgap git://git.yoctoproject.org/poky
# Verify the download
ls poky/
bitbake documentation meta meta-poky meta-yocto-bsp oe-init-build-env scripts
Running Your First Build
Initializing the Build Environment
cd ~/yocto/poky
source oe-init-build-env build
# After running this, you'll be automatically moved to the build/ directory
# You'll see a message like:
You had no conf/local.conf file. This configuration file has therefore been
created for you...
Important: always use source, not bash or ./. The script sets environment variables that need to persist in your current shell session.
Configuring local.conf
Edit conf/local.conf to tune the build parallelism.
# Add these lines, adjusting to your CPU core count
BB_NUMBER_THREADS = "8"
PARALLEL_MAKE = "-j 8"
# Target machine (default is qemux86-64 for QEMU testing)
MACHINE ?= "qemux86-64"
BB_NUMBER_THREADS controls how many BitBake tasks run in parallel. PARALLEL_MAKE controls the -j flag passed to make. Setting both to your CPU core count is a good starting point.
Running the Build
# Build the minimal Linux image
bitbake core-image-minimal
# First builds take 1-3 hours depending on your hardware
# If a build fails partway through, just run the same command again
On the first run, BitBake downloads all source code and compiles everything from scratch. Subsequent builds are much faster thanks to the shared state cache.
Build Time Reference
| Environment | First Build | Rebuild (no changes) |
|---|---|---|
| 8 cores / 32 GB RAM / SSD | ~1 hour | A few minutes |
| 4 cores / 16 GB RAM / SSD | ~2–3 hours | ~10 minutes |
| 4 cores / 8 GB RAM / HDD | ~4–6 hours | ~30 minutes |
Testing Your Build with QEMU
Using runqemu
Once the build finishes, you can launch your Linux image in an emulator — no physical hardware needed.
# Launch the image in QEMU
runqemu qemux86-64
# Launch without a graphical window (serial console only)
runqemu qemux86-64 nographic
# After boot, log in as root (no password)
qemux86-64 login: root
root@qemux86-64:~#
Verifying the System
# Check the kernel version
root@qemux86-64:~# uname -a
Linux qemux86-64 6.6.x-yocto-standard #1 SMP ...
# Check disk usage — notice how small the root filesystem is
root@qemux86-64:~# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 48M 32M 14M 70% /
# Shut down
root@qemux86-64:~# poweroff
Wrapping Up
Here's what we covered in this article:
- Yocto is a toolbox for building custom embedded Linux systems — not an OS itself
- The four core components are Poky, BitBake, layers, and recipes
- On Ubuntu,
bitbake core-image-minimalbuilds a working Linux image runqemulets you test your image without any hardware
Yocto has a steep learning curve, but once you have it down, you can build Linux for virtually any embedded device. Now that you have the basics, here's where to go next:
- Creating and managing layers — structure your builds with custom layers
- Writing recipes — package your own applications into images
- Building Linux for Raspberry Pi — deploy to real hardware
- If you hit build errors, check the debugging guide
To go deeper into embedded Linux, these books are excellent references.