5.3.10 · Coding › Build Systems & Toolchain
Intuition Ek sentence mein idea
Cross-compilation ka matlab hai ki aap ek tarah ki machine (host) par program build karte ho jo ek alag tarah ki machine (target) par chalega . Trick yeh hai: compiler ko yeh maan lena band karna hoga ki "main apni machine ke CPU instructions aur apni machine ki libraries use kar sakta hoon" — balki usse batana padega ki kaun sa CPU ke liye code emit karo aur target ki libraries/headers ki kaun si copy ke against link karo. Yeh doosri cheez hai sysroot .
Intuition Kyun karo yeh sab?
Socho tumne ek chote ARM router ke liye firmware likha jisme 64 MB RAM hai aur koi disk nahi. Tum us par gcc nahi chala sakte — jagah nahi hai, woh slow hai, shayad uska koi OS bhi nahi. Toh tum apne bade x86-64 laptop par compile karte ho aur finished binary ko device par bhejte ho . Laptop hai host (jahan compiler chalta hai); router hai target (jahan output chalta hai).
Aisa hi hota hai: Mac par iOS apps banana, Linux par Android .so files banana, desktop par Raspberry Pi image banana, ek brand-new chip ke liye OS bootstrap karna jisme abhi koi compiler hi nahi hai.
Definition Target triplet
Triplet woh string hai jo ek platform ko name karta hai, is shape mein:
<arch>-<vendor>-<os>-<abi/libc>
Example: arm-linux-gnueabihf = ARM architecture, Linux OS, GNU libc, e mbedded abi with h ard f loat. <vendor> field ko aksar unknown rakha jaata hai ya drop kar diya jaata hai.
Worked example Triplet padhna
aarch64-none-elf
aarch64 → 64-bit ARM CPU
none → koi operating system nahi (bare metal!)
elf → output ek raw ELF binary hai, koi libc assumptions nahi
Yeh kyun important hai: none compiler ko bolta hai "koi kernel nahi hai, koi printf nahi, koi malloc nahi jab tak main provide na karun" — toh woh standard C library link nahi karega.
Toolchain tools ka wo complete set hai jo source code ko target binary mein badalta hai, sab usi target triplet ke liye configured:
*-gcc / *-clang — compiler (source → assembly/object)
*-as — assembler (assembly → object)
*-ld — linker (objects + libs → executable)
*-ar, *-objcopy, *-objdump, *-strip — binutils helpers
target ki C library (glibc / musl / newlib) + headers
target ke startup files (crt0.o etc.)
Ek prefix ke saath named: arm-linux-gnueabihf-gcc, arm-linux-gnueabihf-ld, …
Taaki ek native gcc aur ek cross arm-...-gcc $PATH mein saath mein reh sakein bina collide kiye. Prefix hi triplet hai.
Intuition Is note ka sabse gehri idea
Jab tum #include <stdio.h> karte ho aur printf call karte ho, compiler ko target se do cheezein chahiye, apne host se nahi :
headers (stdio.h) — taaki usse printf ka prototype aur struct layouts pata ho jaise woh target par exist karte hain .
libraries (libc.so) — taaki linker printf symbol ko target ke actual binary code ke against resolve kar sake.
Agar usne tumhare host ka /usr/include/stdio.h aur /usr/lib/libc.so le liya, tum x86 code ko ARM binary mein link kar lete → broken. Sysroot woh directory hai jo target machine ke root / ka natak karti hai .
Sysroot ek directory tree hai jo target ke filesystem root ko mirror karta hai, jisme kam se kam usr/include (target headers) aur usr/lib + lib (target libraries) hoti hain. Compiler ko --sysroot=/path bataya jaata hai, aur tab se woh headers <sysroot>/usr/include mein aur libs <sysroot>/usr/lib mein dhundta hai host ke / ki jagah .
Worked example ARM Linux ke liye Hello-world
arm-linux-gnueabihf-gcc \
--sysroot=/opt/arm-sysroot \
-o hello hello.c
file hello # → ELF 32-bit LSB executable, ARM, EABI5
--sysroot kyun? Taaki stdio.h aur libc.so /opt/arm-sysroot se aayein, tumhare laptop se nahi.
file baad mein kyun? Forecast-then-verify : tumne predict kiya tha "ARM"; file CPU confirm karta hai. Agar woh "x86-64" bolta hai, tumne galat compiler use kiya.
Worked example Bare-metal (koi OS nahi, koi libc nahi)
aarch64-none-elf-gcc -nostdlib -ffreestanding \
-T link.ld -o firmware.elf start.s main.c
-nostdlib kyun? Triplet none kehta hai — koi libc nahi hai, toh crt0/libc link karne ki koshish mat karo.
-ffreestanding kyun? Compiler ko bolta hai "koi hosted environment nahi; main special nahi hai, koi printf guaranteed nahi."
-T link.ld kyun? Koi OS loader nahi hone ki wajah se, tumhe ek linker script ke zariye code/data ko sahi physical addresses par rakhna hoga.
Worked example Build system ko cross-compile karne ke liye bolna (autotools)
./configure --host=arm-linux-gnueabihf \
--build=x86_64-linux-gnu \
CC=arm-linux-gnueabihf-gcc \
--with-sysroot=/opt/arm-sysroot
--host AUR --build kyun dono? Unki inequality hi literally hai jisse configure detect karta hai "yeh cross build hai" aur "features probe karne ke liye test binary chalao" wala kaam band kar deta hai (woh nahi chal sakta — binary tumhare host par nahi chalegi).
Common mistake "Main host par compile karke binary copy kar lunga."
Kyun sahi lagta hai: ek binary "sirf ek file" hai, toh copy karna kaam karna chahiye. Kyun galat hai: host binary mein x86 machine instructions hain; target CPU unhe literally decode nahi kar sakta. Fix: ek cross toolchain use karo jiska triplet target ISA se match kare; file se verify karo.
Common mistake Sysroot bhool jaana → "fatal error: stdio.h not found" ya weird link errors.
Kyun sahi lagta hai: gcc ne pehle hamesha headers dhund li! Kyun galat hai: cross gcc ke paas koi default headers/libs nahi hoti jab tak uska sysroot configure na ho (kuch pre-baked aate hain, bahut se nahi aate). Fix: --sysroot pass karo, ya aisa toolchain use karo jo ek bundled karta ho.
Common mistake Host aur target paths mix karna:
-I/usr/include.
Kyun sahi lagta hai: wahan hi headers "rehti hain." Kyun galat hai: yeh host ke headers hain; tum x86 struct sizes ek ARM build mein kheench laoge → silent ABI corruption. Fix: sirf sysroot ke andar ke paths reference karo; defaults ke liye --sysroot ko handle karne do.
gnueabi vs gnueabihf confusion.
Kyun sahi lagta hai: dono "ARM Linux" hain. Kyun galat hai: hf = hard-float ABI (floats FPU registers mein), soft = floats integer registers mein. Alag ABIs wali library aur tumhara code link toh ho jaate hain lekin runtime par crash karte hain. Fix: poora triplet end-to-end match karo, float ABI bhi shaamil hai.
Cross-compilation ka kya matlab hai? Ek machine (host) par ek aisi program build karna jo ek alag machine/architecture (target) par chalti hai.
Compiler vocabulary mein, build/host/target kya hain? build = jahan compiler build hota hai; host = jahan compiler chalta hai; target = jahan output chalta hai.
Target triplet kya hota hai aur uski shape kya hai? Ek platform ka naam: <arch>-<vendor>-<os>-<abi/libc>, jaise arm-linux-gnueabihf.
Toolchain kya hota hai? Tools ka poora matched set (gcc, as, ld, binutils, target libc + headers + startup files) sab ek target triplet ke liye.
Sysroot kya hota hai? Ek directory tree jo target ke / ki copy karti hai, target headers (usr/include) aur libs (usr/lib) rakhti hai, --sysroot se milti hai.
Host /usr/include ki jagah sysroot kyun zaroori hai? Host headers/libs host ISA/ABI ke liye hain; unhe link karne se broken binary banti hai. Sysroot target ke headers aur libs supply karta hai.
--sysroot=S search paths ko kaise change karta hai? Har default root-anchored path p, S+p ban jaati hai (jaise /usr/include → S/usr/include), compiler ke liye ek chroot ki tarah.
aarch64-none-elf mein none ka kya matlab hai?Koi OS nahi (bare metal); koi libc assumptions nahi — tumhe khud startup aur runtime provide karna hoga.
Autotools ko --host aur --build dono kyun chahiye? Unki inequality cross build signal karti hai, un run-tests ko disable karti hai jo host par target binaries execute karte.
-ffreestanding kya karta hai? Compiler ko bolta hai koi hosted runtime/libc nahi hai; main special nahi hai aur standard library functions assumed nahi hain.
gnueabi aur gnueabihf mein antar? Soft-float vs hard-float ABI; floats integer regs vs FPU regs mein pass hote hain. Inhe mix karna link toh kar deta hai par runtime crash karta hai.
Produce ki gayi binary sahi CPU ke liye hai yeh kaise verify karte hain? file binary chalao; yeh architecture print karta hai (jaise "ELF 32-bit ARM").
Recall Feynman: 12 saal ke bachche ko samjhao
Socho tum sirf English mein letters likh sakte ho, lekin tumhara dost sirf French padhta hai. Tum use English mein nahi bhejte — pehle translate karte ho. Cross-compiling yahi hai — tumhara computer ek program ko ek bilkul alag computer, jaise ek chote robot, ki "language" (machine code) mein translate karta hai. Lekin sirf words translate karna kaafi nahi: tumhe dost ki dictionary bhi chahiye taaki tum unke words for cheezein use karo. Sysroot woh borrowed dictionary hai — robot ke apne files ki ek copy, taaki tumhara computer program us tarah build kare jaise robot expect karta hai, naki us tarah jaise tumhara computer apne liye karta.
Mnemonic Teen roles + crux yaad karo
"BHT, then S" — B uild, H ost, T arget teen machines hain; phir S ysroot target ka borrowed root hai.
Aur triplet order ke liye: "A Very Odd ABI" → A rch-V endor-O S-ABI .
Intuition 80/20 — woh 20% jo 80% deta hai
Agar sirf do cheezein yaad rakho: (1) triplet end-to-end target se match karna chahiye (CPU + OS + float ABI), aur (2) sysroot yeh relocate karta hai ki headers/libs kahan milte hain . Almost har cross-compile failure in donon mein se ek ki galti hoti hai.
Linkers and the linking process — sysroot badalta hai ki ld symbols kahan resolve karta hai.
ELF object file format — file/objdump woh ELF arch field padhte hain jise tum target kar rahe ho.
ABI and calling conventions — soft-float vs hard-float yahan rehta hai.
Build systems CMake and autotools — --host/toolchain files cross compiler kaise wire in karte hain.
Chroot and namespaces — sysroot "compiler ke liye chroot" hai.
Static vs dynamic linking — sysroot mein loader ke liye sahi shared libs honi chahiye.
Host machine runs compiler
Target machine runs output
Target triplet arch-vendor-os-abi