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:
Kullanım senaryoları
| Senaryo | Örnek |
|---|---|
| Çoklu board, aynı yazılım | ARM + RISC-V + x86 için aynı uygulama stack |
| Ana + yardımcı işlemci | Cortex-A (Linux) + Cortex-M (FreeRTOS/bare-metal) |
| Çoklu distro | Üretim (minimal) + test (debug araçlarıyla) |
| SDK + image | SDK'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/
├── bblayers.conf
├── local.conf
└── multiconfig/
├── arm.conf ← ARM Cortex-A53 konfigürasyonu
└── riscv.conf ← RISC-V RV64 konfigürasyonu
# 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"
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"
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.
# 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ı
# 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/
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.
# 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
# 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özdizim | Anlamı |
|---|---|
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ı |
CFG | BBMULTICONFIG'de tanımlı konfigürasyon adı |
PKG | Bağımlı olunan recipe adı |
do_Y | Bağı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
# 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
# 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
| Durum | Boyut |
|---|---|
| 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.
# 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
# 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
# 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.
# 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
# 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.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ı
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
#!/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
#!/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
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