User:Kitty/RPi3 Cross Binhost Guide

From Gentoo Wiki
Jump to:navigation Jump to:search


This guide is designed to help you with creating a local binhost for cross compiling packages to your Raspberry Pi. It assumes that you are using a Raspberry Pi 3, in 64 bit mode, with systemd. It should also prove helpful with other targets, but you will have to change a couple things here and there.

WARNING: The author(s) make no warranty or claim whatsoever that this information is correct, proper, or safe to use. It is intended only as a reference.

Binhost Setup

We assume that you already have a live copy of Gentoo installed on a PC, most likely x86_64.

Set Up Crossdev

If you haven't yet, set up a crossdev toolchain on your binhost for the target platform.[1]

root #crossdev -t aarch64-unknown-linux-gnu

Set Your Profile

On your binhost, set the profile to match the profile that you wish to use on your Raspberry Pi.[2]

root #ARCH=arm64 PORTAGE_CONFIGROOT=/usr/aarch64-unknown-linux-gnu eselect profile set default/linux/arm64/17.0/desktop/systemd

Configure make.conf

On your binhost, edit /usr/aarch64-unknown-linux-gnu/etc/portage/make.conf and copy over your CFLAGS, USE, VIDEO_CARDS, and INPUT_DEVICES lines, as well as anything else (especially USE_EXPAND variables) that might affect package selection and compilation. Do NOT remove any of the other variables that are already in this file, and do NOT directly copy the file from your Raspberry Pi.

Also, make sure that your MAKEOPTS is set correctly for efficient compiles on your binhost.

Install Qemu Userland

Optionally, you may install Qemu Userland to help facilitate the compilation of some packages which need to run native code. This will help some packages avoid cross-compile failures, and shouldn't bother anything else in your system. This requires that your kernel have CONFIG_BINFMT_MISC enabled. The setup provided here will not allow you to chroot using qemu.

Create/edit a package.use file to instruct portage to compile qemu for the target architecture.

FILE /etc/portage/package.use/qemu
app-emulation/qemu qemu_user_targets_aarch64

Compile and install the package to the binhost.

root #emerge -a app-emulation/qemu

Create a wrapper that will set the emulated CPU, and instruct qemu to the location of the linker libraries.[3]

FILE qemu-aarch64-wrapper.c
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv, char **envp) {
        char *newargv[argc + 5];

        newargv[0] = argv[0];
        newargv[1] = "-cpu";
        newargv[2] = "cortex-a53";
        newargv[3] = "-L";
        newargv[4] = "/usr/aarch64-unknown-linux-gnu";

        memcpy(&newargv[5], &argv[1], sizeof(*argv) * (argc -1));
        newargv[argc + 4] = NULL;
        return execve("/usr/bin/qemu-aarch64", newargv, envp);

Compile the wrapper.[4]

root #gcc -static -O3 -s -o qemu-aarch64-wrapper qemu-aarch64-wrapper.c

Move the wrapper into place.

root #mv qemu-aarch64-wrapper /usr/local/bin/qemu-aarch64-wrapper

Add a file to /etc/binfmt.d/ instructing aarch64 binaries to be executed with qemu.

FILE /etc/binfmt.d/qemu-aarch64.conf

Restart the systemd-binfmt service to make your changes take effect.

root #systemctl restart systemd-binfmt

Bootstrapping your Binhost

One of the hardest parts of this guide is going to be getting your binhost crossdev environment bootstrapped, and I'm not going to go into too much detail because the actual steps can vary. You're going to need a good bit of knowledge on how to resolve dependencies, and not everything is going to compile.

A good place to start would be:

root #aarch64-unknown-linux-gnu-emerge -auND @world

... and then start fixing whatever is broken. Certain packages will refuse to cross-compile. See below for more details.

Raspberry Pi Setup

Firstly, you will want to get a running install of Gentoo on your Raspberry Pi. I have personally used Sakaki-'s RPi3 Gentoo Image. You could also follow the Raspberry_Pi_3_64_bit_Install Guide here on the wiki.

Create SSH keys

For the simplest setup, using SSH to transfer the binary files would seem to be the easiest. If you want to get a little more involved, or have a little more security for your binhost, you may opt for other binary hosting options as found in the Binary_package_guide.

On your Raspberry Pi, create SSH keys for root.

root #ssh-keygen -b 4096

After this command has completed, copy the contents of /root/.ssh/ to /home/USERNAME/.ssh/authorized_keys on your binhost. The user on your binhost should be non-root, for security purposes.

Target make.conf

On your Raspberry Pi, open /etc/portage/make.conf and make sure that it contains the following two lines:

FILE /etc/portage/make.conf

Change the PORTAGE_BINHOST line, replacing USERNAME with the username you used while setting up SSH keys, and replacing BINHOSTIP with the IP address of your binhost. If a previous PORTAGE_BINHOST line exists, it should be removed.

Using Your Binhost

Presumably, after the setup is completed, you should be able to run any emerge operation on your binhost first, using aarch64-unknown-linux-gnu-emerge, and then running the same operation on your target. After computing dependencies, your target should show a vast majority of the packages as being binaries.


Many packages will simply refuse to cross-compile. Thankfully, in what would seem to be the majority of cases, only small packages are the problem.

If you have a package that will not cross-compile, either emerge it on the host with the -B option, or make a binary package from the already installed package using quickpkg PKGATOM. Then, copy the package from /usr/portage/packages/ to the matching spot in /usr/aarch64-unknown-linux-gnu/packages/ and install it using:

root #aarch64-unknown-linux-gnu-emerge -a1K PKGATOM

By default, quickpkg will restrict access permissions to the packages it builds, presumably because of security concerns in building packages from existing files. In order to facilitate easier copying of package files when using quickpkg, the following line may be added to /usr/portage/make.conf on your Raspberry Pi:

FILE /etc/portage/make.conf