Cross Compilation for Raspberry Pi 4B

Dear all,
I have a small C and a small Haskell project for my Raspberry Pi 4 B. The Raspberry runs the NixOS AArch64 image. Now I would like to cross-compile from my x86_64 desktop, also running NixOS. Compiling works fine, both natively and when cross-compiling, both with GCC or CLang for the C program and with GHC and Haskell.nix overlay for Haskell. I tried nixpkgs.pkgsCross.aarch64-multiplatform as well as pkgs.pkgsCross.raspberryPi for cross-compilation but the binaries fail to run with no such file or directory. I guess the problem is the dynamic library loader?

# From nix-shell -p gcc on the Raspberry
$ cat $NIX_CC/nix-support/dynamic-linker
/nix/store/4pc5akylpxdi0azn6mcqcg0qaj4wz88r-glibc-2.32-10/lib/ld-linux-aarch64.so.1

# The cross compiled binary on the Raspberry
$ patchelf --print-interpreter $CROSS_EXE 
/nix/store/iqn7226k4w31g93hd9hjxxazdpfq5j8x-glibc-2.31-aarch64-unknown-linux-gnu/lib/ld-linux-aarch64.so.1

$ patchelf --print-needed $CROSS_EXE 
librt.so.1
libutil.so.1
libdl.so.2
libpthread.so.0
libgmp.so.10
libc.so.6
ld-linux-aarch64.so.1
libm.so.6
libffi.so.7
libnuma.so.1

So what is the proper way to cross compile for the Raspberry Pi 4 and is there a way to ensure that all the libraries are installed on the target machine?

And a question out of interest: if it should run on lets say Raspberry Pi OS with totally different paths, would I simply use patchelf to set the RPATH and interpreter to their locations on Raspberry Pi OS?

Thanks in advance
Phillip

Are you copying the single cross-compiled binary over? As you noticed, that won’t copy any required libraries over. Instead, use nix-copy-closure, which handles all that: nix-copy-closure [hostname of the pi] /nix/store/whatever.

As for running on Raspberry Pi OS, there are a few options:

  • Install Nix (not NixOS) on Raspberry Pi OS, and do the same nix-copy-closure thing. Nix shouldn’t interfere with anything else, and your cross-compiled program will use libraries from /nix/store instead of relying on Raspberry Pi OS (which could be a good or a bad thing)
  • Use something like nix-bundle, which packages a program, and everything it depends on in /nix/store, into one binary that can run anywhere. (Internally, it sets up something like a chroot with a /nix/store embedded in the binary.) Like the above, this’ll use its own binaries, not Raspberry Pi OS’s, but you won’t need Nix installed.
  • Do what you suggested, with patchelf. I imagine this could work, but I’m not aware anyone’s tried it.
1 Like

nix-copy-closure is exactly what I needed, thanks :slight_smile: