CRUX-ARM : Home

Home :: Documentation :: Download :: Development :: Community :: Packages :: Bugs :: Links :: About :: Donors

Manual Building

In addition to using pre-built binaries, you may want or need to manually compile U-Boot and the Linux kernel to customize features or apply specific patches for your device. To ensure a reproducible and isolated build environment, we use a Docker container based on Debian armel. This approach allows compilation on various host systems, including Apple Silicon machines.

For our setup, we performed all builds on a Mac mini M4 host, leveraging Docker to provide a consistent Debian armel environment. This method is especially useful for ARM development, as it avoids host dependency issues and simplifies toolchain management

Steps Overview:

1. Prepare the Docker Environment
Install Docker on your host machine (macOS, Linux, or Windows). Ensure you have the latest version and sufficient disk space for the build process

2. Launch a Debian armel Docker Container
Start an interactive shell within a Debian armel container for any armel/armhf build. For example:

docker run --rm -ti armel/debian:latest /bin/bash

This container provides a clean environment where we install the necessary tools for compiling U-Boot and the Kernel.

Note: for aarch64 builds we can use a CRUX-ARM container.

3. Install required build tools
Inside the container, update the package list and install essential packages:

apt-get update
apt-get install -y git make build-essential bison m4 flex python3 python3-setuptools python3-dev swig libssl-dev libgnutls28-dev wget bc device-tree-compiler cpio libncurses-dev

CRUX-ARM container:

prt-get depinst swig gnutls

4. Clone U-Boot source repositories
Fetch the U-Boot repository:

git clone https://source.denx.de/u-boot/u-boot

5. Get/Clone Linux kernel sources:

wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.14.8.tar.gz
tar xvf linux-6.14.8.tar.gz
wget https://resources.crux-arm.nu/files/devices/cubieboard/3.8/kernel/6.14.8config
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.14.8.tar.xz
tar xvf linux-6.14.8.tar.gz
wget https://resources.crux-arm.nu/files/devices/cubieboard2/3.8/kernel/6.14.8/config
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.14.8.tar.gz
tar xvf linux-6.14.8.tar.gz
wget https://resources.crux-arm.nu/files/devices/odroidxu4/3.8/kernel/6.14.8/config
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.14.8.tar.gz
tar xvf linux-6.14.8.tar.gz

6. Compile U-Boot
Configure and build U-Boot for your target board:

cd u-boot
git checkout v2025.04
make Cubieboard_defconfig
make -j$(nproc)

The resulting u-boot-sunxi-with-spl.bin file can then be flashed to the microSD card as described in the installation steps.

Configure and build U-Boot for your target board:

cd u-boot
git checkout v2025.04
make Cubieboard2_defconfig
make -j$(nproc)

The resulting u-boot-sunxi-with-spl.bin file can then be flashed to the microSD card as described in the installation steps.

Configure and build U-Boot for your target board:

cd u-boot
make orangepi_pc_defconfig
make -j$(nproc)

The resulting u-boot-sunxi-with-spl.bin file can then be flashed to the microSD card as described in the installation steps.

Configure and build U-Boot for your target board:

cd u-boot
git checkout v2025.04
make odroid-xu3_defconfig
make -j$(nproc)

The resulting u-boot-dtb.bin file can then be flashed to the microSD card as described in the installation steps.

Configure and build U-Boot for your target board:

arm-trusted-firmware

Needed patch:

--- Makefile.orig       2025-05-29 05:51:27.463649004 +0000
+++ Makefile    2025-05-29 05:51:51.622579002 +0000
@@ -418,7 +418,7 @@
 # LD = gcc (used when GCC LTO is enabled)
 else ifneq ($(findstring gcc,$(notdir $(LD))),)
 # Pass ld options with Wl or Xlinker switches
-TF_LDFLAGS             +=      -Wl,--fatal-warnings -O1
+TF_LDFLAGS             +=      -O1
 TF_LDFLAGS             +=      -Wl,--gc-sections
 ifeq ($(ENABLE_LTO),1)
        ifeq (${ARCH},aarch64)
