Yocto İleri Düzey
TEKNİK REHBER YOCTO İLERİ MULTICONFIG 2026

Multiconfig & SSTATE
Paralel Build

Tek bitbake çağrısıyla birden fazla MACHINE hedefi, sstate-cache ile akıllı yeniden kullanım ve hash equivalence sunucusuyla CI optimizasyonu.

00 Multiconfig nedir?

Multiconfig (çoklu konfigürasyon), tek bir bitbake çağrısında birden fazla farklı makine veya dağıtım için image üretmenizi sağlayan bir BitBake özelliğidir.

Neden multiconfig?

Büyük projelerde aynı yazılım yığını birden fazla hedef donanım için derlenebilir — örneğin ARM Cortex-A53 ve RISC-V RV64 tabanlı iki board. Multiconfig olmadan iki ayrı build dizini, iki ayrı çalışma ve paylaşımsız sstate-cache gerekir. Multiconfig ile:

Paralel buildBitBake her konfigürasyon için bağımsız task grafiği oluşturur ve tümünü paralel çalıştırır
Ortak sstate-cacheMimariden bağımsız task'lar (örn. native araçlar) tek seferde derlenir ve paylaşılır
Tek CI jobCI pipeline'ında tek bitbake çağrısı tüm hedefleri üretir
Çapraz bağımlılıkmc[machine1:package] sözdizimi ile konfigürasyonlar arası bağımlılık tanımlanabilir

Kullanım senaryoları

SenaryoÖrnek
Çoklu board, aynı yazılımARM + RISC-V + x86 için aynı uygulama stack
Ana + yardımcı işlemciCortex-A (Linux) + Cortex-M (FreeRTOS/bare-metal)
Çoklu distroÜretim (minimal) + test (debug araçlarıyla)
SDK + imageSDK'yı ve image'ı tek seferde üret

Bu bölümde

  • Multiconfig = tek bitbake çağrısında birden fazla MACHINE/DISTRO kombinasyonu
  • Paralel yürütme + ortak sstate-cache ile zaman tasarrufu
  • mc: sözdizimi ile konfigürasyonlar arası bağımlılık

01 Multiconfig kurulumu

Multiconfig için her hedef makineye ait bir .conf dosyası ve BBMULTICONFIG değişkeni gerekir.

Dizin yapısı

build/conf/ dizin yapısı
build/conf/
├── bblayers.conf
├── local.conf
└── multiconfig/
    ├── arm.conf      ← ARM Cortex-A53 konfigürasyonu
    └── riscv.conf    ← RISC-V RV64 konfigürasyonu
build/conf/local.conf — BBMULTICONFIG
# Varsayılan MACHINE (tek başına bitbake için)
MACHINE = "qemux86-64"

# Multiconfig listesi — conf/multiconfig/*.conf dosya adları
BBMULTICONFIG = "arm riscv"

# Ortak DL_DIR ve SSTATE_DIR tüm konfigürasyonlar tarafından paylaşılır
DL_DIR = "/data/yocto/downloads"
SSTATE_DIR = "/data/yocto/sstate-cache"
build/conf/multiconfig/arm.conf
MACHINE = "mymachine-arm"
DISTRO = "mydistro"

# Bu konfigürasyona özgü ayarlar
IMAGE_FSTYPES = "ext4 wic"
EXTRA_IMAGE_FEATURES = ""

# Multiconfig'e özgü TMPDIR (çıktıları ayrı tut)
TMPDIR = "${TOPDIR}/tmp-arm"
build/conf/multiconfig/riscv.conf
MACHINE = "qemuriscv64"
DISTRO = "mydistro"

# RISC-V için farklı tune
DEFAULTTUNE = "riscv64"
IMAGE_FSTYPES = "ext4"

# Ayrı TMPDIR
TMPDIR = "${TOPDIR}/tmp-riscv"

