5.3.10 · D3Build Systems & Toolchain

Worked examples — Cross-compilation — toolchains, sysroot

4,756 words22 min readBack to topic

This page is the "hands dirty" companion to Cross-compilation — toolchains, sysroot (index 5.3.10). The parent told you what a toolchain, triplet and sysroot are. Here we run the machine through every kind of situation it can hit — every combination of "which machine builds", "does the target have an OS", "static or dynamic", "does it produce an executable or a shared library", "does the sysroot help or hurt". You should never meet a cross-compile case in real life that isn't one of the cells below.


The scenario matrix

Each row is a case class — a genuinely different situation. Each has at least one worked example that lands on it (the "Cell" tag tells you which).

Cell Case class Distinguishing input What changes
A Native (control case) build = host = target nothing special; the baseline to compare against
B Plain cross, dynamic libc build = host ≠ target, has OS needs --sysroot, links libc.so
C Cross, static libc same but -static sysroot's libc.a baked in; no runtime deps
D Bare metal (degenerate: no OS, no libc) <os> = none -nostdlib -ffreestanding, linker script
E Canadian cross (all three differ) build ≠ host ≠ target two toolchains + a target sysroot to build
F Zero/degenerate: header not found sysroot missing/empty the error, and why
G Sign/ABI mismatch (soft vs hard float) gnueabi vs gnueabihf links fine, crashes at run
G2 Endianness mismatch (big vs little) mips vs mipsel links or silently reads bytes backwards
H Real-world word problem Raspberry-Pi image build pick the whole toolchain from a description
I Exam twist reason about ALL search phases derive the full include + library search order
J Output-kind axis: shared library (PIC/PIE) -shared -fPIC (or -fPIE) produces a .so (not an executable), position-independent code

The matrix really is a set of independent yes/no axes. The figure below shows the arch / OS / static-vs-dynamic / output-kind cube, and the decision tree that routes you to each cell.

Figure — Cross-compilation — toolchains, sysroot

We now walk the cells A → J.


Cell A — the native control case


Cell B — plain cross, dynamic libc


Cell C — cross, statically linked libc


Cell D — bare metal (degenerate: no OS, no libc)

Figure — Cross-compilation — toolchains, sysroot

Cell E — the Canadian cross (all three machines differ)


Cell F — zero/degenerate input: the sysroot is missing


Cell G — sign/ABI mismatch: soft-float vs hard-float


Cell G2 — endianness mismatch (big-endian vs little-endian)

Figure — Cross-compilation — toolchains, sysroot

Cell H — real-world word problem


Cell I — exam twist: derive ALL search phases

Figure — Cross-compilation — toolchains, sysroot

Cell J — the output-kind axis: cross-building a shared library (PIC/PIE)


The whole matrix as one picture

The flow below shows how a single decision tree lands you in each cell.

yes

no

no

yes

yes

no

shared lib

executable

dynamic

static

host equals target

Cell A native

target has an OS

Cell D bare metal

all three machines differ

Cell E canadian cross

output kind

Cell J PIC shared object

link libc how

Cell B dynamic

Cell C static

watch triplet sub fields

Cell F missing sysroot

Cell G float ABI crash

Cell G2 endianness


Recall Quick self-test

Which cells REQUIRE a sysroot? ::: B, C, F, H, J, and Cell I's derivation — every case that reads target headers/libs. (D uses -nostdlib, A needs none.) Cross build, links cleanly, crashes on a double — which cell and why? ::: Cell G — soft vs hard float ABI mismatch; the linker matches names, not calling conventions (VFP d0 vs core r0). Cross build reads every 4-byte int backwards — which cell? ::: Cell G2 — endianness mismatch (mips big-endian vs mipsel little-endian). How many pre-existing cross compilers does a Canadian cross need, and what else? ::: Two (build→host and build→target) plus one target sysroot you build (e.g. via make install DESTDIR=…) or apt install. Difference between installation prefix and sysroot? ::: Prefix = where the compiler itself lives (its default paths derive from it); sysroot = where the target's / lives (target headers/libs). Different directories. What is feature-probing and how do you disable its run step? ::: Compiling+running a tiny test program to detect features; make --host--build so autotools goes compile-only, and supply ac_cv_* cache answers. What extra flag does building a .so need and why? ::: -fPIC (position-independent code) plus -shared, because a shared library is loaded at an unpredictable address. On multi-arch Debian, where do default libraries really live? ::: In arch-tagged subdirs like /usr/lib/x86_64-linux-gnu; a cross sysroot mirrors this as S/usr/lib/<triplet>. What does a linker script (-T) do? ::: Maps program sections (.text/.data/.bss) to explicit memory addresses when there is no OS loader to place them.


See also

  • Cross-compilation — toolchains, sysroot (index 5.3.10) — the parent topic
  • 5.3.10 Cross-compilation — toolchains, sysroot (Hinglish)
  • Static vs dynamic linking · Linkers and the linking process · ELF object file format
  • ABI and calling conventions · Build systems CMake and autotools · Chroot and namespaces