Tüm eğitimler
TEKNİK REHBER GÖMÜLÜ LİNUX BUILDROOT 2026

Buildroot
Minimal Embedded Linux

tek make komutuyla toolchain + kernel + rootfs + image — hızlı prototip, sıkı boyut kısıtı.

00 Buildroot nedir ve neden

Buildroot, tek bir make çağrısıyla cross-toolchain, Linux kernel, rootfs ve boot image'ı üretebilen Makefile tabanlı bir embedded Linux build sistemidir.

Buildroot ne yapar

Buildroot, GNU Make üzerine inşa edilmiş bir cross-compile orkestrasyon sistemidir. Toolchain seçimi, Linux kernel konfigürasyonu, rootfs içeriği ve bootloader entegrasyonunu tek bir menuconfig arayüzünden yönetir. Komple bir embedded Linux sistemi üretmek için yazılması gereken binlerce satır Makefile yerine, birkaç konfigürasyon seçeneği yeterlidir.

make menuconfig → .config → make -j$(nproc) → output/images/ (kernel + DTB + rootfs + image)

Yocto ile karşılaştırma

ÖzellikBuildrootYocto Project
Öğrenme eğrisiDüz — Makefile, menuconfig bilmek yeterliDik — BitBake DSL, layer sistemi, recipe kavramı
İlk build süresi20–40 dakika1–2 saat (sstate-cache yoksa)
Incremental buildSınırlı — toolchain değişirse full rebuildGüçlü sstate-cache — yalnızca değişen task
Paket sayısı~2 000 paket5 000+ recipe
Çoklu board desteğidefconfig bazlı, basitBSP layer + MACHINE değişkeni — güçlü
SDK üretimimake sdk — temel düzeydeYerleşik, güçlü, eSDK dahil
Yapılandırma dosyası.config — düz metinlocal.conf + bblayers.conf
Ticari destekSınırlı, topluluk odaklıWind River, Mentor/Siemens, Timesys

Ne zaman Buildroot tercih edilir

Küçük projeTek board, küçük ekip — Yocto'nun ek karmaşıklığına gerek yok
Sıkı boyut kısıtımusl + BusyBox kombinasyonuyla 4–8 MB rootfs üretilebilir
Hızlı prototipKavram kanıtı için birkaç saatte çalışan QEMU veya gerçek donanım sistemi
Az kaynak8 GB RAM ve eski bir laptop yeterli; Yocto için 16+ GB ve SSD önerilir
Basit paket listesi100'den az paket — Yocto'nun incremental build avantajı önemsiz kalır

Desteklenen mimariler

