Gentoo rpi - hpaluch/hpaluch.github.io GitHub Wiki

Gentoo on Raspberry PI

My target: Raspberry PI 1.b

[!WARNING]

I did not deployed results on real hardware - so far only tested chroot using "QEMU User ARM" emulation.

There are actually 3 ways how to run and build Gentoo on Raspberry PI:

  1. Run builds natively on RPi
  2. Use chroot with qemu-user-arm (QEMU that will emulate ARM for running ELF binaries using binfmt-misc kernel support. It is similar approach as for legendary Nokia "scratchbox" (remains are on scratchbox.org). But not complete (scratchbox actually runs native cross gcc for amd64/i386 to get decent compiler speed).
  3. Crossdev package - crossbuilding ARM on amd64 Host machine to directory under /usr/ARM_ARCH_NAME - fastest.

Variant 1 is theoretically most reliable but prohibitively slow and also today quite impossible because current compilers require excessive amount of memory (my RPi 1.b has only 512MB RAM - even reduced when GPU is used and 1 core at 700 MHz). So basically any C++ project with enabled LTO (Link time optimizations) will exhaust all memory. Without LTO it could be barely better (older compilers optimized code on single module boundary only so it was not that memory hungry as LTO). Also SD card with its very slow I/O speed will not help.

Variant 2 is moderately slow but convenient (because some packages have issues with cross-building). But some sandboxes must be disabled in /etc/portage/make.conf to make qemu work properly. See https://wiki.gentoo.org/wiki/Embedded_Handbook/General/Compiling_with_QEMU_user_chroot#Portage_configuration

Variant 3 is fastest (because compiler runs at native Host speeds) but most tricky - not all packages can be cross-build without issues (GNU Autoconf is very hostile to that - because it compiles and runs C program - where later is not possible on cross-compilation) - for example Glib with Introspection.

Setup

You should always start on https://wiki.gentoo.org/wiki/Raspberry_Pi/Installation to find what ARM version you have. In my case (RPi 1.B) it is armv6j-unknown-linux-gnueabihf. (hf means "hard-float" - that such ARM CPU has hardware support for floating-point math).

Originally I tried QEMU User Chroot setup which is described on:

But I found it very slow (configure script and/or Python is terribly slow under qemu-arm (user)).

So I'm now testing variant 3:

# running on amd 64 Host:
emerge --ask sys-devel/crossdev
emerge -an app-eselect/eselect-repository
# `crossdev` here is automatically selected as default cross-build repo:
eselect repository create crossdev
# command below will take lot of time
crossdev -S -t armv6j-unknown-linux-gnueabihf
# I already downloaded stage3 tarball:
tar xpvf /mnt/gentoo-rpi/stage3-armv6j_hardfp-openrc-20250312T233353Z.tar.xz -C /usr/armv6j-unknown-linux-gnueabihf  --exclude=dev --skip-old-files

Basic benchmark - building app-editor/vim:

  • command: armv6j-unknown-linux-gnueabihf-emerge -an app-editor/vim
  • QEMU user chroot: 18 minutes (despite 5 parallel jobs, 6 host cores).
  • crossdev: 1.5 minute (!)

Testing Cross-dev chroot:

  • first you must copy QEMU user for arm in my case:
    # qemu-arm must be in same direcctory in chroot as in main system so binfmt-misc will work:
    cp /usr/bin/qemu-arm /usr/armv6j-unknown-linux-gnueabihf/usr/bin/qemu-arm
    
  • small fix:
    mkdir -p /usr/armv6j-unknown-linux-gnueabihf/dev
    
  • script /usr/armv6j-unknown-linux-gnueabihf/bind_mounts.sh contains:
    #!/bin/bash
    set -xeuo pipefail
    cd $(dirname $0)
    
    for i in dev sys proc
    do
            [ -d "$i" ] || {
                    echo "Fatal error: '$i' missing at `pwd`" >&2
                    exit 1
            }
            mount -B /$i $i
    done
    exit 0
    
  • script /usr/armv6j-unknown-linux-gnueabihf/enter-chroot.sh contains:
    #!/bin/bash
    set -xeuo pipefail
    cd $(dirname $0)
    chroot . /bin/bash
    exit 0
    
  • and finally script /usr/armv6j-unknown-linux-gnueabihf/init_shell.sh contains
    source /etc/profile
    export PS1="(AZ CROSS-RPI) ${PS1}"
    

Usage:

  • after boot once and only once run: /usr/armv6j-unknown-linux-gnueabihf/bind_mounts.sh
  • now every time you want to enter emulated ARM chroot, run:
    /usr/armv6j-unknown-linux-gnueabihf/enter-chroot.sh
    
  • inside chroot run:
    source /init_shell.sh
    
  • and try:
    $ uname -m
    
    armv7l
    
  • remember - to quickly crossbuild anything, run on Host (outside chroot!):
    armv6j-unknown-linux-gnueabihf-emerge -an PACKAGE_NAME
    

Bugs

Need to also cross-build kernel!

armv6j-unknown-linux-gnueabihf-emerge -an app-misc/mc

* Unable to find kernel sources at /usr/armv6j-unknown-linux-gnueabihf/usr/src/linux
 * Unable to calculate Linux Kernel version for build, attempting to use running version
 * Unable to check for the following kernel config options due
 * to absence of any configured kernel sources or compiled
 * config:
 *  - INOTIFY_USER
 * You're on your own to make sure they are set if needed.
 * ERROR: dev-libs/glib-2.84.0::gentoo failed (configure phase):
                                                         *   configure failed

Trying:

# On Host:
armv6j-unknown-linux-gnueabihf-emerge -an sys-kernel/raspberrypi-sources
# Now dirty trick!
cd /usr/armv6j-unknown-linux-gnueabihf/usr/src/linux-6.6.47_p20240902-raspberrypi
# creates config from template
CROSS_COMPILE=armv6j-unknown-linux-gnueabihf- ARCH=arm make bcmrpi_defconfig
# builds kernel
CROSS_COMPILE=armv6j-unknown-linux-gnueabihf- ARCH=arm make -j`nproc`
# still on Host - be carefull
CROSS_COMPILE=armv6j-unknown-linux-gnueabihf- ARCH=arm \
   make install INSTALL_PATH=/usr/armv6j-unknown-linux-gnueabihf/boot \
                INSTALL_MOD_PATH=/usr/armv6j-unknown-linux-gnueabihf

CROSS_COMPILE=armv6j-unknown-linux-gnueabihf- ARCH=arm \
   make modules_install INSTALL_PATH=/usr/armv6j-unknown-linux-gnueabihf/boot \
                        INSTALL_MOD_PATH=/usr/armv6j-unknown-linux-gnueabihf

Under chroot create symlink:

# in chroot
$ eselect kernel list

vailable kernel symlink targets:
  [1]   linux-6.6.47_p20240902-raspberrypi

$ eselect kernel set 1

Trying again on host:

armv6j-unknown-linux-gnueabihf-emerge -an app-misc/mc

Errrr

ERROR: An exe_wrapper is needed for /usr/armv6j-unknown-linux-gnueabihf/tmp/portage/dev-libs/glib-2.84.0/work/gobject-in
trospection-1.82.0-build/tools/g-ir-compiler but was not found. Please define one in cross file and check the command an
d/or add it to PATH.

As workaround must disable introspection (it is hostile to cross-builds) for glib:

USE=-introspection armv6j-unknown-linux-gnueabihf-emerge -an app-misc/mc

Yeah! That did the trick... Now you can try in chroot mc command if it works.

FIXME

I should use QEMU exec wrapper to emulate armv6j (as is on RPi 1b), because default is armv7l which may cause troubles.