Cross-Compilation Toolchain Setup

Updated

October 30, 2026

Cross-Compilation Toolchain Setup

In this section, we compile our isolated cross-compiler: $TOOLS/bin/$TARGET-gcc. This compiler runs on the host but emits binaries for our target system.

+-----------------------------------------------------------+
|                Toolchain Construction Sequence            |
|                                                           |
| 1. Linux Kernel Headers -> Staged into $SYSROOT/usr/include
| 2. GNU Binutils (Pass 1) -> Installed into $TOOLS         |
| 3. GCC (Pass 1 / Static) -> Basic C compiler              |
| 4. musl-libc             -> C standard library in $SYSROOT|
| 5. GCC (Pass 2 / Shared) -> Full compiler with libgcc_s   |
+-----------------------------------------------------------+

Step 1: Install Linux Kernel API Headers

Kernel headers provide the system call interfaces needed by the C library:

$ cd "$BYOL_ROOT/build"
$ tar -xf "$BYOL_ROOT/sources/linux-6.10.2.tar.xz"
$ cd linux-6.10.2
$ make mrproper
$ make headers_install INSTALL_HDR_PATH="$SYSROOT/usr"

Verify that <linux/unistd.h> and <asm/types.h> exist inside $SYSROOT/usr/include.

Step 2: Compile Cross-Binutils (Pass 1)

$ cd "$BYOL_ROOT/build"
$ tar -xf "$BYOL_ROOT/sources/binutils-2.42.tar.xz"
$ mkdir -p binutils-build && cd binutils-build

$ ../binutils-2.42/configure \
    --prefix="$TOOLS" \
    --with-sysroot="$SYSROOT" \
    --target="$TARGET" \
    --disable-nls \
    --disable-werror \
    --enable-gold \
    --enable-plugins

$ make $MAKEFLAGS
$ make install

Verify that $TOOLS/bin/$TARGET-as and $TOOLS/bin/$TARGET-ld are available.

Step 3: Compile GCC (Pass 1 - Static / Bootstrap)

Prepare GCC prerequisites:

$ cd "$BYOL_ROOT/build"
$ tar -xf "$BYOL_ROOT/sources/gcc-14.1.0.tar.xz"
$ cd gcc-14.1.0
$ tar -xf "$BYOL_ROOT/sources/mpfr-4.2.1.tar.xz" && mv mpfr-4.2.1 mpfr
$ tar -xf "$BYOL_ROOT/sources/gmp-6.3.0.tar.xz" && mv gmp-6.3.0 gmp
$ tar -xf "$BYOL_ROOT/sources/mpc-1.3.1.tar.gz" && mv mpc-1.3.1 mpc
$ cd ..

$ mkdir -p gcc-build && cd gcc-build
$ ../gcc-14.1.0/configure \
    --target="$TARGET" \
    --prefix="$TOOLS" \
    --with-sysroot="$SYSROOT" \
    --without-headers \
    --disable-nls \
    --disable-shared \
    --disable-threads \
    --disable-libatomic \
    --disable-libgomp \
    --disable-libquadmath \
    --disable-libssp \
    --disable-libvtv \
    --enable-languages=c

$ make all-gcc all-target-libgcc $MAKEFLAGS
$ make install-gcc install-target-libgcc

Step 4: Compile musl-libc

Now compile the target C library using our newly minted $TARGET-gcc:

$ cd "$BYOL_ROOT/build"
$ tar -xf "$BYOL_ROOT/sources/musl-1.2.5.tar.gz"
$ cd musl-1.2.5

$ CC="$TARGET-gcc" ./configure \
    --prefix=/usr \
    --syslibdir=/lib \
    --target="$TARGET"

$ make $MAKEFLAGS
$ make DESTDIR="$SYSROOT" install

Step 5: Test the Cross-Toolchain

Verify that our cross-compiler can build a clean dynamic binary targeting the sysroot:

$ cat << 'EOF' > test.c
#include <stdio.h>
int main() {
    printf("Hello from BYOL Toolchain!\n");
    return 0;
}
EOF

$ $TARGET-gcc test.c -o test
$ file test
test: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1

Success! The toolchain is fully isolated and operational.