build-kernel-arm64.sh and build-kernel-rpi.sh both insisted on aarch64-linux-gnu-gcc (the cross-compiler from x86), which fails on a native ARM64 build host like the Odroid runner. Detect uname -m and use the host's gcc with an empty CROSS_COMPILE on aarch64 hosts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
175 lines
5.8 KiB
Bash
Executable File
175 lines
5.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# build-kernel-rpi.sh — Build kernel for Raspberry Pi 4/5 (ARM64)
|
|
#
|
|
# Uses the official raspberrypi/linux kernel fork with bcm2711_defconfig as the
|
|
# base, overlaid with the shared container-config fragment.
|
|
#
|
|
# This is the RPi-specific build track. For generic ARM64 (UEFI / virtio /
|
|
# kernel.org mainline) see build/scripts/build-kernel-arm64.sh.
|
|
#
|
|
# Output is cached in $CACHE_DIR/custom-kernel-rpi/ and reused across builds.
|
|
#
|
|
# Requirements:
|
|
# - gcc-aarch64-linux-gnu (cross-compiler)
|
|
# - Standard kernel build deps (bc, bison, flex, etc.)
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
CACHE_DIR="${CACHE_DIR:-$PROJECT_ROOT/build/cache}"
|
|
|
|
# shellcheck source=../config/versions.env
|
|
. "$SCRIPT_DIR/../config/versions.env"
|
|
|
|
CUSTOM_KERNEL_DIR="$CACHE_DIR/custom-kernel-rpi"
|
|
CUSTOM_IMAGE="$CUSTOM_KERNEL_DIR/Image"
|
|
CUSTOM_MODULES="$CUSTOM_KERNEL_DIR/modules"
|
|
CUSTOM_DTBS="$CUSTOM_KERNEL_DIR/dtbs"
|
|
|
|
mkdir -p "$CACHE_DIR" "$CUSTOM_KERNEL_DIR"
|
|
|
|
# --- Skip if already built ---
|
|
if [ -f "$CUSTOM_IMAGE" ] && [ -d "$CUSTOM_MODULES" ]; then
|
|
echo "==> RPi kernel already built (cached)"
|
|
echo " Image: $CUSTOM_IMAGE ($(du -h "$CUSTOM_IMAGE" | cut -f1))"
|
|
exit 0
|
|
fi
|
|
|
|
# --- Toolchain selection: native on arm64 hosts, cross-compile elsewhere ---
|
|
HOST_ARCH="$(uname -m)"
|
|
if [ "$HOST_ARCH" = "aarch64" ] || [ "$HOST_ARCH" = "arm64" ]; then
|
|
if ! command -v gcc >/dev/null 2>&1; then
|
|
echo "ERROR: gcc not found"
|
|
echo "Install: apt-get install build-essential"
|
|
exit 1
|
|
fi
|
|
CROSS_COMPILE=""
|
|
echo "==> Native ARM64 build (host arch: $HOST_ARCH)"
|
|
else
|
|
if ! command -v aarch64-linux-gnu-gcc >/dev/null 2>&1; then
|
|
echo "ERROR: aarch64-linux-gnu-gcc not found"
|
|
echo "Install: apt-get install gcc-aarch64-linux-gnu"
|
|
exit 1
|
|
fi
|
|
CROSS_COMPILE="aarch64-linux-gnu-"
|
|
echo "==> Cross-building RPi kernel from $HOST_ARCH"
|
|
fi
|
|
|
|
echo "==> Building RPi kernel (raspberrypi/linux)..."
|
|
echo " Branch: $RPI_KERNEL_BRANCH"
|
|
echo " Repo: $RPI_KERNEL_REPO"
|
|
|
|
# --- Download kernel source ---
|
|
KERNEL_SRC_DIR="$CACHE_DIR/rpi-linux-${RPI_KERNEL_BRANCH}"
|
|
if [ ! -d "$KERNEL_SRC_DIR" ]; then
|
|
echo "==> Downloading RPi kernel source (shallow clone)..."
|
|
git clone --depth 1 --branch "$RPI_KERNEL_BRANCH" \
|
|
"$RPI_KERNEL_REPO" "$KERNEL_SRC_DIR"
|
|
else
|
|
echo "==> Kernel source already cached"
|
|
fi
|
|
|
|
# --- Build in /tmp for case-sensitivity ---
|
|
KERNEL_BUILD_DIR="/tmp/kernel-build-arm64"
|
|
rm -rf "$KERNEL_BUILD_DIR"
|
|
cp -a "$KERNEL_SRC_DIR" "$KERNEL_BUILD_DIR"
|
|
|
|
cd "$KERNEL_BUILD_DIR"
|
|
|
|
# --- Apply base config (Pi 4 = bcm2711) ---
|
|
echo "==> Applying bcm2711_defconfig..."
|
|
make ARCH=arm64 CROSS_COMPILE="$CROSS_COMPILE" bcm2711_defconfig
|
|
|
|
# --- Apply container config overrides ---
|
|
CONFIG_FRAGMENT="$PROJECT_ROOT/build/config/kernel-container.fragment"
|
|
if [ -f "$CONFIG_FRAGMENT" ]; then
|
|
echo "==> Applying KubeSolo config overrides..."
|
|
while IFS= read -r line; do
|
|
# Skip comments and empty lines
|
|
case "$line" in \#*|"") continue ;; esac
|
|
key="${line%%=*}"
|
|
value="${line#*=}"
|
|
case "$value" in
|
|
y) ./scripts/config --enable "$key" ;;
|
|
m) ./scripts/config --module "$key" ;;
|
|
n) ./scripts/config --disable "${key#CONFIG_}" ;;
|
|
*) ./scripts/config --set-str "$key" "$value" ;;
|
|
esac
|
|
done < "$CONFIG_FRAGMENT"
|
|
fi
|
|
|
|
# Handle "is not set" comments as disables
|
|
if [ -f "$CONFIG_FRAGMENT" ]; then
|
|
while IFS= read -r line; do
|
|
case "$line" in
|
|
"# CONFIG_"*" is not set")
|
|
key=$(echo "$line" | sed -n 's/^# \(CONFIG_[A-Z_]*\) is not set$/\1/p')
|
|
[ -n "$key" ] && ./scripts/config --disable "${key#CONFIG_}"
|
|
;;
|
|
esac
|
|
done < "$CONFIG_FRAGMENT"
|
|
fi
|
|
|
|
# Resolve dependencies
|
|
make ARCH=arm64 CROSS_COMPILE="$CROSS_COMPILE" olddefconfig
|
|
|
|
# --- Build kernel + modules + DTBs ---
|
|
NPROC=$(nproc 2>/dev/null || echo 4)
|
|
echo ""
|
|
echo "==> Building RPi kernel (${NPROC} parallel jobs)..."
|
|
echo " This may take 20-30 minutes..."
|
|
|
|
make ARCH=arm64 CROSS_COMPILE="$CROSS_COMPILE" -j"$NPROC" Image modules dtbs 2>&1
|
|
|
|
echo "==> RPi kernel build complete"
|
|
|
|
# --- Install to staging ---
|
|
echo "==> Installing Image..."
|
|
cp arch/arm64/boot/Image "$CUSTOM_IMAGE"
|
|
|
|
echo "==> Installing modules (stripped)..."
|
|
rm -rf "$CUSTOM_MODULES"
|
|
mkdir -p "$CUSTOM_MODULES"
|
|
make ARCH=arm64 CROSS_COMPILE="$CROSS_COMPILE" \
|
|
INSTALL_MOD_STRIP=1 modules_install INSTALL_MOD_PATH="$CUSTOM_MODULES"
|
|
|
|
# Remove build/source symlinks
|
|
KVER=$(ls "$CUSTOM_MODULES/lib/modules/" | head -1)
|
|
rm -f "$CUSTOM_MODULES/lib/modules/$KVER/build"
|
|
rm -f "$CUSTOM_MODULES/lib/modules/$KVER/source"
|
|
|
|
# Run depmod
|
|
depmod -a -b "$CUSTOM_MODULES" "$KVER" 2>/dev/null || true
|
|
|
|
echo "==> Installing Device Tree Blobs..."
|
|
rm -rf "$CUSTOM_DTBS"
|
|
mkdir -p "$CUSTOM_DTBS/overlays"
|
|
# Pi 4 DTBs
|
|
cp arch/arm64/boot/dts/broadcom/bcm2711*.dtb "$CUSTOM_DTBS/" 2>/dev/null || true
|
|
# Pi 5 DTBs
|
|
cp arch/arm64/boot/dts/broadcom/bcm2712*.dtb "$CUSTOM_DTBS/" 2>/dev/null || true
|
|
# Overlays we need
|
|
for overlay in disable-wifi disable-bt; do
|
|
[ -f "arch/arm64/boot/dts/overlays/${overlay}.dtbo" ] && \
|
|
cp "arch/arm64/boot/dts/overlays/${overlay}.dtbo" "$CUSTOM_DTBS/overlays/"
|
|
done
|
|
|
|
# Save config for reference
|
|
cp .config "$CUSTOM_KERNEL_DIR/.config"
|
|
|
|
# --- Clean up ---
|
|
echo "==> Cleaning kernel build directory..."
|
|
cd /
|
|
rm -rf "$KERNEL_BUILD_DIR"
|
|
|
|
# --- Summary ---
|
|
echo ""
|
|
echo "==> RPi kernel build complete:"
|
|
echo " Image: $CUSTOM_IMAGE ($(du -h "$CUSTOM_IMAGE" | cut -f1))"
|
|
echo " Kernel ver: $KVER"
|
|
MOD_COUNT=$(find "$CUSTOM_MODULES/lib/modules/$KVER" -name '*.ko*' 2>/dev/null | wc -l)
|
|
echo " Modules: $MOD_COUNT"
|
|
echo " Modules size: $(du -sh "$CUSTOM_MODULES/lib/modules/$KVER" 2>/dev/null | cut -f1)"
|
|
echo " DTBs: $(ls "$CUSTOM_DTBS"/*.dtb 2>/dev/null | wc -l)"
|
|
echo ""
|