Building an AArch64 Toolchain for Raspberry Pi 4 with crosstool-NG
My step-by-step journey building an AArch64 cross-compilation toolchain for Raspberry Pi 4 with crosstool-NG on Ubuntu 24.04 LTS.
Table of Contents
Prerequisites
All steps in this article were tested using the following host and target hardware.
Host PC
OS: Ubuntu 24.04 LTS (64-bit)
CPU: AMD Ryzen 5 4500U
RAM: 12 GB
Architecture: x86_64Target Board
Board: Raspberry Pi 4 Model B
SoC: Broadcom BCM2711
CPU: Quad-core ARM Cortex-A72
Architecture: ARMv8-A (AArch64)
RAM: 2 GB
Target OS: Raspberry Pi OS 64-bitNote: The host PC specifications above are not strict requirements. They simply describe the machine I used to build the toolchain.
First, install the required packages using:
sudo apt-get install autoconf automake bison bzip2 cmake flex g++ gawk gcc \
gettext git gperf help2man libncurses5-dev libstdc++6 libtool \
libtool-bin make patch python3-dev rsync texinfo unzip wget xz-utilsBuilding crosstool-NG
In your workspace, clone the current crosstool-NG Git repository and check out the latest release. At the time of writing, I am using crosstool-ng-1.29.0.
git clone https://github.com/crosstool-ng/crosstool-ng.git
cd crosstool-ng
git checkout crosstool-ng-1.29.0Prepare the crosstool-NG source tree with bootstrap, check the build environment, and generate the Makefiles and configuration with configure.
Then build and install it:
./bootstrap
./configure --prefix="${PWD}" # Install into the current directory
make
make installWe can now use bin/ct-ng to configure and build our toolchain.
Building a Toolchain for Raspberry Pi 4
Run the following command to see the available target samples:
./bin/ct-ng list-samplesThere are quite a few samples, so filtering the output with grep makes it easier to find the Raspberry Pi 4 targets:
./bin/ct-ng list-samples | grep rpi4Example output:
[L...] aarch64-rpi4-linux-gnu
[L...] armv8-rpi4-linux-gnueabihf
L (Local) : sample was found in current directory
G (Global) : sample was installed with crosstool-NG
X (EXPERIMENTAL): sample may use EXPERIMENTAL features
B (BROKEN) : sample is currently broken
O (OBSOLETE) : sample needs to be upgradedI am using a Raspberry Pi 4 Model B, which has a quad-core Cortex-A72 (ARMv8-A) 64-bit SoC.
Therefore, I chose:
aarch64-rpi4-linux-gnuThe armv8-rpi4-linux-gnueabihf target is intended for a 32-bit ARM userspace using the hard-float ABI.
Note: In the AArch64 execution state used by 64-bit ARMv8-A systems, floating-point and SIMD support are part of the architecture. Therefore, there is no separate
hf/hard-floattoolchain naming convention like the one commonly seen with 32-bit ARM toolchains.
If a sample for your board is not available, you may be able to start with a generic target that closely matches the architecture and then customize its configuration.
Get IceJ’s stories in your inbox
Join Medium for free to get updates from this writer.
For example, for a 64-bit ARM Linux target, I might start with:
aarch64-unknown-linux-gnuI have not tested this configuration with the Raspberry Pi 4, however.
Inspecting the sample configuration
We can inspect a sample configuration by adding the show- prefix:
./bin/ct-ng show-aarch64-rpi4-linux-gnuExample output:
[L...] aarch64-rpi4-linux-gnu
Languages : C,C++
OS : linux-7.1
Binutils : binutils-2.47
Compiler : gcc-16.2.0
Linkers :
C library : glibc-2.44
Debug tools : gdb-17.2
Companion libs : expat-2.7.1 gettext-0.26 gmp-6.3.0 isl-0.27
libiconv-1.18 mpc-1.3.1 mpfr-4.2.2 ncurses-6.5
zlib-1.3.1 zstd-1.5.7
Companion tools :Next, select the Raspberry Pi 4 sample:
./bin/ct-ng aarch64-rpi4-linux-gnuExample output:
CONF aarch64-rpi4-linux-gnu#
# configuration written to .config
#***********************************************************Initially reported by: Bensuperpc <bensuperpc@gmail.com>
URL: https://github.com/BensuperpcComment:
Raspberry PI 4 aarch64***********************************************************Now configured for "aarch64-rpi4-linux-gnu"
This creates a .config file containing the toolchain configuration.
Customizing the configuration
Open the configuration menu:
./bin/ct-ng menuconfigFor my use case, I want to be able to modify the toolchain installation later — for example, to add additional libraries to its sysroot.
Therefore, I disable the Render the toolchain read-only option.
After saving the configuration, we are ready to build the toolchain.
./bin/ct-ng buildLD_LIBRARY_PATH sanity-check error
During my first build attempt, I encountered the following sanity-check error:
[INFO ] Performing some trivial sanity checks
[ERROR] Don't set LD_LIBRARY_PATH. It screws up the build.In my case, LD_LIBRARY_PATH had been set by my ROS 2 Jazzy environment.
crosstool-NG intentionally rejects this because LD_LIBRARY_PATH can cause host libraries to be loaded unexpectedly during the toolchain build.
I removed it from the current shell environment and started the build again:
unset LD_LIBRARY_PATH
./bin/ct-ng buildOn my computer, the complete build took approximately 37 minutes:
[INFO ] Build completed at 20260920.120327
[INFO ] (elapsed: 37:25.94)By default, the resulting toolchain was installed under:
~/x-tools/aarch64-rpi4-linux-gnuThe complete toolchain takes approximately 504 MB of disk space on my system.
Toolchain Is Ready
To make the toolchain commands easier to use, add its bin directory to PATH:
export PATH="$HOME/x-tools/aarch64-rpi4-linux-gnu/bin:$PATH"You can verify that the tools are available with:
ls ~/x-tools/aarch64-rpi4-linux-gnu/bin/aarch64-rpi4-linux-gnu-*Example output:
aarch64-rpi4-linux-gnu-addr2line
aarch64-rpi4-linux-gnu-ar
aarch64-rpi4-linux-gnu-as
aarch64-rpi4-linux-gnu-c++
aarch64-rpi4-linux-gnu-cc
aarch64-rpi4-linux-gnu-c++filt
aarch64-rpi4-linux-gnu-cpp
aarch64-rpi4-linux-gnu-elfedit
aarch64-rpi4-linux-gnu-g++
aarch64-rpi4-linux-gnu-gcc
aarch64-rpi4-linux-gnu-gcc-16.2.0
aarch64-rpi4-linux-gnu-gcc-ar
aarch64-rpi4-linux-gnu-gcc-nm
aarch64-rpi4-linux-gnu-gcc-ranlib
aarch64-rpi4-linux-gnu-gcov
aarch64-rpi4-linux-gnu-gcov-dump
aarch64-rpi4-linux-gnu-gcov-tool
aarch64-rpi4-linux-gnu-gdb
aarch64-rpi4-linux-gnu-gdb-add-index
aarch64-rpi4-linux-gnu-gprof
aarch64-rpi4-linux-gnu-gstack
aarch64-rpi4-linux-gnu-ld
aarch64-rpi4-linux-gnu-ld.bfd
aarch64-rpi4-linux-gnu-ldd
aarch64-rpi4-linux-gnu-lto-dump
aarch64-rpi4-linux-gnu-nm
aarch64-rpi4-linux-gnu-objcopy
aarch64-rpi4-linux-gnu-objdump
aarch64-rpi4-linux-gnu-populate
aarch64-rpi4-linux-gnu-ranlib
aarch64-rpi4-linux-gnu-readelf
aarch64-rpi4-linux-gnu-size
aarch64-rpi4-linux-gnu-strings
aarch64-rpi4-linux-gnu-stripAt this point, the Raspberry Pi 4 cross-compilation toolchain is ready to use.
For example:
aarch64-rpi4-linux-gnu-gcc --version
aarch64-rpi4-linux-gnu-g++ --versionThese compilers can now be used to build AArch64 Linux applications for the Raspberry Pi 4 from the Ubuntu host machine.
What’s Next?
At this point, we have successfully built an AArch64 cross-compilation toolchain for the Raspberry Pi 4.
In the next article, I’ll take a closer look at the anatomy of a cross-compilation toolchain and explain what crosstool-NG actually generated.
References
This article was written based on my own toolchain-building experience, with additional guidance and background from the following resources:
- Frank Vasquez and Chris Simmonds, Mastering Embedded Linux Programming, Third Edition, Packt Publishing, 2021.
- crosstool-NG Documentation
- crosstool-NG GitHub Repository