Bu bölümde

  • conf/multiconfig/*.conf — her hedef için ayrı konfigürasyon dosyası
  • BBMULTICONFIG = "arm riscv" — etkin konfigürasyon adları
  • Her multiconfig için ayrı TMPDIR önerilir

02 Multiconfig build çalıştırma

mc: sözdizimi ile belirli konfigürasyon ve image kombinasyonlarını hedefleyebilirsiniz.

bash — multiconfig build komutları
# Tek konfigürasyon — normal kullanım
bitbake mc:arm:core-image-minimal

# İki konfigürasyon paralel
bitbake mc:arm:core-image-minimal mc:riscv:core-image-minimal

# Tüm konfigürasyonlar için aynı image
bitbake mc:arm:myproduct-image mc:riscv:myproduct-image

# Konfigürasyona özgü recipe (sadece ARM için myapp)
bitbake mc:arm:myapp

# Karma — bir konfigürasyon için image, diğeri için package
bitbake mc:arm:myproduct-image mc:riscv:myapp

# Tüm tanımlı multiconfig'leri listele
bitbake -e | grep '^BBMULTICONFIG='

Build çıktıları

bash — çıktı dizinleri
# Her konfigürasyon kendi TMPDIR altında üretir
ls build/
# tmp-arm/
#   deploy/images/mymachine-arm/
#     myproduct-image-mymachine-arm.ext4
#     myproduct-image-mymachine-arm.wic
# tmp-riscv/
#   deploy/images/qemuriscv64/
NOT

Multiconfig build sırasında BitBake tüm konfigürasyonların task grafiklerini birleştirerek ortak bağımlılıkları tek seferde çalıştırır. bitbake-native ve sstate-cache paylaşıldığı için toplam süre iki ayrı build'den çok daha kısadır.

Bu bölümde

  • mc:<config>:<target> sözdizimi ile konfigürasyon hedeflenir
  • Birden fazla mc: hedefi aynı komutta belirtilerek paralel çalıştırılır
  • Çıktılar TMPDIR'a göre ayrı dizinlerde toplanır

03 Multiconfig bağımlılıkları

Bir konfigürasyonun çıktısı başka bir konfigürasyona bağımlı olabilir. mc[] sözdizimi bu çapraz bağımlılıkları tanımlar.

Çapraz konfigürasyon bağımlılığı
# Senaryo: ARM image'ın içine RISC-V firmware'i göm
# ARM image recipe'sinde:

# RISC-V konfigürasyonundan bir package'a build-time bağımlılık
do_image[mcdepends] = "mc::riscv:riscv-firmware:do_deploy"

# Genel syntax: do_TASK[mcdepends] = "mc::CONFIG:RECIPE:do_DEPTASK"
# mc:: (çift kolon) multiconfig bağımlılığı işareti
Pratik: ARM image'a RISC-V firmware ekle
# meta-myproduct/recipes-core/images/myproduct-image.bb içinde

# RISC-V firmware'in deploy edilmesini bekle
do_image_complete[mcdepends] = \
    "mc::riscv:riscv-firmware:do_deploy"

do_install:append() {
    # RISC-V firmware dosyasını ARM image'a dahil et
    # (RISC-V TMPDIR'dan kopyala)
    RISCV_DEPLOY=${TOPDIR}/tmp-riscv/deploy/images/qemuriscv64
    install -d ${D}/lib/firmware
    install -m 0644 ${RISCV_DEPLOY}/riscv-firmware.bin \
        ${D}/lib/firmware/
}

mc[] bağımlılık kuralları

SözdizimAnlamı
do_X[mcdepends] = "mc::CFG:PKG:do_Y"Bu task çalışmadan önce CFG'deki PKG'nin do_Y görevi tamamlanmalı
mc::Çift kolon — multiconfig bağımlılığı başlangıcı
CFGBBMULTICONFIG'de tanımlı konfigürasyon adı
PKGBağımlı olunan recipe adı
do_YBağımlı olunan görevin tamamlanması gereken task

Bu bölümde

  • do_task[mcdepends] ile konfigürasyonlar arası task bağımlılığı
  • Syntax: "mc::CONFIG:RECIPE:do_TASK"
  • Örnek: ARM image'a RISC-V firmware dahil etme

04 sstate-cache

sstate-cache (Shared State Cache), BitBake'in her task'ın çıktısını imzalayarak sakladığı ve sonraki build'lerde tekrar kullandığı akıllı önbellekleme mekanizmasıdır.

sstate-cache nasıl çalışır?

  Task çalışmadan önce:
  BitBake → task input hash'ini hesaplar
            (kaynak kodu + recipe değişkenleri + bağımlılıklar)
         → sstate-cache'te bu hash'e ait tarball var mı?

  Evet → sstate tarball'ı aç, task'ı ATLA
  Hayır → Task'ı çalıştır, çıktıyı sstate-cache'e kaydet
    
local.conf — sstate konfigürasyonu
# Ortak sstate-cache dizini — tüm build'ler paylaşır
SSTATE_DIR = "/data/yocto/sstate-cache"

# Mirror: önce cache server'a bak, sonra local'e düş
SSTATE_MIRRORS = "file://.* http://sstate.mycompany.com/sstate/PATH"

# Birden fazla mirror
SSTATE_MIRRORS += "file://.* file:///nfs/sstate/PATH"

# sstate-cache boyutunu sınırla (isteğe bağlı, MB cinsinden)
# SSTATE_CACHE_MANAGEMENT = "1"

sstate-cache yönetimi

bash — cache temizleme ve istatistik
# Eski sstate dosyalarını temizle (30 günden eski)
scripts/sstate-cache-management.sh \
    --cache-dir=/data/yocto/sstate-cache \
    --remove-duplicates \
    --yes

# Build'de sstate hit oranını gör
bitbake core-image-minimal 2>&1 | grep -E "(Sstate|NOTE.*running)"

# Belirli bir task için sstate durumunu kontrol et
bitbake -c checkstatus myapp

# sstate tarball yapısını incele
ls /data/yocto/sstate-cache/
# universal/      — mimari bağımsız task'lar
# cortexa53-poky-linux/  — ARM A53 task'ları
# riscv64-poky-linux/    — RISC-V task'ları

sstate boyutu ve büyüme

DurumBoyut
core-image-minimal (ilk build)~8–12 GB
core-image-full-cmdline~15–25 GB
Aylık birikimli (weekly clean öncesi)50–100+ GB
sstate-cache-management.sh sonrasıAktif versiyonlar kalır

Bu bölümde

  • Her task'ın çıktısı hash ile sstate-cache'te saklanır
  • SSTATE_DIR ile ortak cache dizini, SSTATE_MIRRORS ile server
  • sstate-cache-management.sh ile periyodik temizleme yapın

05 Hash equivalence

Hash equivalence sunucusu, farklı ortamlarda üretilen aynı çıktıların hash'lerini eşitlererek sstate yeniden kullanım oranını dramatik biçimde artırır.

Hash equivalence nedir?

Normalde BitBake, bir task'ın girdisi değişmese bile build ortamı farklıysa (farklı host, farklı path) farklı bir hash üretir. Hash equivalence sunucusu, "bu iki farklı hash aslında aynı çıktıyı üretiyor" bilgisini depolar. Böylece Developer A'nın build'i ile CI sunucusunun build'i sstate'i paylaşabilir.

local.conf — hash equivalence sunucusu
# Hash equivalence özelliğini etkinleştir
BB_HASHDEDUP = "1"

# Ortak hash equivalence sunucusu
# Boş bırakılırsa BitBake local bir sunucu başlatır
SSTATE_HASHEQUIV_SERVER = "grpc://hashequiv.mycompany.com:8686"

# Sadece okuma (CI build'leri için)
SSTATE_HASHEQUIV_REPORT_TASKDATA = "1"

# Reproducible build için kaynak tarih bilgisini sabitle
SOURCE_DATE_EPOCH = "1700000000"

Hashequiv sunucusu kurulumu

bash — hashequiv sunucu kurma
# Poky içindeki hashequiv server script'i
python3 /home/user/poky/bin/bitbake-hashserv \
    --bind 0.0.0.0:8686 \
    --database /data/yocto/hashequiv.sqlite3 \
    --log-level INFO &

# Sunucu durumunu kontrol et
curl http://localhost:8686/

# systemd servisi olarak çalıştırma
cat /etc/systemd/system/bitbake-hashserv.service
# [Unit]
# Description=BitBake Hash Equivalence Server
# [Service]
# ExecStart=/usr/bin/python3 /opt/poky/bin/bitbake-hashserv \
#   --bind 0.0.0.0:8686 --database /data/yocto/hashequiv.sqlite3
# Restart=always

Reproducible builds

local.conf — reproducible build ayarları
# Reproducible build — zaman damgası ve path bağımsızlığı
INHERIT += "reproducible_build"

# Tüm dosyalar için sabit tarih
SOURCE_DATE_EPOCH = "1700000000"

# Build host path'ini gizle
BB_GENERATE_MIRROR_TARBALLS = "1"

# PR servisi (optional — sstate'de hash çakışmalarını önler)
PRSERV_HOST = "localhost:8585"

Bu bölümde

  • Hash equivalence, farklı ortamlardaki aynı çıktıları eşitler
  • SSTATE_HASHEQUIV_SERVER ile merkezi sunucu — geliştirici ve CI paylaşımı
  • bitbake-hashserv ile sunucu kurulumu, SQLite veya PostgreSQL backend
  • SOURCE_DATE_EPOCH ile reproducible build

06 Shared downloads

DL_DIR, tüm build'lerin ortak kaynak indirme deposudur. Mirror server kurulumu ve BB_GENERATE_MIRROR_TARBALLS ile offline build mümkün hale gelir.

local.conf — DL_DIR konfigürasyonu
# Ortak download dizini — disk boyutu büyük olmalı (50+ GB)
DL_DIR = "/data/yocto/downloads"

# Mirror tarball'larını üret (git repo'lar için)
# Offline build için gerekli — git snapshot tarball oluşturur
BB_GENERATE_MIRROR_TARBALLS = "1"

# Sadece önceden indirilmiş dosyaları kullan (network yasak)
BB_NO_NETWORK = "1"

# Belirli mirror'lar için ağa izin ver
BB_ALLOWED_NETWORKS = "*.mycompany.com *.github.com"

# Mirror server: önce yerel HTTP sunucusuna bak
PREMIRRORS:prepend = "ftp://.*/.* http://mirror.mycompany.com/yocto/downloads/ \n \
                       git://.*/.* http://mirror.mycompany.com/yocto/downloads/ \n"

