Cross-Compilation & Toolchain
TEKNİK REHBER CROSS-COMPILATION TOOLCHAIN 2026

crosstool-NG —
custom toolchain.

Hedef mimari için sıfırdan toolchain derle. menuconfig ile arch, libc ve CPU parametrelerini seç — Yocto veya dağıtım paketi olmadan tam kontrol.

00 Cross-compilation kavramı

Cross-compilation, kodun çalışacağı mimariden farklı bir makinede derlenmesidir. Gömülü geliştirmede standart yaklaşımdır: güçlü x86_64 iş istasyonunda ARM veya RISC-V binary üretirsin.

Üç makine kavramı

build
Derlemenin gerçekleştiği makine. Geliştirici iş istasyonu — genellikle x86_64 Linux.
host
Derleyicinin çalışacağı makine. Basit cross-compile'da build = host. Canadian cross'ta farklıdır.
target
Üretilen binary'lerin çalışacağı makine. Hedef gömülü kart — ARM Cortex-A53, RISC-V, vb.

Canadian Cross

Build ≠ host ≠ target olan senaryodur. Örnek: x86_64 Linux makinesinde, Windows'ta çalışacak bir ARM cross-derleyici üretmek. crosstool-NG bu senaryoyu da destekler ancak tipik embedded kullanımda gerekmez.

  Tipik cross-compile:
  ┌─────────────────────────────────────────────┐
  │  build  = x86_64-pc-linux-gnu               │
  │  host   = x86_64-pc-linux-gnu  (aynı)       │
  │  target = arm-unknown-linux-gnueabihf        │
  └─────────────────────────────────────────────┘

  Canadian cross:
  ┌─────────────────────────────────────────────┐
  │  build  = x86_64-pc-linux-gnu               │
  │  host   = x86_64-w64-mingw32  (Windows)     │
  │  target = aarch64-unknown-linux-gnu          │
  └─────────────────────────────────────────────┘
    

Neden paket yöneticisi toolchain'i yetmez?

Ubuntu'nun gcc-arm-linux-gnueabihf paketi genel amaçlıdır. Cortex-A53 için özel FPU optimizasyonu, belirli bir glibc sürümü veya musl libc gibi gereksinimler için crosstool-NG ile özel toolchain gerekir.

KURAL

Toolchain ile hedef sistemin C kütüphanesi sürüm uyumlu olmalıdır. Toolchain'deki glibc sürümü, hedef rootfs'teki glibc sürümünden yeni olamaz — aksi hâlde binary çalışmaz (version 'GLIBC_2.33' not found hatası).

01 crosstool-NG kurulumu

crosstool-NG, GNU toolchain bileşenlerini (binutils, gcc, glibc/musl, gdb) otomatik indirip derleyen bir meta-build aracıdır. Autotools tabanlıdır, kaynak koddan kurulur.

Sistem bağımlılıkları (Ubuntu/Debian)

bash
sudo apt update
sudo apt install -y \
    gcc g++ gperf bison flex texinfo help2man make \
    libncurses5-dev python3-dev autoconf automake \
    libtool libtool-bin gawk wget bzip2 xz-utils \
    unzip patch libstdc++6 rsync git meson ninja-build

Kaynak koddan kurulum

bash
# Kararlı sürümü indir (2024-02 itibariyle 1.26.0)
git clone https://github.com/crosstool-ng/crosstool-ng.git
cd crosstool-ng
git checkout crosstool-ng-1.26.0

# configure ve install (~$HOME/ct-ng veya /usr/local)
./bootstrap
./configure --prefix="${HOME}/ct-ng"
make -j$(nproc)
make install

# PATH'e ekle
export PATH="${HOME}/ct-ng/bin:${PATH}"
echo 'export PATH="${HOME}/ct-ng/bin:${PATH}"' >> ~/.bashrc

# doğrula
ct-ng version
# crosstool-NG 1.26.0

Hazır sample listeleme

bash
# desteklenen örnek konfigürasyonları listele
ct-ng list-samples

# ARM ile ilgili örnekler
ct-ng list-samples | grep arm
# arm-cortex_a8-linux-gnueabi
# arm-unknown-linux-gnueabi
# armv6-rpi-linux-gnueabi
# aarch64-unknown-linux-gnu

# örnek konfigürasyonu yükle
ct-ng arm-cortex_a8-linux-gnueabi

# ya da temiz başlangıç
ct-ng menuconfig
ÇALIŞMA DİZİNİ

ct-ng komutlarını her zaman proje dizininde çalıştır. .config dosyası geçerli dizinde oluşturulur. Farklı projeler için ayrı dizinler kullan.

02 ct-ng menuconfig — arch ve libc seçimi

