What is Building Toolchains With Crosstool-NG in Linux-Free Embedded Linux Course

Building Toolchains With Crosstool-NG

Stop downloading toolchains you don’t understand. Build one from source and see exactly what’s inside.

crosstool-NG 1.28.0 is the current stable release
Hundreds of sample configurations ship out of the box
One menuconfig session is all it takes to customize a build
free linux kernel development course
free embedded linux course
free embedded systems course

What You Will Learn

Where crosstool-NG came from and why it still matters
Installing crosstool-NG’s build dependencies today
Picking and customizing a sample configuration
The float-ABI gotcha that catches almost everyone once
Building and testing your first from-scratch toolchain

Prerequisites

Understand toolchain tuples and ABIs from the earlier lectures
A Linux host machine or VM with a few GB of free disk space
Roughly 30-60 minutes for the build itself

Why Build a Toolchain From Source?

Prebuilt toolchains from Bootlin or Arm cover most needs, but building one yourself is still the fastest way to actually understand what a toolchain is made of. Dan Kegel started this idea years ago with a set of scripts called crosstool. In 2007, Yann E. Morin rebuilt the concept from the ground up as crosstool-NG, adding a menu-driven configuration front-end similar in spirit to the Linux kernel’s own menuconfig. It remains, by a wide margin, the most approachable way to generate a fully custom cross toolchain from source.

Installing Crosstool-NG Today

You need a working native toolchain and a handful of build dependencies on the host first. On a current Ubuntu or Debian host, install the prerequisites crosstool-NG actually needs today, which has drifted since Python 2 was retired:

$ sudo apt-get install automake bison chrpath flex g++ git gperf \
  gawk libexpat1-dev libncurses-dev libsdl1.2-dev libtool \
  python3-dev texinfo help2man libtool-bin unzip rsync

Then fetch the current release and build the ct-ng front-end itself:

$ wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.28.0.tar.bz2
$ tar xf crosstool-ng-1.28.0.tar.bz2
$ cd crosstool-ng-1.28.0
$ ./configure --enable-local
$ make
$ make install

The --enable-local flag installs everything into the current directory instead of a system path, so you don’t need root privileges. From here on you launch the tool with ./ct-ng.

Picking a Sample Configuration

Crosstool-NG ships with a large library of sample configurations covering common CPU and ABI combinations, which saves you from configuring everything by hand. List them with:

$ ./ct-ng list-samples

Say your target is a 64-bit Arm Cortex-A53 board, a very common core in current single-board computers. The closest sample is typically named along the lines of aarch64-unknown-linux-gnu. Inspect its defaults before committing to it:

$ ./ct-ng show-aarch64-unknown-linux-gnu
[L..] aarch64-unknown-linux-gnu
    OS         : linux-6.x
    binutils   : binutils 2.4x
    C compiler : gcc 14.x (C,C++)
    C library  : glibc 2.4x (threads: nptl)
    Tools      : gdb strace ltrace

Exact component versions shift with each crosstool-NG release, since it tracks current upstream GCC, binutils, and glibc/musl releases rather than pinning to fixed old versions. Select the sample as your starting configuration:

$ ./ct-ng aarch64-unknown-linux-gnu

Customizing With menuconfig

Before building, review and adjust the configuration:

$ ./ct-ng menuconfig

The interface will feel immediately familiar if you’ve ever configured the Linux kernel, because it’s built on the same underlying kconfig system. A few changes are worth making on almost every build:

Menu location Change Why
Paths and misc options Disable “Render the toolchain read-only” Lets you add extra libraries into the toolchain sysroot later
Target options > Floating point Select hardware (FPU) Uses the CPU’s hardware floating-point unit instead of a slow software emulation
C-library > extra config Add any package-specific compatibility flags you’ve identified you need Some legacy userspace packages still expect obsolete headers or interfaces
Crosstool-NG Build Flow
list-samples → select sample → menuconfig → ct-ng build → toolchain in ~/x-tools/

The Float-ABI Gotcha