Mirror server kurulumu

bash — basit HTTP mirror
# DL_DIR'ı HTTP ile yayınla (nginx ile)
cat /etc/nginx/sites-available/yocto-mirror
# server {
#   listen 80;
#   server_name mirror.mycompany.com;
#   root /data/yocto/downloads;
#   autoindex on;
#   location / { try_files $uri $uri/ =404; }
# }

# Mirror tarball'larını üretmek için bir kez online build yap
BB_GENERATE_MIRROR_TARBALLS = "1"
bitbake core-image-minimal

# Bundan sonra BB_NO_NETWORK=1 ile offline build yapılabilir
# DL_DIR içindeki *.tar.gz dosyaları kaynak olarak kullanılır

CI/CD entegrasyonu

GitLab CI — shared cache ile
# .gitlab-ci.yml
build-image:
  stage: build
  script:
    - source /opt/poky/oe-init-build-env build/
    - echo 'DL_DIR = "/nfs/yocto/downloads"' >> conf/local.conf
    - echo 'SSTATE_DIR = "/nfs/yocto/sstate-cache"' >> conf/local.conf
    - echo 'BB_NO_NETWORK = "1"' >> conf/local.conf
    - bitbake mc:arm:myproduct-image mc:riscv:myproduct-image
  artifacts:
    paths:
      - build/tmp-arm/deploy/images/
      - build/tmp-riscv/deploy/images/