MimariÖrnek hedeflerC library desteği
ARM (32-bit)Cortex-A8/A9/A53, Cortex-M (MMU'suz)glibc, musl, uClibc-ng
ARM64 (AArch64)Cortex-A55/A72/A76, Raspberry Pi 4/5glibc, musl
MIPSMIPS32, MIPS64, OpenWrt router SoC'larıglibc, musl, uClibc-ng
RISC-Vrv32, rv64 — SiFive, StarFive, T-Headglibc, musl
x86 / x86-64Intel Atom, AMD Embedded, QEMUglibc, musl
PowerPCe500, e5500 — NXP QorIQ SoC'larıglibc, musl, uClibc-ng

Buildroot dizin yapısı

Dizinİçerik
board/Board-specific dosyalar: post-build script, overlay, kernel config, patches
configs/Hazır defconfig'ler — make list-defconfigs ile listelenir
dl/İndirilen kaynak tarball'ları — build'ler arası paylaşılabilir
output/Build çıktıları: images/, host/, target/, build/, staging/
package/~2000 paket tarifi — her paketin Config.in ve .mk dosyası burada
toolchain/Internal toolchain build kuralları ve external toolchain wrapper'ları

Bu bölümde

  • Buildroot = GNU Make + menuconfig — tek komutla toolchain + kernel + rootfs + image
  • İlk build 20–40 dakika; Yocto 1–2 saat — hızlı prototip için ideal
  • ARM, ARM64, MIPS, RISC-V, x86, PowerPC mimarileri; glibc/musl/uClibc-ng seçeneği
  • ~2000 paket, 220+ hazır defconfig, sade öğrenme eğrisi

01 İlk build: QEMU ARM

Buildroot'un klonlanmasından QEMU'da ilk boot'a kadar tüm adımlar — donanım gerekmeden çalışan bir ARM sistemi.

Ön gereksinimler

bash — Ubuntu 22.04 / Debian 12
sudo apt-get install -y \
  build-essential gcc g++ make unzip \
  python3 file wget cpio rsync \
  bc libncurses-dev libssl-dev \
  qemu-system-arm

# Versiyon kontrolü
gcc --version     # gcc 11+ önerilir
make --version    # GNU Make 4.0+
python3 --version # Python 3.6+

Buildroot indirme

bash
# Git ile belirli bir LTS sürümünü klonla
git clone https://git.buildroot.net/buildroot -b 2024.02.x buildroot
cd buildroot

# Alternatifl: tarball indirme
wget https://buildroot.org/downloads/buildroot-2024.02.tar.gz
tar xf buildroot-2024.02.tar.gz

# Hazır ARM QEMU konfigürasyonunu yükle
make qemu_arm_versatile_defconfig

# .config içeriğini doğrula
grep -E '^BR2_(ARCH|TOOLCHAIN_BUILDROOT_LIBC)=' .config
# BR2_ARCH="arm"
# BR2_TOOLCHAIN_BUILDROOT_LIBC="uclibc"

make menuconfig — temel gezinme

bash
make menuconfig

# Navigasyon kısayolları:
# ↑↓         : seçenek gezinme
# ← →        : alt menü Enter / Esc
# Space      : toggle seçenek (y/n/m)
# /          : arama (BR2_ değişken adı veya başlık)
# ?          : seçenek hakkında yardım
# Esc Esc    : bir üst menüye çıkış
# S (Save)   : konfigürasyonu kaydet

Build ve çıktı analizi

bash — build
# Tüm CPU çekirdeklerini kullan
make -j$(nproc) 2>&1 | tee build.log

# Build aşamaları (log'da görüntülenir):
# [1/5] Toolchain build (gcc 13 → arm-buildroot-linux-uclibcgnueabi-gcc)
# [2/5] Kernel headers
# [3/5] Target packages (busybox, dropbear, ...)
# [4/5] Linux kernel
# [5/5] Rootfs image

# Çıktıları incele
ls -lh output/images/
# rootfs.ext2   — ext2 formatında rootfs (~16 MB)
# zImage        — ARM Linux kernel
# versatile-pb.dtb — ARM Versatile Platform Baseboard DTB
# start-qemu.sh — hazır QEMU başlatma scripti

QEMU ile boot

bash — QEMU ARM başlatma
# Hazır script varsa kullan
./output/images/start-qemu.sh

# Manuel başlatma (eşdeğer komut)
qemu-system-arm \
  -M versatilepb \
  -kernel output/images/zImage \
  -dtb output/images/versatile-pb.dtb \
  -drive "file=output/images/rootfs.ext2,if=scsi,format=raw" \
  -append "rootwait root=/dev/sda console=ttyAMA0,115200" \
  -serial stdio \
  -net nic,model=smc91c111 -net user \
  -nographic

# Login: root (şifre yok — varsayılan)
# QEMU'dan çık: Ctrl+A, ardından X
NOT

İlk build sırasında Buildroot, toolchain dahil her şeyi sıfırdan derler — bu 20–40 dakika sürebilir. Sonraki build'lerde BR2_CCACHE=y etkinleştirilmişse aynı build yalnızca 2–5 dakika alır. Toolchain veya libc değiştirilmedikçe make clean gerekmez.

Bu bölümde

  • make qemu_arm_versatile_defconfig: 220+ hazır konfigürasyondan biri — ARM başlangıç noktası
  • make -j$(nproc): ilk build ~30 dakika; çıktılar output/images/ altında
  • output/images/: zImage + versatile-pb.dtb + rootfs.ext2 + start-qemu.sh
  • qemu-system-arm -M versatilepb: gerçek donanım olmadan tam ARM Linux boot

02 menuconfig anatomy

menuconfig'in 8 ana kategorisi — Target options, Toolchain, Build options, System configuration, Kernel, Packages, Filesystem images, Bootloaders.

Target options

menuconfig — Target options
# Target Architecture seçenekleri
# BR2_arm=y            → ARM 32-bit
# BR2_aarch64=y        → ARM 64-bit (AArch64)
# BR2_riscv=y          → RISC-V
# BR2_x86_64=y         → x86-64

# ARM ABI seçimi (arm için)
# BR2_ARM_EABI=y       → soft-float ABI
# BR2_ARM_EABIHF=y     → hard-float ABI (Cortex-A için önerilir)

# CPU variant (performans optimizasyonu)
# BR2_cortex_a9=y      → Cortex-A9 (-mcpu=cortex-a9)
# BR2_cortex_a53=y     → Cortex-A53
# BR2_cortex_a72=y     → Cortex-A72 (Raspberry Pi 4)

Toolchain kategorisi

SeçenekAçıklamaNe zaman
Buildroot toolchaingcc/binutils kaynak derlemesiTam kontrol, custom libc gerektiğinde
External toolchainLinaro, ARM GNU, vendor binary toolchaingcc derleme istemiyorsan, hızlı build için
glibcGNU C Library — tam POSIX uyumuÜretim sistemleri, geniş uygulama uyumluluğu
muslHafif C library (~600 KB)Embedded, güvenlik odaklı, küçük rootfs
uClibc-ngMMU'suz sistemler içinCortex-M (MPU), bazı MIPS SoC'ları

Build options

.config — Build options
# Derleyici optimizasyonu
# BR2_OPTIMIZE_2=y         → -O2 (varsayılan)
# BR2_OPTIMIZE_S=y         → -Os (boyut öncelikli)
# BR2_OPTIMIZE_3=y         → -O3 (performans öncelikli)

# Binary'leri strip et (debug sembollerini kaldır)
# BR2_STRIP_strip=y        → rootfs boyutunu ~%30 düşürür

# Hata ayıklama sembolleri (strip ile çakışır)
# BR2_ENABLE_DEBUG=y       → -g flag eklenir; strip devre dışı kalır

# ccache — compiler cache (tekrar build'leri hızlandırır)
# BR2_CCACHE=y
# BR2_CCACHE_DIR="/home/user/.buildroot-ccache"

System configuration

.config — System configuration
# Sistem hostname
BR2_TARGET_GENERIC_HOSTNAME="embedded"

# /etc/issue banner
BR2_TARGET_GENERIC_ISSUE="Welcome to Embedded Linux"

# Timezone
BR2_TARGET_TZ_INFO=y
BR2_TARGET_LOCALTIME="Europe/Istanbul"

# Init sistemi seçimi
# BR2_INIT_BUSYBOX=y    → BusyBox init (sysvinit benzeri, hafif)
# BR2_INIT_SYSTEMD=y    → systemd (daha büyük, geniş özellik)
# BR2_INIT_SYSV=y       → sysvinit (klasik /etc/init.d)

# Root şifre (SHA256 hash)
BR2_TARGET_GENERIC_PASSWD_METHOD_SHA256=y
BR2_TARGET_GENERIC_ROOT_PASSWD="mypassword"

# Getty (seri konsol login)
BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
BR2_TARGET_GENERIC_GETTY_BAUDRATE_115200=y

Kernel ve Filesystem images

.config — Kernel ve image seçenekleri
# Kernel versiyonu
# BR2_LINUX_KERNEL_LATEST_VERSION=y   → en yeni stable
# BR2_LINUX_KERNEL_CUSTOM_VERSION=y   → belirli sürüm
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.21"

# Kernel defconfig
BR2_LINUX_KERNEL_DEFCONFIG="versatile"
# ya da board dizinindeki özel config
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/myboard/linux.config"

# Rootfs formatları (birden fazla seçilebilir)
# BR2_TARGET_ROOTFS_EXT2=y     → ext2 (SD kart, eMMC)
# BR2_TARGET_ROOTFS_SQUASHFS=y → squashfs read-only (NOR flash)
# BR2_TARGET_ROOTFS_CPIO=y     → initramfs (RAM boot)
# BR2_TARGET_ROOTFS_TAR=y      → tarball (NFS root, Docker)
UYARI

Toolchain veya C library değiştirildiğinde tüm build geçersiz olur. make clean komutuyla output/ dizinini temizleyin ve yeniden build edin. Yalnızca paket veya kernel konfigürasyonu değiştiyse make clean gerekmez — Buildroot etkilenen paketleri otomatik yeniden derler.

Bu bölümde

  • Target options: mimari + ABI + CPU variant — cross-compiler flag'lerini belirler
  • Toolchain: internal (gcc kaynak) vs external (Linaro binary) + libc seçimi
  • System configuration: hostname, init sistemi, timezone, root şifre
  • Filesystem images: ext2/ext4, squashfs, cpio, tar — birden fazla aynı anda seçilebilir

03 Package ekleme

Buildroot'un ~2000 paketini menuconfig'den seçmek veya .config'te BR2_PACKAGE_XXX=y ile etkinleştirmek yeterlidir.

Package seçim yöntemleri

bash — paket ekleme
# Yöntem 1: menuconfig ile interaktif seçim
make menuconfig
# → Target packages → Networking applications → [*] openssh
# → Target packages → Networking applications → [*] dropbear
# → Target packages → Interpreter languages  → [*] python3
# → Target packages → System tools           → [*] htop

# Yöntem 2: .config'i doğrudan düzenle
echo 'BR2_PACKAGE_OPENSSH=y'  >> .config
echo 'BR2_PACKAGE_DROPBEAR=y' >> .config
make olddefconfig  # bağımlılıkları çöz

# Yöntem 3: paket arama
make menuconfig
# '/' tuşuna basın → 'libcurl' yazın → sonucu bulun

Örnek: libcurl, openssh, python3 + modüller

.config — paket seçimi
# libcurl — HTTP/HTTPS client library
BR2_PACKAGE_LIBCURL=y
BR2_PACKAGE_LIBCURL_OPENSSL=y    # HTTPS için SSL backend

# OpenSSH — tam SSH server + client
BR2_PACKAGE_OPENSSH=y
BR2_PACKAGE_OPENSSH_SERVER=y
BR2_PACKAGE_OPENSSH_CLIENT=y

# Python3 + minimal pip modülleri
BR2_PACKAGE_PYTHON3=y
BR2_PACKAGE_PYTHON_PIP=y
BR2_PACKAGE_PYTHON_REQUESTS=y
BR2_PACKAGE_PYTHON_PAHO_MQTT=y

# Mosquitto MQTT broker
BR2_PACKAGE_MOSQUITTO=y
BR2_PACKAGE_MOSQUITTO_BROKER=y

Tek paket rebuild komutları

make <pkg>Paketi ve bağımlılıklarını ilk kez build et
make <pkg>-rebuildPaketin tüm build adımlarını yeniden çalıştır (kaynak değiştiyse)
make <pkg>-dircleanPaketin build dizinini sil (dl/ tarball korunur) — clean rebuild için
make <pkg>-distcleanBuild dizini + indirilen tarball'ı da sil — tam temizlik
make <pkg>-sourceYalnızca kaynak tarball'ını indir (offline build hazırlığı)
make <pkg>-graph-dependsPaketin bağımlılık ağacını DOT grafiği olarak üret
bash — tek paket workflow
# Örnek: mosquitto paketini yeniden build et
make mosquitto-dirclean
make mosquitto

# Host tool'u rebuild et (cross-compile araçları)
make host-dtc-rebuild   # device tree compiler

# Paket bağımlılıklarını görselleştir
make mosquitto-graph-depends
dot -Tsvg output/graphs/graph-depends.dot -o mosquitto-deps.svg

Host package: BR2_PACKAGE_HOST_XXX

.config — host paketler
# Host package: build host üzerinde çalışır (cross-compile araçları)
# Target package: rootfs'e dahil edilir

# Örnek: genimage — SD kart image üretimi (host'ta çalışır)
BR2_PACKAGE_HOST_GENIMAGE=y

# device tree compiler — host'ta dtc binary
BR2_PACKAGE_HOST_DTC=y

# mtools — FAT image manipülasyonu (host)
BR2_PACKAGE_HOST_MTOOLS=y

# Host binary konumu
ls output/host/bin/
# arm-buildroot-linux-gnueabihf-gcc
# dtc
# genimage
# mtools
NOT

Package bağımlılıkları Config.in içinde select ve depends on direktifleriyle tanımlanır. select ile işaretlenen bağımlılıklar otomatik seçilir; depends on ise ilgili seçenek etkinleştirilmeden paketin seçilmesini engeller. menuconfig'de gri görünen paketler genellikle karşılanmamış bir depends on koşuluna sahiptir — ? tuşuyla detay görüntüleyin.

Bu bölümde

  • BR2_PACKAGE_XXX=y satırı .config'e eklenmesi veya menuconfig seçimi yeterli
  • libcurl + openssl, openssh, python3 + paho-mqtt, mosquitto broker ekleme örnekleri
  • make <pkg>-dirclean && make <pkg>: tek paket temiz rebuild
  • Host package: build host'ta çalışan araçlar — genimage, dtc, mtools

04 Custom package yazmak

Kendi uygulamanızı Buildroot'a entegre etmek iki dosya gerektirir: Config.in (menuconfig girişi) ve .mk (build kuralları).

Package dizin yapısı

bash — dizin oluşturma
mkdir -p package/my-app

# Gerekli dosyalar:
# package/my-app/Config.in   → menuconfig girişi
# package/my-app/my-app.mk   → build kuralları

# Ana Config.in'e kaynak ekle (bir kerelik)
grep -n 'endmenu' package/Config.in | tail -1
# Uygun endmenu'dan önce source satırı ekle:
# source "package/my-app/Config.in"

Config.in — Kconfig snippet

package/my-app/Config.in
config BR2_PACKAGE_MY_APP
	bool "my-app"
	depends on BR2_USE_MMU        # MMU gerektiriyor
	depends on BR2_TOOLCHAIN_HAS_THREADS
	select BR2_PACKAGE_LIBCURL     # otomatik seç
	select BR2_PACKAGE_OPENSSL
	help
	  Minimal IoT daemon — HTTP REST API + MQTT publish.

	  https://github.com/myorg/my-app

my-app.mk — generic-package

package/my-app/my-app.mk
################################################################################
# my-app — IoT daemon (generic package)
################################################################################

MY_APP_VERSION       = 1.3.0
MY_APP_SITE          = https://github.com/myorg/my-app/archive/refs/tags
MY_APP_SOURCE        = v$(MY_APP_VERSION).tar.gz
MY_APP_DEPENDENCIES  = libcurl openssl
MY_APP_LICENSE       = MIT
MY_APP_LICENSE_FILES = LICENSE

define MY_APP_BUILD_CMDS
	$(MAKE) CC="$(TARGET_CC)" LD="$(TARGET_LD)" \
		CFLAGS="$(TARGET_CFLAGS)" \
		LDFLAGS="$(TARGET_LDFLAGS)" \
		-C $(@D)
endef

define MY_APP_INSTALL_TARGET_CMDS
	$(INSTALL) -D -m 0755 $(@D)/my-app \
		$(TARGET_DIR)/usr/bin/my-app
	$(INSTALL) -D -m 0644 $(@D)/config/default.conf \
		$(TARGET_DIR)/etc/my-app/my-app.conf
endef

$(eval $(call generic-package))

cmake-package örneği

package/my-app/my-app.mk — CMake varyantı
MY_APP_VERSION   = 2.0.0
MY_APP_SITE      = https://github.com/myorg/my-app/archive/v$(MY_APP_VERSION).tar.gz
MY_APP_LICENSE   = Apache-2.0

# CMake konfigürasyon seçenekleri (-DXXX=YYY)
MY_APP_CONF_OPTS = \
	-DBUILD_TESTS=OFF \
	-DBUILD_DOCS=OFF \
	-DENABLE_MQTT=ON \
	-DENABLE_TLS=ON

# cmake configure + ninja build + install otomatik çalışır
$(eval $(call cmake-package))

Local source override ile geliştirme

bash — local source override
# Tarball indirmek yerine yerel kaynak dizini kullan
# Geliştirme aşamasında her değişiklikte hız kazandırır

# local.mk dosyasına ekle (Buildroot kök dizinine):
echo 'MY_APP_OVERRIDE_SRCDIR = /home/user/src/my-app' >> local.mk

# Build et (tarball indirilmez, yerel dizin kullanılır)
make my-app-rebuild

# Kaynak değişikliği → direkt rebuild (indirme yok)
make my-app-rebuild  # ~5-10 saniye

# Override'ı kaldır (release build için)
sed -i '/MY_APP_OVERRIDE/d' local.mk

Gerçek örnek: basit C daemon

src/hello-daemon.c
/* hello-daemon: syslog'a mesaj yazan minimal daemon */
#include <stdio.h>
#include <syslog.h>
#include <unistd.h>
#include <signal.h>

static volatile int running = 1;

void sig_handler(int sig) { running = 0; }

int main(void) {
    openlog("hello-daemon", LOG_PID, LOG_DAEMON);
    signal(SIGTERM, sig_handler);
    signal(SIGINT,  sig_handler);

    syslog(LOG_INFO, "started");
    while (running) {
        syslog(LOG_INFO, "heartbeat");
        sleep(10);
    }
    syslog(LOG_INFO, "stopped");
    closelog();
    return 0;
}
NOT

generic-package, autotools-package, cmake-package makrolarının farkı: generic-package'ta BUILD_CMDS ve INSTALL_TARGET_CMDS adımlarını kendiniz yazarsınız. autotools-package ise ./configure --host=TARGET + make + make install adımlarını otomatik yönetir. cmake-package de benzer şekilde cmake -DCMAKE_TOOLCHAIN_FILE=... + ninja + ninja install sırasını çalıştırır. Özel ek argümanlar için sırasıyla PKGNAME_CONF_OPTS veya PKGNAME_CONF_OPTS değişkeni kullanılır.

Bu bölümde

  • Config.in: menuconfig girişi — BR2_PACKAGE_MY_APP, depends on, select, help
  • my-app.mk: MY_APP_VERSION, MY_APP_SITE, BUILD_CMDS, INSTALL_TARGET_CMDS
  • cmake-package: CMake projeler için — CONF_OPTS ile -D argümanları
  • MY_APP_OVERRIDE_SRCDIR: local.mk'ya ekle → tarball indirilmeden yerel kaynak kullan

05 Board support (custom hardware)

board/ dizini board-specific her şeyi merkezi tutar: kernel config, post-build script, overlay, U-Boot config ve genimage için partition şablonu.

board/ dizin yapısı

Dosya / DizinAmaç
board/myvendor/myboard/Board'a özel tüm dosyalar
board/myvendor/myboard/linux.configKernel defconfig — make linux-update-defconfig ile güncellenir
board/myvendor/myboard/uboot.configU-Boot defconfig
board/myvendor/myboard/patches/linux/Kernel kaynak yamalar (.patch dosyaları)
board/myvendor/myboard/rootfs-overlay/Rootfs overlay dizini — target'a doğrudan kopyalanır
board/myvendor/myboard/post-build.shRootfs hazırlandıktan sonra çalışır — dinamik değişiklikler
board/myvendor/myboard/post-image.shImage oluşturulduktan sonra — genimage, U-Boot + kernel birleştirme
board/myvendor/myboard/genimage.cfgSD kart partition tablosu şablonu
configs/myboard_defconfigTam board konfigürasyonu — make savedefconfig ile üretilir

linux.config — kernel defconfig override

bash — kernel config yönetimi
# .config'te board'a özel linux.config belirt
# BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
# BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/myvendor/myboard/linux.config"

# Kernel menuconfig ile değişiklik yap
make linux-menuconfig

# Değişiklikleri board dizinine kaydet
make linux-update-defconfig
# → board/myvendor/myboard/linux.config güncellenir

# Kernel yamalarını uygulama
# board/myvendor/myboard/patches/linux/ dizinindeki .patch dosyaları
# Buildroot otomatik uygular: BR2_GLOBAL_PATCH_DIR kullanılarak
BR2_GLOBAL_PATCH_DIR="board/myvendor/myboard/patches"

post-build.sh — rootfs modifikasyonu

board/myvendor/myboard/post-build.sh
#!/bin/bash
# Buildroot: post-build.sh çağrılır sonra image üretilir
# Argüman: $1 = TARGET_DIR (output/target/)

set -e
TARGET_DIR="$1"

# Hostname ayarla
echo "myboard-v2" > "${TARGET_DIR}/etc/hostname"

# Build bilgisini rootfs'e göm
cat > "${TARGET_DIR}/etc/build-info" <<EOF
BUILD_DATE=$(date +%Y-%m-%dT%H:%M:%S)
BUILD_HOST=$(hostname)
GIT_HASH=$(git -C "${BR2_EXTERNAL_MYPROJECT_PATH}" rev-parse --short HEAD 2>/dev/null || echo unknown)
BUILDROOT_VERSION=$(git -C "$(dirname "$0")/../../../" describe --tags 2>/dev/null || echo unknown)
EOF

# Gereksiz dosyaları sil (rootfs boyutunu düşür)
rm -rf "${TARGET_DIR}/usr/share/doc"
rm -rf "${TARGET_DIR}/usr/share/man"
rm -f  "${TARGET_DIR}/usr/bin/perl"

post-image.sh — SD kart image

board/myvendor/myboard/post-image.sh
#!/bin/bash
# post-image.sh: image oluşturulduktan sonra SD kart image yap
# Değişkenler: BINARIES_DIR, HOST_DIR, BUILD_DIR, BR2_EXTERNAL

set -e
GENIMAGE_CFG="${BR2_EXTERNAL_MYPROJECT_PATH}/board/myvendor/myboard/genimage.cfg"

# genimage aracıyla partition tablosu oluştur
"${HOST_DIR}/bin/genimage" \
  --config "${GENIMAGE_CFG}" \
  --rootpath "${TARGET_DIR}" \
  --tmppath  "${BUILD_DIR}/genimage.tmp" \
  --inputpath "${BINARIES_DIR}" \
  --outputpath "${BINARIES_DIR}"

genimage.cfg — SD kart partition şablonu

board/myvendor/myboard/genimage.cfg
image boot.vfat {
    vfat {
        files = {
            "zImage",
            "myboard.dtb",
            "u-boot.bin"
        }
    }
    size = 32M
}

image sdcard.img {
    hdimage {}

    partition boot {
        partition-type = 0xC   # FAT32
        bootable = "true"
        image = "boot.vfat"
    }

    partition rootfs {
        partition-type = 0x83  # Linux
        image = "rootfs.ext4"
    }
}

Bu bölümde

  • board/myvendor/myboard/: linux.config, patches, overlay, post-*.sh tek dizinde
  • make linux-update-defconfig: kernel menuconfig değişikliklerini board dizinine kaydet
  • post-build.sh: hostname, build tarihi, gereksiz dosya silme — image öncesi hook
  • genimage.cfg + post-image.sh: boot + rootfs partition'larını tek sdcard.img'e birleştir

06 Rootfs kişiselleştirme

Rootfs overlay, post-build script, kullanıcı tablosu ve device table — paket yazmadan rootfs'i şekillendirmenin dört yolu.

BR2_ROOTFS_OVERLAY — dosya sistemi overlay

bash — overlay kurulumu
# Overlay dizin yapısını oluştur
mkdir -p board/myvendor/myboard/rootfs-overlay/etc/init.d
mkdir -p board/myvendor/myboard/rootfs-overlay/etc/my-app
mkdir -p board/myvendor/myboard/rootfs-overlay/usr/bin

# .config'te overlay dizinini belirt
# BR2_ROOTFS_OVERLAY="board/myvendor/myboard/rootfs-overlay"
# Birden fazla dizin (boşlukla ayır):
# BR2_ROOTFS_OVERLAY="board/common/overlay board/myvendor/myboard/rootfs-overlay"
Overlay dosyasıCihazda hedefAmaç
etc/init.d/S99my-app/etc/init.d/S99my-appBusyBox SysV init başlatma scripti
etc/my-app/config.yaml/etc/my-app/config.yamlUygulama konfigürasyonu
etc/network/interfaces/etc/network/interfacesStatik IP / DHCP ağ ayarları
etc/inittab/etc/inittabBusyBox init konfigürasyonu override
usr/bin/health-check.sh/usr/bin/health-check.shScript dosyaları, yardımcı araçlar

BusyBox init scripti — /etc/init.d/S99my-app

rootfs-overlay/etc/init.d/S99my-app
#!/bin/sh
# S99my-app: BusyBox SysV init başlatma scripti
# 'S' prefix'i = start; sayı = sıra (99 = en son)

DAEMON=/usr/bin/my-app
PIDFILE=/var/run/my-app.pid
CFGFILE=/etc/my-app/config.yaml

case "$1" in
  start)
    printf "Starting my-app... "
    start-stop-daemon -S -b -m -p $PIDFILE \
      -x $DAEMON -- --config $CFGFILE
    echo "OK"
    ;;
  stop)
    printf "Stopping my-app... "
    start-stop-daemon -K -p $PIDFILE
    echo "OK"
    ;;
  restart)
    "$0" stop; sleep 1; "$0" start
    ;;
  *)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