menuconfig, Kconfig tabanlı bir arayüzdür — Linux kernel konfigürasyonuyla aynı sistem. Ok tuşları, Space ve Enter ile gezinilir.

ARM Cortex-A53 konfigürasyonu

bash
mkdir ~/toolchains/arm-cortex-a53 && cd ~/toolchains/arm-cortex-a53
ct-ng menuconfig
Target options → Target Architecture
arm seç. 64-bit için aarch64.
Target options → Endianness
Cortex-A53 için Little endian.
Target options → Bitness
32-bit ARM için 32-bit.
Target options → Emit assembly for CPU
cortex-a53 — gcc'ye -mcpu=cortex-a53 geçer.
Target options → Use specific FPU
neon-fp-armv8 — Cortex-A53'ün desteklediği FPU.
Target options → Floating point
hardware (FPU) — hard-float ABI için.

C kütüphanesi seçimi

menuconfig — C-library
C-library → C library → glibc        # tam POSIX, büyük boyut (~2 MB)
C-library → C library → musl         # hafif, statik linking dostu (~600 KB)
C-library → C library → uclibc-ng    # çok küçük MCU/router hedef (~400 KB)
glibc
En geniş uyumluluk. Sunucu/masaüstü uygulamaları glibc bekler. Boyutu büyüktür ancak modern embedded SBC'lerde (RPi, BeagleBone) standarttır.
musl
Hafif, güvenli, statik linkinge uygun. Alpine Linux temeldir. Bazı glibc uzantıları eksik olabilir (pthread_setname_np gibi).
uclibc-ng
En küçük boyut. OpenWRT gibi router/MCU-class cihazlarda kullanılır. C99 + POSIX.1-2008 alt kümesi.

GCC sürümü ve ek bileşenler

menuconfig — Toolchain options
Toolchain options → Tuple's vendor string → "unknown"
                  → Tuple's alias         → "arm-linux-gnueabihf"

CC → GCC version → 13.2.0     # ya da mevcut en güncel
   → C++ support → [*]        # C++ için işaretle
   → Fortran support → [ ]    # gerekmiyorsa kapat

Debug facilities → gdb → [*]  # target üzerinde çalışacak gdb
                → strace → [*]

03 ct-ng build — derleme süreci

Konfigürasyon tamamlandıktan sonra derleme başlatılır. İlk derleme internet bağlantısı gerektirir — kaynak arşivleri otomatik indirilir.

Derlemeyi başlat

bash
# tüm CPU çekirdeklerini kullan (2 eksik bırakmak iyi pratik)
ct-ng build.$(( $(nproc) - 2 ))

# ya da sabit sayı
ct-ng build.4

# hata ayıklama modu — her adımı verbose yazdır
ct-ng build V=1 2>&1 | tee build.log
SÜRE

İlk derleme 30–90 dakika sürer (makineye ve seçilen bileşenlere göre değişir). Sonraki derlemeler, kaynak arşivler önbelleğe alındığı için daha hızlıdır. Önbellek dizini: ~/src/ (CT_LOCAL_TARBALLS_DIR ile değiştirilebilir).

Çıktı konumu

bash
# varsayılan çıktı dizini
ls ~/x-tools/arm-unknown-linux-gnueabihf/

# çıktı dizinini değiştirmek için .config'de
CT_PREFIX_DIR="${HOME}/toolchains/${CT_TARGET}"

# toolchain'i PATH'e ekle
export PATH="${HOME}/x-tools/arm-unknown-linux-gnueabihf/bin:${PATH}"

# test et
arm-unknown-linux-gnueabihf-gcc --version
# arm-unknown-linux-gnueabihf-gcc (crosstool-NG 1.26.0) 13.2.0

Yaygın derleme hataları

FAILED to download
Kaynak sunucu erişim sorunu. CT_SAVE_TARBALLS=y ayarı ve elle indirip ~/src/'e kopyalama çözüm.
No space left on device
Derleme geçici olarak 10–20 GB disk kullanır. CT_WORK_DIR ile büyük disk bölümüne yönlendir.
ERROR: libc0-start failed
Genellikle sysroot yapılandırma sorunu. ct-ng menuconfig'de sysroot seçeneklerini kontrol et.

04 Tuple formatı