Bu bölümde

  • DL_DIR ortak download deposu — tüm build'ler ve geliştiriciler paylaşır
  • BB_GENERATE_MIRROR_TARBALLS — git snapshot'larını tarball olarak saklar
  • BB_NO_NETWORK = "1" — tam offline build
  • PREMIRRORS ile HTTP mirror server önceliklendirilir

07 Pratik: ARM + RISC-V dual target build

Tek conf repository'den ARM Cortex-A53 ve RISC-V RV64 için paralel image build — ortak sstate-cache ve CI entegrasyonu.

Proje yapısı

Repository yapısı
myproject-build/                ← Build konfigürasyon repo'su
├── conf/
│   ├── local.conf.template
│   ├── bblayers.conf.template
│   └── multiconfig/
│       ├── arm.conf
│       └── riscv.conf
├── scripts/
│   ├── setup-env.sh
│   └── build-all.sh
└── .gitlab-ci.yml

Setup script

scripts/setup-env.sh
#!/bin/bash
set -euo pipefail

POKY_DIR=${POKY_DIR:-/opt/poky}
BUILD_DIR=${BUILD_DIR:-$(pwd)/build}
DL_DIR=${DL_DIR:-/data/yocto/downloads}
SSTATE_DIR=${SSTATE_DIR:-/data/yocto/sstate-cache}