@@ -435,7 +435,7 @@

 # LD = gcc-ld (ld) or llvm-ld (ld.lld) or other
 else
-TF_LDFLAGS             +=      --fatal-warnings -O1
+TF_LDFLAGS             +=      -O1
 TF_LDFLAGS             +=      --gc-sections
 # ld.lld doesn't recognize the errata flags,
 # therefore don't add those in that case

Build:

git clone https://github.com/crust-firmware/arm-trusted-firmware/
cd arm-trusted-firmware
export CROS_COMPILE=""
export ARCH=arm64
make PLAT=sun50i_a64 -j$(nproc) bl31

arm-trusted-firmware/build/sun50i_a64/release/bl31.bin

cd u-boot
export BL31=../arm-trusted-firmware/build/sun50i_a64/release/bl31.bin
# We don't need SCP firmware so we avoid the build warning
export SCP=/dev/null
make pine64_plus_defconfig
make -j$(nproc)

u-boot-sunxi-with-spl.bin -> Integrates U-boot SPL and FIT images

7. Compile the Linux Kernel Similarly, configure and build the kernel:

cd linux-6.14.8
make sunxi_defconfig
make -j$(nproc) zImage modules sun4i-a10-cubieboard.dtb

After compilation, copy the arch/arm/boot/zImage and device tree blob arch/arm/boot/dts/sun4i-a10-cubieboard.dtb to the appropriate locations on your microSD card.

Similarly, configure and build the kernel:

cd linux-6.14.8
cp config .config
make oldconfig
make -j$(nproc) zImage dtbs modules

After compilation, copy the arch/arm/boot/zImage and device tree blob arch/arm/boot/dts/allwinner/sun7i-a20-cubieboard2.dtb to the appropriate locations on your microSD card. After compilation, copy the arch/arm/boot/zImage and device tree blob arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-pc.dtb to the appropriate locations on your microSD card.

Similarly, configure and build the kernel:

cd linux-6.14.8
cp config .config
make oldconfig
make -j$(nproc) zImage dtbs modules

After compilation, copy the arch/arm/boot/zImage and device tree blob arch/arm/boot/dts/samsung/exynos5422-odroidxu4.dtb to the appropriate locations on your microSD card.

Similarly, configure and build the kernel:

cd linux-6.14.8
cp config .config
make clean defconfig
make -j$(nproc)
make -j$(nproc) dtbs

After compilation, copy the arch/arm64/boot/Image and device tree blob arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dtb to the appropriate locations on your microSD card.

Similarly, configure and build the kernel:

git clone --depth=1 https://github.com/raspberrypi/linux
cd linux
KERNEL=kernel8
make bcm2711_defconfig
make -j$(nproc) Image.gz modules dtbs

Needed files:

Similarly, configure and build the kernel:

git clone --depth=1 https://github.com/raspberrypi/linux
cd linux
KERNEL=kernel_2712
make bcm2712_defconfig
make -j$(nproc) Image.gz modules dtbs

Needed files:

8. Modules and headers
Install modules and headers to a specific path to be packaged and distributed

make modules_install INSTALL_MOD_PATH="desired_path_to_be_compressed_and_distributed"
make headers_install INSTALL_HDR_PATH="desired_path_to_be_compressed_and_distributed"

Note:
Building in a Docker container ensures a clean, repeatable environment, and using Debian armel as the base image provides compatibility with ARM targets. This workflow is particularly effective on Apple Silicon Macs, where native ARM support in Docker streamlines cross-compilation tasks.
We cannot use the CRUX-ARM toolchain for this process because it only provides support for the hard-float ABI (arm-unknown-linux-gnueabihf), which targets systems with hardware floating-point support. Since our target requires soft-float compatibility, we rely on the Debian armel toolchain, which is specifically designed for ARM systems using the soft-float ABI. This ensures proper compatibility and functionality throughout the build process.