Here is the trap that catches almost everyone the first time. On 32-bit ARM, choosing the hardware FPU option in menuconfig does not automatically flip the ABI tuple to the hard-float variant in every crosstool-NG version. If your target tuple should read eabihf but the generated configuration still shows plain eabi, you may need to explicitly force the hard-float ABI in the raw .config file:

CT_ARCH_ARM_EABI_FORCE=y
CT_ARCH_ARM_TUPLE_USE_EABIHF=y

This mismatch is exactly the kind of ABI inconsistency the earlier lectures warned about, so always confirm your finished toolchain’s tuple with -dumpmachine before you trust it, rather than assuming menuconfig got it right.

Building It

Once the configuration looks right, kick off the build:

$ ./ct-ng build

Expect this to take somewhere between 20 minutes and an hour depending on your host’s CPU, since crosstool-NG is compiling binutils, GCC, your chosen C library, and supporting tools entirely from source. When it finishes, your toolchain lives under ~/x-tools/<tuple>/.

Try It: Verify Your Freshly Built Toolchain

Add the new toolchain to your PATH and prove it works with a small original program, ep_buildcheck.c:

#include <stdio.h>

int main(void)
{
    printf("Built by crosstool-NG, running on target!\n");
    return 0;
}
$ export PATH=~/x-tools/aarch64-unknown-linux-gnu/bin:$PATH
$ aarch64-unknown-linux-gnu-gcc -dumpmachine
aarch64-unknown-linux-gnu

$ aarch64-unknown-linux-gnu-gcc ep_buildcheck.c -o ep_buildcheck
$ file ep_buildcheck
ep_buildcheck: ELF 64-bit LSB pie executable, ARM aarch64, dynamically linked, ...

Common Mistakes

Mistake Why it hurts
Skipping menuconfig entirely and building the raw sample You inherit whatever float ABI and library version the sample author picked, which may not match your board
Rebuilding with a different host GCC version between attempts Can produce inconsistent partial builds; clean the working directory first
Forgetting –enable-local and needing root for a system-wide install Unnecessary complexity for a tool you’ll likely run from one project directory
Not verifying the tuple after building An accidental soft-float build silently under-performs on hardware that has an FPU

Best Practices

Always run ct-ng show-<sample> before committing to a base configuration
Keep the .config file from a successful build under version control
Verify the tuple and float ABI with -dumpmachine after every build
Prefer building on a dedicated CI machine or container for reproducibility
Re-check crosstool-NG’s release notes when moving to a newer version, since default component versions change

Summary and Key Takeaways

Crosstool-NG turns building a cross toolchain from source into a guided, menu-driven process instead of a hand-rolled nightmare of scripts. Pick a sample close to your target, review it with menuconfig, pay close attention to the float ABI on 32-bit ARM, and build. The result is a toolchain you actually understand, not a black box you downloaded. In the next lecture we take that toolchain apart and look at exactly what’s inside it.

FAQ

Do I need crosstool-NG if Buildroot or Yocto already generates a toolchain?

Not necessarily for day-to-day work, but learning crosstool-NG builds real understanding of what those build systems are doing under the hood, which pays off when something goes wrong.

How long does a crosstool-NG build actually take?

Typically 20 minutes to an hour on a modern multi-core host, depending on the C library chosen and how many companion libraries the configuration pulls in.

Why did my toolchain build with the wrong float ABI?

Selecting hardware FPU support in menuconfig doesn’t always update the ABI tuple automatically. You may need to manually set CT_ARCH_ARM_TUPLE_USE_EABIHF=y in the .config file for 32-bit ARM hard-float targets.

Can crosstool-NG build musl or uClibc-ng toolchains, not just glibc?

Yes. Crosstool-NG supports multiple C libraries, and you choose which one in the C-library section of menuconfig before building.

Where does the finished toolchain get installed?

By default under ~/x-tools/<target-tuple>/, unless you changed the install path in menuconfig.

Is python2.7-dev still required to build crosstool-NG?

No. Current crosstool-NG releases build against Python 3, so you should install python3-dev rather than the long-retired Python 2 development headers referenced in older guides.

 

Next: take your new toolchain apart and see what’s inside

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *