Cross compiling native binaries is easier than ever, thanks to docker and its --platform flag.
To cross compile a binary for a different OS and CPU architecture, using Docker, follow these simple steps:
1) Finding the right docker image
Since each docker image is built against a specific CPU architecture, the first step is to find a docker image that combines both the OS and CPU architecture you want to cross compile for.
You can see the CPU architecture an image was built for on Docker Hub by scanning the "OS/ARCH" column:
The most popular docker images tend to offer multiple builds, each targeting a different CPU architecture. The following shows the latest tag of
ubuntu. As you can see, it offers builds for multiple CPU architectures:
Let's assume we want to build an ImageMagick binary for Ubuntu (ARM64) on our MacBook (x86, aka AMD64). Since the above shows
linux/arm64/v8, we're ready to move on to step 2!
2) Running the docker image
docker run will pick the image that matches your host machine's CPU architecture. This is for performance reasons, since the emulation adds overhead.
We can see docker picking the x86 image by default:
$ docker run ubuntu uname -p x86_64
To force docker into selecting (and emulating the hardware for) the ARM64 version of the
ubuntu image, we simply add the
$ docker run --platform linux/arm64/v8 ubuntu uname -p aarch64
Excellent! We can now boot-up an Ubuntu ARM64 machine to build our native binaries on!
3) Building your native binaries
The rest is easy: just compile your binaries inside the docker container we launched above. Remember: the
--platform flag is crucial! (You can always run
uname -p inside your container to make sure you are really being emulated.)
Be warned: CPU architecture emulation adds significant overhead. In our experience, compile times can take up to 5x longer when emulating via the
--platformtag. Maybe go grab a coffee after starting