esac

users.table — servis kullanıcısı

board/myvendor/myboard/users.table
# Format: username uid group gid password home shell groups comment
# uid/gid = -1 → otomatik atama
# password = !  → login yasak (servis hesabı)
myapp  -1 myapp  -1  !  /var/lib/myapp  /bin/false  -  "myapp service user"

# .config'te tabloyu belirt:
# BR2_ROOTFS_USERS_TABLES="board/myvendor/myboard/users.table"

device_table.txt — özel cihaz dosyaları

board/myvendor/myboard/device_table.txt
# Format: path type mode uid gid major minor start inc count
# type: f=dosya, d=dizin, c=char device, b=block device, l=symlink

# Özel karakter cihazı (örn: custom FPGA driver)
/dev/fpga0  c  0660  0  myapp  240  0  0  0  -

# /var/log dizini oluştur
/var/log    d  0755  0  0   -   -   -  -  -
/var/run    d  0755  0  0   -   -   -  -  -

# .config'te belirt:
# BR2_ROOTFS_DEVICE_TABLE="board/myvendor/myboard/device_table.txt"

Şifre hashing

.config — root şifre ayarları
# SHA256 hash ile şifre (güvenli)
BR2_TARGET_GENERIC_PASSWD_METHOD_SHA256=y
BR2_TARGET_GENERIC_ROOT_PASSWD="mysecretpassword"

