Published: | |
Tags: | clang llvm |
Cross compiling for different architectures and linux distributions is actually not half as hard as it is made out to be. I know many that regard cross compilation as too difficult and error prone to be even considered and thus always require an entire setup for the target architecture. But handling virtual machines can be cumbersome and juggling real hardware even more. Worry not tho, i will teach you an easy yet versitile way to achieve cross compilation
If you are like me and added some custom goodies to your C compiler of choice clang
but want to target multiple architectures, let’s say x86_64
and aarch64
, you really have only two options. You either
dare to cross compile with your custom compiler, or you build clang with your addition on a seperate system for each target
architecture. The second option quickly becomes cumbersome so lets take a look at the former one.
Cross compilation has two prerequists:
- you need to use
lld
from the llvm-project - You need to have a copy of the target root filesystem for includes and libraries
If you are using a standard clang installation you either already have lld as well or you can obtain it the same way as clang.
If you build clang yourself you just need to also enable the lld project during cmake configuration (-DLLVM_ENABLE_PROJECTS="lld;clang"
).
Obtaining a root file system is just a little bit trickier. In the simplest case you can directly mount that of your target device e.g. via sshfs.
If that is not possible or desirable you can possibly create one using debootstrap and QEMU User Emulation.
sudo debootstrap --arch arm64 --foreign bullseye bullseye-arm64 http://ftp.debian.org/debian
sudo cp /usr/bin/qemu-aarch64-static bullseye-arm64/bin
sudo chroot bullseye-arm64
debootstrap/debootstrap --second-stage
now you need to install all required libraries by simply using the debian package manager. To build lua for example we need to install the readline library
apt update
apt upgrade
apt install libreadline-dev
and finally all there is left to do is tell the toolchain to use clang, a different sysroot, and the lld linker.
The most difficult part here is to get the target right as it is automatically used to locate includes and libraries.
The best way to get it is to just list the /lib
directory and take the entry already looking like a target.
Putting it all together it looks like this for lua:
git clone -b v5.4.6 --depth 1 https://github.com/lua/lua.git
cd lua
make CC=clang \
CFLAGS="-O2 --target=aarch64-linux-gnu --sysroot=${HOME}/crosscompile/bullseye-arm64" \
MYLDFLAGS="--target=aarch64-linux-gnu --sysroot=${HOME}/crosscompile/bullseye-arm64 -fuse-ld=lld"
Have fun with your freshly cross compiled libraries and binaries.