Toolchain prefix'i "tuple" olarak adlandırılır. Hedef sistemi tanımlayan standart bir format vardır.

  arm  -  unknown  -  linux  -  gnueabihf
   │         │          │           │
   │         │          │           └─ ABI: gnu + eabi + hf (hard-float)
   │         │          └─ İşletim sistemi: linux
   │         └─ Vendor: unknown (özel: "rpi", "linaro", vb.)
   └─ Mimari: arm

  Örnekler:
  ┌─────────────────────────────────────────────────────┐
  │ aarch64-unknown-linux-gnu       64-bit ARM, glibc   │
  │ arm-unknown-linux-gnueabihf     32-bit ARM hard-FP  │
  │ arm-unknown-linux-gnueabi       32-bit ARM soft-FP  │
  │ arm-unknown-linux-musleabihf    32-bit ARM + musl   │
  │ riscv64-unknown-linux-gnu       RISC-V 64-bit       │
  │ riscv32-unknown-linux-gnu       RISC-V 32-bit       │
  │ arm-unknown-linux-uclibcgnueabi uclibc-ng           │
  └─────────────────────────────────────────────────────┘
    

ABI açıklaması

gnueabi
GNU ABI + EABI (Embedded ABI). Kayan nokta argümanları integer registerlarında (r0-r3) taşınır. Yazılım FPU emülasyonu. Eski ARM çekirdekleri ve FPU'suz sistemler için.
gnueabihf
GNU ABI + EABI + Hard-Float. FPU registerlarını (s0-s15, d0-d7) kayan nokta argümanları için kullanır. Cortex-A ve üstü için — daha hızlı.
musleabihf
musl libc + EABI + Hard-Float. Alpine Linux tarzı küçük ve güvenli sistem için.

05 Toolchain testi — Hello World ARM

Toolchain doğrulaması için minimal C programı derle, ARM binary olduğunu kontrol et ve QEMU ile çalıştır.

Kaynak dosya

hello.c
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    printf("Merhaba ARM dünyası!\n");
    printf("sizeof(long) = %zu\n", sizeof(long));
    return EXIT_SUCCESS;
}

Cross-compile ve doğrulama

bash
# cross-compile
arm-unknown-linux-gnueabihf-gcc -o hello hello.c

# binary tipini doğrula
file hello
# hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV),
#        dynamically linked, interpreter /lib/ld-linux-armhf.so.3, ...

# native x86_64'te çalışmaz
./hello
# bash: ./hello: cannot execute binary file: Exec format error

# QEMU user-mode ile çalıştır
sudo apt install qemu-user-static
qemu-arm-static ./hello
# Merhaba ARM dünyası!
# sizeof(long) = 4

# objdump ile mimariye bak
arm-unknown-linux-gnueabihf-objdump -f hello
# architecture: arm, flags 0x00000112:
# EXEC_P, HAS_SYMS, D_PAGED
DİNAMİK LİNKİNG

Dinamik linked binary'yi QEMU ile çalıştırmak için qemu-arm-static toolchain sysroot'unu bilmeli. QEMU_LD_PREFIX=~/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot qemu-arm-static ./hello komutunu kullan ya da statik link: gcc -static -o hello hello.c.

06 Sysroot yapısı

Sysroot, hedef sistemin dosya sistemi hiyerarşisinin derleme makinesindeki taklididir. Başlık dosyaları ve kütüphaneler buradan alınır.

Dizin yapısı

bash
SYSROOT=~/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot

ls $SYSROOT
# etc  lib  lib64  sbin  usr

tree $SYSROOT -L 3
# ├── lib/
# │   ├── ld-linux-armhf.so.3       ← dynamic linker
# │   ├── libc.so.6                 ← glibc
# │   ├── libm.so.6                 ← math
# │   └── libpthread.so.0           ← threads
# └── usr/
#     ├── include/                  ← başlık dosyaları
#     │   ├── stdio.h
#     │   ├── pthread.h
#     │   └── ...
#     └── lib/
#         ├── libc.a                ← statik kütüphane
#         └── crt1.o               ← C runtime başlangıç

Sysroot'a kütüphane ekleme

bash
# hedef sistemde kurulu bir kütüphanenin başlık ve lib dosyalarını sysroot'a kopyala
# örnek: libssl cross-compile için sysroot'a ekle

SYSROOT=~/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot
TARGET_ROOTFS=/mnt/rpi-rootfs   # SD karttaki rootfs mount noktası

# başlık dosyaları
cp -r ${TARGET_ROOTFS}/usr/include/openssl ${SYSROOT}/usr/include/

# kütüphane dosyaları
cp ${TARGET_ROOTFS}/usr/lib/arm-linux-gnueabihf/libssl.so* ${SYSROOT}/usr/lib/
cp ${TARGET_ROOTFS}/usr/lib/arm-linux-gnueabihf/libcrypto.so* ${SYSROOT}/usr/lib/

# artık --sysroot ile otomatik bulunur
arm-unknown-linux-gnueabihf-gcc --sysroot=$SYSROOT -lssl -lcrypto ...

07 Raspberry Pi toolchain örneği

Raspberry Pi 4 (ARM Cortex-A72, 64-bit) için özel toolchain oluşturma adımları.

Konfigürasyon dosyası