# MD5 (eski sistemler, önerilmez)
# BR2_TARGET_GENERIC_PASSWD_METHOD_MD5=y

# Şifresiz root (geliştirme ortamı için)
# BR2_TARGET_GENERIC_ROOT_PASSWD=""

# Üretimde şifreyi build sistemi değişkeni üzerinden ver
# export BR2_TARGET_GENERIC_ROOT_PASSWD="$(cat /etc/secrets/rootpw)"

Bu bölümde

  • Rootfs overlay: board/*/rootfs-overlay/ → doğrudan / üzerine kopyalanır
  • BR2_ROOTFS_POST_BUILD_SCRIPT: hostname, build tarihi gibi dinamik değişiklikler için
  • users.table: servis kullanıcısı oluştur; device_table.txt: özel cihaz node'ları
  • BR2_TARGET_GENERIC_PASSWD_METHOD_SHA256: root şifresi güvenli hash ile saklanır

07 External toolchain kullanımı

Linaro, ARM GNU veya vendor SDK gibi hazır toolchain'leri Buildroot'a entegre ederek gcc derleme adımını tamamen atlayabilirsiniz.

Ne zaman external toolchain

Hızgcc kaynak derlemesi atlanır — ilk build 20 dakika yerine 5 dakika
Linaro / ARM GNUTest edilmiş, optimize edilmiş toolchain; Cortex-A için -mcpu tuning yapılmış
Vendor SDKSoC üreticisinin (NXP, TI, Rockchip) kendi toolchain'i — BSP patch'leriyle uyumlu
TutarlılıkAynı toolchain sürümünü CI ve geliştirici ortamında kullanmak bütünlüğü sağlar

menuconfig — external toolchain yapılandırması

.config — Linaro ARM GNU Toolchain
# External toolchain (pre-built binary)
BR2_TOOLCHAIN_EXTERNAL=y

# Önceden tanımlı toolchain seçimi
# menuconfig → Toolchain → Toolchain → ARM AArch64 2023.06 (Linaro)
BR2_TOOLCHAIN_EXTERNAL_LINARO_AARCH64=y

# ya da ARM32 hard-float Linaro
BR2_TOOLCHAIN_EXTERNAL_LINARO_ARMHF=y

# ya da ARM GNU (arm.com toolchain)
BR2_TOOLCHAIN_EXTERNAL_ARM_AARCH64=y

# Buildroot tanımadığı 3rd-party toolchain için:
BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y
BR2_TOOLCHAIN_EXTERNAL_PATH="/opt/vendor-sdk/arm-linux-gnueabihf"
BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="arm-linux-gnueabihf"

Custom external toolchain — tam yapılandırma

.config — vendor SDK entegrasyonu
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y

# Toolchain binary'lerinin konumu
BR2_TOOLCHAIN_EXTERNAL_PATH="/opt/vendor-sdk/gcc-arm-11.2"

# Prefix: arm-none-linux-gnueabihf-, arm-linux-gnueabihf- vb.
BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="arm-none-linux-gnueabihf"

# C library tipi (toolchain ile eşleşmeli)
BR2_TOOLCHAIN_EXTERNAL_GLIBC=y

# Kernel headers versiyonu (toolchain ile eşleşmeli)
BR2_TOOLCHAIN_EXTERNAL_HEADERS_5_15=y

# C++ desteği varsa
BR2_TOOLCHAIN_EXTERNAL_CXX=y

Doğrulama

bash — toolchain doğrulama
# Build sonrası toolchain wrapper'ları kontrol et
ls output/host/bin/ | grep -E '(gcc|g\+\+|ld|ar)$'
# arm-buildroot-linux-gnueabihf-gcc
# arm-buildroot-linux-gnueabihf-g++
# arm-buildroot-linux-gnueabihf-ld

# Versiyon ve target tuple
output/host/bin/arm-buildroot-linux-gnueabihf-gcc --version
# arm-buildroot-linux-gnueabihf-gcc (Linaro GCC 12.3) 12.3.1

# Sysroot konumu
output/host/bin/arm-buildroot-linux-gnueabihf-gcc -print-sysroot
# output/host/arm-buildroot-linux-gnueabihf/sysroot

# Test: basit cross-compile
output/host/bin/arm-buildroot-linux-gnueabihf-gcc \
  -o /tmp/hello_arm hello.c
file /tmp/hello_arm
# ELF 32-bit LSB executable, ARM, EABI5

Sysroot ve soname bağımlılıkları

bash — soname kontrolü
# Target binary'nin kütüphane bağımlılıklarını listele
output/host/bin/arm-buildroot-linux-gnueabihf-readelf \
  -d output/target/usr/bin/my-app | grep 'NEEDED'
# 0x00000001 (NEEDED) libcurl.so.4
# 0x00000001 (NEEDED) libssl.so.3
# 0x00000001 (NEEDED) libc.so.6

# Rootfs'te kütüphane var mı?
ls output/target/usr/lib/libcurl.so*
# Eksikse: menuconfig → Libraries → libcurl seç

Bu bölümde

  • BR2_TOOLCHAIN_EXTERNAL=y: Linaro, ARM GNU, vendor SDK entegrasyonu
  • BR2_TOOLCHAIN_EXTERNAL_PATH: 3rd-party toolchain dizini; CUSTOM_PREFIX: tuple adı
  • output/host/bin/: Buildroot wrapper scriptleri — cross-compile ortamını hazırlar
  • readelf -d: NEEDED kütüphanelerin rootfs'te bulunduğunu doğrula

08 Build hızlandırma

BR2_DL_DIR, BR2_CCACHE ve incremental rebuild stratejileri — günlük geliştirme döngüsünü hızlandıran teknikler.

BR2_DL_DIR — download cache

bash — paylaşılan download cache
# Birden fazla Buildroot projesi için ortak indirme dizini
# Her proje ayrı build dir, aynı dl/ paylaşır
mkdir -p /data/buildroot-dl

# .config'te veya komut satırında belirt
make BR2_DL_DIR=/data/buildroot-dl -j$(nproc)

# Kalıcı ayar için .bashrc veya CI environment:
export BR2_DL_DIR=/data/buildroot-dl

# Avantaj: 5+ projeniz varsa & linux kernel (~100 MB)
# yalnızca bir kez indirilir

# Toplam dl/ boyutunu kontrol et
du -sh /data/buildroot-dl
# Tipik: 3–10 GB (tüm proje kaynak tarball'ları)

BR2_CCACHE — compiler cache

.config — ccache
# menuconfig → Build options → Enable compiler cache
BR2_CCACHE=y
BR2_CCACHE_DIR="/home/user/.buildroot-ccache"

# ccache istatistikleri (build sonrası)
ccache -s
# cache directory: /home/user/.buildroot-ccache
# cache hit (direct):    1234
# cache hit (preprocessed): 89
# cache miss:            456
# cache size:            2.4 GB

# İlk build: ~30 dakika (cache dolu değil)
# İkinci tam build: ~4-8 dakika (cache hit rate %70-90)
# Yalnızca paket değişikliği: ~1-2 dakika

Paralel build ve jlevel

bash — paralel build seçenekleri
# Otomatik: mevcut CPU sayısını kullan
make -j$(nproc)

# .config'te sabit değer ayarla
# BR2_JLEVEL=8   → make -j8 anlamında
BR2_JLEVEL=0   # 0 = nproc otomatik (önerilir)

# Belirli paket için paralel seviye kısıtla
# (bellek yiyen paketler için — örn. GCC kendisi)
BR2_JLEVEL_PACKAGES_PARALLELISM=4

make graph-depends ve graph-build

bash — analiz araçları
# Tüm paket bağımlılık grafiği
make graph-depends
dot -Tsvg output/graphs/graph-depends.dot -o deps.svg
# Büyük projeler için xdot veya graphviz kullanın

# Tek paket bağımlılık grafiği
make python3-graph-depends

# Build süresi analizi (her paketin build süresi)
make graph-build
# output/graphs/graph-build.* dosyaları oluşur
# En uzun süren paketleri gösterir → toolchain, GCC, Qt5 genellikle başta

# Lisans bilgisi raporu
make legal-info
ls output/legal-info/
# manifest.csv  — tüm paket lisansları
# licenses/      — lisans metinleri
# sources/       — GPL gerektiren kaynak kopyaları

Incremental rebuild stratejisi

Değişiklik türüGerekli komutSüre
Tek paket kaynak değişikliğimake <pkg>-rebuildSaniyeler–dakikalar
Yeni paket eklendimakeYeni paket + bağımlılıklar
Kernel konfigürasyonu değiştimake linux-rebuild5–15 dakika
Toolchain versiyonu değiştimake clean && makeTam rebuild (~30 dk)
C library değişti (glibc→musl)make clean && makeTam rebuild (~30 dk)
Sadece overlay dosyası değiştimake<1 dakika
UYARI

Toolchain veya C library değiştirildiğinde make clean zorunludur. Bu komut output/ dizinini tamamen siler (dl/ hariç). make distclean ise .config dahil her şeyi temizler — dikkatli kullanın. Yalnızca paket veya kernel konfigürasyonu değiştiyse make clean gerekmez; Buildroot ilgili paketleri yeniden derler.

Bu bölümde

  • BR2_DL_DIR: birden fazla proje için ortak indirme cache — disk tasarrufu
  • BR2_CCACHE=y: 2–5x hızlanma — her projede açık tutun
  • make graph-build: hangi paket en uzun sürdü — bottleneck analizi
  • Toolchain/libc değişikliği → make clean; paket değişikliği → sadece make <pkg>-rebuild

09 Pratik: minimal IoT image

Hedef: ARM Cortex-A8, 16 MB rootfs, musl libc, MQTT destekli — gerçek bir endüstriyel IoT cihazının konfigürasyon seti.

Hedef gereksinimleri

MimariARM Cortex-A8, hard-float ABI, NEON desteği
Rootfs boyutuSquashfs sıkıştırılmış ≤16 MB
Boot süresiU-Boot → kernel → init → uygulama: <8 saniye
Gerekli yazılımmosquitto client, dropbear SSH, python3-minimal, busybox
StorageeMMC 64 MB — squashfs read-only rootfs + küçük data partition

Konfigürasyon seçimleri

configs/iot-cortex-a8_defconfig
# Target: ARM Cortex-A8 hard-float
BR2_arm=y
BR2_cortex_a8=y
BR2_ARM_EABIHF=y
BR2_ARM_FPU_NEON=y

# External toolchain (hızlı build için)
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TOOLCHAIN_EXTERNAL_LINARO_ARMHF=y

# musl libc — küçük, güvenli
BR2_TOOLCHAIN_BUILDROOT_LIBC="musl"

# Build optimizasyonu
BR2_OPTIMIZE_S=y              # -Os: boyut öncelikli
BR2_STRIP_strip=y             # debug sembolleri kaldır
BR2_CCACHE=y

# Sistem konfigürasyonu
BR2_TARGET_GENERIC_HOSTNAME="iot-device"
BR2_INIT_BUSYBOX=y            # hafif init
BR2_TARGET_GENERIC_PASSWD_METHOD_SHA256=y

# Paketler
BR2_PACKAGE_BUSYBOX=y
BR2_PACKAGE_DROPBEAR=y        # ~350 KB — openssh'den küçük
BR2_PACKAGE_MOSQUITTO=y
BR2_PACKAGE_MOSQUITTO_BROKER=y
BR2_PACKAGE_PYTHON3=y
BR2_PACKAGE_PYTHON3_PY_ONLY=y # .pyc derlemesini atla → küçük
BR2_PACKAGE_PYTHON_PAHO_MQTT=y

# Kernel
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.21"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/iot/linux-minimal.config"

# Squashfs read-only rootfs
BR2_TARGET_ROOTFS_SQUASHFS=y
BR2_TARGET_ROOTFS_SQUASHFS_LZMA=y  # iyi sıkıştırma, hızlı açma

Kernel minimal config — sadece gerekli sürücüler

board/iot/linux-minimal.config (fragment)
# Genel
CONFIG_LOCALVERSION="-iot"
CONFIG_EXPERT=y
CONFIG_EMBEDDED=y

# Gereksiz özellikleri devre dışı bırak
# CONFIG_STAGING is not set
# CONFIG_HAMRADIO is not set
# CONFIG_ISDN is not set
# CONFIG_INPUT_KEYBOARD is not set (headless cihaz)

# Gerekli ağ desteği
CONFIG_NET=y
CONFIG_INET=y
CONFIG_TCP_CONG_CUBIC=y
# CONFIG_IPV6 is not set (gerekli değilse)

# eMMC sürücüsü
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_OMAP=y

# Ethernet
CONFIG_NET_VENDOR_TI=y
CONFIG_TI_CPSW=y

# Squashfs desteği (rootfs için)
CONFIG_SQUASHFS=y
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_LZO=y

Toplam boyut ve boot süresi

BileşenBoyut (squashfs)Boyut (ext4)
BusyBox (musl statik)~580 KB~900 KB
dropbear SSH~320 KB~520 KB
mosquitto broker~180 KB~280 KB
python3 (minimal)~5.2 MB~8.5 MB
paho-mqtt modülü~120 KB~200 KB
musl libc~410 KB~620 KB
Diğer (/etc, /dev vb.)~200 KB~300 KB
Toplam rootfs~7 MB~11 MB

Deployment: eMMC yazma

bash — eMMC deployment
# Build
make iot-cortex-a8_defconfig
make -j$(nproc)

# Çıktıları kontrol et
ls -lh output/images/
# sdcard.img       — genimage tarafından üretilen tam image
# zImage           — Linux kernel
# am335x-iot.dtb   — device tree
# rootfs.squashfs  — ~7 MB sıkıştırılmış rootfs

# SD kart / eMMC'ye yaz
sudo dd if=output/images/sdcard.img of=/dev/mmcblk0 \
  bs=4M status=progress conv=fsync
sudo sync

# OTA update için squashfs'i doğrudan yaz (sadece rootfs)
sudo dd if=output/images/rootfs.squashfs \
  of=/dev/mmcblk0p2 bs=1M status=progress
sudo sync
NOT

Squashfs read-only rootfs kullandığınızda uygulama verisi için ayrı bir ext4 partition gereklidir. /var, /tmp, /etc/my-app/ gibi yazılabilir konumları bu partition'a veya tmpfs'e (mount -t tmpfs tmpfs /tmp) bağlayın. Bu yapı OTA güncellemelerini basitleştirir: rootfs partition'ını atomik olarak değiştirebilirsiniz.

Bu bölümde

  • ARM Cortex-A8 + musl + -Os + strip → squashfs ~7 MB rootfs
  • dropbear (SSH) + mosquitto (MQTT) + python3-minimal — IoT temel stack
  • Minimal kernel config: gereksiz sürücüleri kapat → kernel boyutu ve boot süresi düşer
  • Squashfs read-only rootfs: OTA güncellemesi için partition atomik değiştirilir