Linaro Toolchain For The Pi (Defunct)

Important

This article is defunct; check out Building A Cross Toolchain For The Raspberry Pi, Using crosstool-ng instead!

Reason: C++ is much more involved, and libstdc++ itself (as from Linaro) depends on a specific glibc version. The Raspberry situation sure does not meet these requirements.

Toolchains are always a pain in the butt. Here’s a writeup (as of 2022-03-29) of something that I found workable.

  • It is not clean. The sysroot is not usually copied over from the existing target.

  • By no way it gives insight into the black art of toolchain-making.

  • I have no idea why the Linaro toolchain works for our sysroot, and Fedora’s gcc-arm-linux-gnu doesn’t.

Download And Unpack Linaro Toolchain

  • Download tarball (I chose the lastest). Be sure to pick the one that runs on x86_64, not the aarch64 one.

    $ wget -o ~/Downloads/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf.tar.xz \
         https://snapshots.linaro.org/gnu-toolchain/12.0-2022.02-1/arm-linux-gnueabihf/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf.tar.xz
    
  • Unpack into ~/cross/toolchains

    $ mkdir -p ~/cross/toolchains
    $ tar -C ~/cross/toolchains -J -x -f ~/Downloads/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf.tar.xz
    

Create a sysroot

Lacking a precomposed sysroot that only contains what we need, we copy over a minimal set of artifacts from the target. By trial and error we can come up with the following remote directories that we copy into the host’s sysroot,

  • /usr/lib/arm-linux-gnueabihf

  • /usr/lib/gcc/arm-linux-gnueabihf

  • /usr/include

  • /lib/arm-linux-gnueabihf

We use SSH remote command execution in a pipe to

  • Create a tar archive containing these directories, remotely

  • Compress that archive onto the wire, remotely

  • Uncompress from the wire, locally

  • Unpack that, locally, into a directory of our choice. Lets use ~/cross/ to keep things in order.

$ mkdir -p ~/cross/sysroots/raspberry
$ ssh  me@target 'tar -c -f - /usr/lib/arm-linux-gnueabihf /usr/lib/gcc/arm-linux-gnueabihf /usr/include /lib/arm-linux-gnueabihf | xz --compress' | \
     xz --decompress | \
     tar -C ~/cross/sysroots/raspberry -x -f -
tar: Removing leading `/' from member names
tar: Removing leading `/' from hard link targets

Test Cross Build

What We Have

  • The target’s libraries and header files in ~/cross/sysroots/raspberry/,

    $ ls -l ~/cross/sysroots/raspberry/
    total 0
    drwxrwxr-x. 1 jfasch jfasch 38 Mar 29 19:00 lib
    drwxrwxr-x. 1 jfasch jfasch 20 Mar 29 18:59 usr
    
  • The cross toolchain in ~/cross/toolchains/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf/

    $ ls -l ~/cross/toolchains/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf/
    total 12
    drwxr-xr-x. 1 jfasch jfasch    40 Feb  5 23:47 arm-linux-gnueabihf
    drwxr-xr-x. 1 jfasch jfasch  1706 Feb  5 23:54 bin
    -rw-r--r--. 1 jfasch jfasch 10552 Feb  5 23:53 gcc-linaro-12.0.1-2022.02-linux-manifest.txt
    drwxr-xr-x. 1 jfasch jfasch    72 Feb  5 23:49 include
    drwxr-xr-x. 1 jfasch jfasch   168 Feb  5 23:54 lib
    drwxr-xr-x. 1 jfasch jfasch     6 Feb  5 23:32 libexec
    drwxr-xr-x. 1 jfasch jfasch    58 Feb  5 23:49 share
    

    It’s the bin/ subdirectory that contains the compiler, gcc, and the other toolchain programs. All properly prefixed with arm-linux-gnueabihf- to distinguish them from toolchains for other architectures.

    $ ls -l ~/cross/toolchains/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf/bin/
    total 73812
    ...
    -rwxr-xr-x. 1 jfasch jfasch  1107168 Feb  5 23:54 arm-linux-gnueabihf-ar
    -rwxr-xr-x. 1 jfasch jfasch  1481768 Feb  5 23:54 arm-linux-gnueabihf-gcc
    -rwxr-xr-x. 1 jfasch jfasch  1968456 Feb  5 23:54 arm-linux-gnueabihf-ld
    -rwxr-xr-x. 1 jfasch jfasch  1091864 Feb  5 23:54 arm-linux-gnueabihf-nm
    -rwxr-xr-x. 1 jfasch jfasch  1030432 Feb  5 23:54 arm-linux-gnueabihf-readelf
    -rwxr-xr-x. 1 jfasch jfasch  1221816 Feb  5 23:54 arm-linux-gnueabihf-strip
    ...
    

Use Cross Compiler To Build Against sysroot

#include <stdio.h>

int main(void)
{
    printf("Hello World\n");
    return 0;
}

Run our cross compiler to compile and link that source code, against the Raspberry situation that we have. This is where it all comes together.

$ ~/cross/toolchains/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc \
       --sysroot ~/cross/sysroots/raspberry \
       -o hello-single hello-single.c

Copy the executable over, and run it,

$ scp hello-single jfasch@target:
$ ssh jfasch@target ./hello-single
Hello World

Voila! It works for the simplest case.

Adjust $PATH To Point To Toolchain

Add toolchain’s program directory to your $PATH environment variable (you might want to add it to your ~/.bashrc file, and re-source that),

$ PATH=/home/jfasch/cross/toolchains/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf/bin:$PATH
$ export PATH

With this, you are now to just say,

$ arm-linux-gnueabihf-gcc --sysroot ~/cross/sysroots/raspberry -o hello-single hello-single.c