.config — RPi4 aarch64
# Temel mimari
CT_ARCH="arm"
CT_ARCH_64=y
CT_ARCH_ARCH="cortex-a72"
CT_ARCH_FPU="crypto-neon-fp-armv8"
CT_ARCH_FLOAT="hard"
CT_ARCH_WITH_ARCH="-march=armv8-a+crc"

# Vendor tuple
CT_TARGET_VENDOR="rpi4"

# Kernel headers (Raspbian Bullseye = 5.15)
CT_KERNEL_VERSION="5.15.0"

# C kütüphanesi
CT_LIBC="glibc"
CT_LIBC_VERSION="2.35"

# GCC sürümü
CT_CC_GCC_VERSION="13.2.0"

Derleme ve test

bash
ct-ng build.$(nproc)

# Tuple: aarch64-rpi4-linux-gnu
export PATH="${HOME}/x-tools/aarch64-rpi4-linux-gnu/bin:${PATH}"

# derleme
aarch64-rpi4-linux-gnu-gcc -mcpu=cortex-a72 -O2 -o hello hello.c

# RPi'ye kopyala ve çalıştır
scp hello pi@raspberrypi.local:/home/pi/
ssh pi@raspberrypi.local "./hello"
# Merhaba ARM dünyası!
# sizeof(long) = 8  ← 64-bit

08 RISC-V toolchain örneği

RISC-V 64-bit (rv64gc) toolchain oluşturma — SiFive HiFive Unmatched, BeagleV Ahead gibi kartlar için.

menuconfig RISC-V ayarları

bash
# hazır sample ile başla
ct-ng riscv64-unknown-linux-gnu

# veya manuel
ct-ng menuconfig
# Target Architecture → riscv
# Bitness → 64-bit
# Architecture level → rv64gc (general + compressed + double FP)
.config — RISC-V 64
CT_ARCH="riscv"
CT_ARCH_64=y
CT_ARCH_ARCH="rv64gc"
CT_ARCH_ABI="lp64d"          # double-precision FP ABI
CT_TARGET_VENDOR="unknown"
CT_KERNEL_VERSION="6.1.0"
CT_LIBC="glibc"
CT_LIBC_VERSION="2.36"
CT_CC_GCC_VERSION="13.2.0"

RISC-V derleme ve test

bash
ct-ng build.$(nproc)

export PATH="${HOME}/x-tools/riscv64-unknown-linux-gnu/bin:${PATH}"

# derleme — rv64gc ABI
riscv64-unknown-linux-gnu-gcc \
    -march=rv64gc -mabi=lp64d \
    -O2 -o hello hello.c

# doğrula
file hello
# hello: ELF 64-bit LSB executable, UCB RISC-V, RVC, double-float ABI

# QEMU ile test
qemu-riscv64-static ./hello
# Merhaba ARM dünyası!
# sizeof(long) = 8

09 Pre-built toolchain alternatifleri

Özel derleme gerekmiyorsa, topluluğun sağladığı hazır toolchain'ler zaman kazandırır.

Linaro Toolchain

bash
# Linaro aarch64 toolchain indir (releases.linaro.org)
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/\
gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz

tar xf gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz
export PATH="$(pwd)/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin:${PATH}"

aarch64-linux-gnu-gcc --version
# aarch64-linux-gnu-gcc (Linaro GCC 7.5-2019.12) 7.5.0

ARM GNU Toolchain (arm.com)

bash
# developer.arm.com'dan indirme (2023.10 sürümü)
wget https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/\
arm-gnu-toolchain-13.2.rel1-x86_64-aarch64-none-linux-gnu.tar.xz

tar xf arm-gnu-toolchain-13.2.rel1-x86_64-aarch64-none-linux-gnu.tar.xz
export PATH="$(pwd)/arm-gnu-toolchain-13.2.Rel1-x86_64-aarch64-none-linux-gnu/bin:${PATH}"

aarch64-none-linux-gnu-gcc --version
# aarch64-none-linux-gnu-gcc (Arm GNU Toolchain 13.2.rel1) 13.2.0

Ubuntu/Debian paket toolchain'i

bash
# ARM 32-bit hard-float
sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
arm-linux-gnueabihf-gcc --version

# ARM 64-bit
sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
aarch64-linux-gnu-gcc --version

# RISC-V 64-bit
sudo apt install gcc-riscv64-linux-gnu
riscv64-linux-gnu-gcc --version
NE ZAMAN CROSSTOOL-NG?

Paket toolchain'leri çoğu proje için yeterlidir. crosstool-NG'yi şu durumlarda tercih et: özel glibc sürümü gereksinimi, musl/uclibc seçimi, belirli CPU için agresif optimizasyon (-mcpu=cortex-a53 yerine özel arch level), ya da reproducible build gerekliliği.