# Poky ortamını başlat
source ${POKY_DIR}/oe-init-build-env ${BUILD_DIR}

# conf dizinine template'leri kopyala
cp -n ../conf/local.conf.template conf/local.conf
cp -n ../conf/bblayers.conf.template conf/bblayers.conf
cp -rn ../conf/multiconfig conf/

# Yerel değerleri ata
sed -i "s|DL_DIR_PLACEHOLDER|${DL_DIR}|" conf/local.conf
sed -i "s|SSTATE_DIR_PLACEHOLDER|${SSTATE_DIR}|" conf/local.conf

echo "Build ortamı hazır: ${BUILD_DIR}"

Build script

scripts/build-all.sh
#!/bin/bash
set -euo pipefail

source scripts/setup-env.sh
cd build/

# Paralel ARM + RISC-V build
bitbake mc:arm:myproduct-image mc:riscv:myproduct-image

# Çıktıları kontrol et
echo "=== ARM Image ==="
ls -lh tmp-arm/deploy/images/mymachine-arm/*.wic

echo "=== RISC-V Image ==="
ls -lh tmp-riscv/deploy/images/qemuriscv64/*.ext4

CI pipeline

.gitlab-ci.yml — dual target CI
variables:
  DL_DIR: "/nfs/yocto/downloads"
  SSTATE_DIR: "/nfs/yocto/sstate-cache"

stages:
  - build
  - test

build-all:
  stage: build
  tags:
    - yocto-runner   # NFS erişimi olan runner
  script:
    - bash scripts/build-all.sh
  artifacts:
    paths:
      - build/tmp-arm/deploy/images/mymachine-arm/
      - build/tmp-riscv/deploy/images/qemuriscv64/
    expire_in: 1 week

test-qemu-riscv:
  stage: test
  needs: [build-all]
  script:
    - runqemu qemuriscv64 nographic \
        build/tmp-riscv/deploy/images/qemuriscv64/myproduct-image-qemuriscv64.ext4 \
        bootparams="systemd.unit=rescue.target"
  allow_failure: false

Bu bölümde

  • Tek conf repo ile ARM + RISC-V paralel build — BBMULTICONFIG ile
  • Ortak DL_DIR + SSTATE_DIR — geliştiriciler ve CI aynı cache'i kullanır
  • setup-env.sh + build-all.sh ile tekrarlanabilir build ortamı
  • GitLab CI'da NFS üzerinden shared cache — sıfırdan build olmaz