Skip to content

unix: support building Linux x86-64 from macOS aarch64#1056

Open
indygreg wants to merge 1 commit intomainfrom
gps-macos-linux-x86-64-cross-compile
Open

unix: support building Linux x86-64 from macOS aarch64#1056
indygreg wants to merge 1 commit intomainfrom
gps-macos-linux-x86-64-cross-compile

Conversation

@indygreg
Copy link
Copy Markdown
Collaborator

Docker on aarch64 macOS will automagically virtualize x86-64 containers if containers are spawned with platform=linux/amd64. Performance of spawned containers is a bit slower than native, but not horrible. This functionality means it is viable to develop Linux x86-64 from modern Apple hardware.

This commit teaches the build system to support cross-compiling Linux x86-64 from macOS aarch64.

Implementing this wasn't too difficult: we need to pass platform into Docker's APIs for building and creating containers. We need to teach code to resolve the effective host platform when this scenario is detected. And we need to advertise support for cross-compiling in the targets.yml file.

In case you are wondering, yes, a similar solution could be employed for Linux too by using emulation. But this requires Docker be configured to support emulation, which isn't as common. Rosetta on macOS "just works" and is therefore the lowest hanging fruit to implement.

@indygreg indygreg requested a review from geofft March 26, 2026 10:20
host_platforms:
- linux_x86_64
# Rosetta doesn't support AVX-512. So we cannot run x86-64-v4 binaries
# under Rosetta. But they can build correctly.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be moved to x86_64_v4-unknown-linux-musl

@jjhelmus
Copy link
Copy Markdown
Contributor

I tried this out locally and after building for aarch64-unknown-linux-gnu and removing the build directory a follow up build for x86_64-unknown-linux-gnu fails when building the image-gcc target.

For some reason armhf deb packages are being installed in the container and uname -a reports Linux 9ceedc289281 6.10.14-linuxkit #1 SMP Tue Oct 14 07:32:13 UTC 2025 armv7l GNU/Linux.

I think this is caused by docker-py not fully respecting the platform argument, see docker/docker-py#2990. There may be a workaround that involves removing cached images.

@indygreg
Copy link
Copy Markdown
Collaborator Author

That's a fun quirk. I'll take a look and try to concoct a workaround. I know a bit about Docker/Buildkit internals and may be able to devise something non-obvious.

@indygreg
Copy link
Copy Markdown
Collaborator Author

Yeah, I bet the code in docker buildx build handles this platform issue. Whereas the raw Docker image build API (which abstracts away the BuildKit bits) doesn't. We may want to switch to the CLI command for image building. I may do that as its own PR.

@indygreg
Copy link
Copy Markdown
Collaborator Author

Oh, I think it is sillier than that. We're adding platform when cross compiling on Linux. That forces Docker to run an image from a non-native arch, invalidating assumptions that Linux images are always for the native arch.

Docker on aarch64 macOS will automagically virtualize x86-64 containers
if containers are spawned with `platform=linux/amd64`. Performance of
spawned containers is a bit slower than native, but not horrible. This
functionality means it is viable to develop Linux x86-64 from modern
Apple hardware.

This commit teaches the build system to support cross-compiling
Linux x86-64 from macOS aarch64.

Implementing this wasn't too difficult: we need to pass `platform` into
Docker's APIs for building and creating containers. We need to teach
code to resolve the effective host platform when this scenario is
detected. And we need to advertise support for cross-compiling in the
`targets.yml` file.

In case you are wondering, yes, a similar solution could be employed for
Linux too by using emulation. But this requires Docker be configured to
support emulation, which isn't common. Rosetta on macOS "just works" and
is therefore the lowest hanging fruit to implement.
@indygreg indygreg force-pushed the gps-macos-linux-x86-64-cross-compile branch from d1fddea to affe720 Compare March 27, 2026 07:56
@jjhelmus
Copy link
Copy Markdown
Contributor

I'm still getting armhf Debian packages installed into the image-build and image-gcc containers when building with --target-triple x86_64-unknown-linux-gnu on a macOS host. I may have some armhf debian containers in my cache from debugging issues with that platform but the cache should not be effecting the platforms selection.

@indygreg
Copy link
Copy Markdown
Collaborator Author

I'm still getting armhf Debian packages installed into the image-build and image-gcc containers when building with --target-triple x86_64-unknown-linux-gnu on a macOS host. I may have some armhf debian containers in my cache from debugging issues with that platform but the cache should not be effecting the platforms selection.

Right - our build system is supposed to load the local image tags into Docker and then execute those images directly by specifying their SHA-256 digest. The only time we would be loading incorrect images is if the docker build equivalent that we're running is producing an invalid image and we're loading that.

Try removing build/image-*.tar files and see if you can reproduce?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants