Skip to content

Use the same Docker image to cross-compile Rust x86_64/ARM64 programs for Linux and macOS (osxcross).

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

joseluisq/rust-linux-darwin-builder

Repository files navigation

Rust Linux / Darwin Builder

Use the same Docker image to cross-compile Rust programs for Linux (musl libc) and macOS (osxcross)

Build Status Docker Image Version (tag latest semver) Docker Image Size (tag) Docker Image

Overview

This is a Linux Docker image based on ekidd/rust-musl-builder but using the latest Debian 12-slim (Bookworm).

It contains essential tools for cross-compile Rust projects such as Linux static binaries via musl-libc / musl-gcc (x86_64-unknown-linux-musl) and macOS binaries (x86_64-apple-darwin) via osxcross just using the same Linux image.

The Docker image is multi-arch (amd64 and arm64) so you can use them in native environments. Also, it is possible to cross-compile arm64 Linux or Darwin apps from the x86_64 Docker image variant.

Usage

Compiling an application inside a Docker container

By default, the working directory is /root/src.

x86_64 (amd64)

Below are the default toolchains included in the Docker image.

x86_64-unknown-linux-musl

docker run --rm \
    --volume "${PWD}/sample":/root/src \
    --workdir /root/src \
      joseluisq/rust-linux-darwin-builder:1.82.0 \
        sh -c "cargo build --release --target x86_64-unknown-linux-musl"

x86_64-unknown-linux-gnu

docker run --rm \
    --volume "${PWD}/sample":/root/src \
    --workdir /root/src \
      joseluisq/rust-linux-darwin-builder:1.82.0 \
        sh -c "cargo build --release --target x86_64-unknown-linux-gnu"

x86_64-apple-darwin

docker run --rm \
    --volume "${PWD}/sample":/root/src \
    --workdir /root/src \
      joseluisq/rust-linux-darwin-builder:1.82.0 \
        sh -c "cargo build --release --target x86_64-apple-darwin"

aarch64 (arm64)

aarch64-unknown-linux-gnu

docker run --rm \
    --volume "${PWD}/sample":/root/src \
    --workdir /root/src \
      joseluisq/rust-linux-darwin-builder:1.82.0 \
        sh -c "cargo build --release --target aarch64-unknown-linux-gnu"

aarch64-unknown-linux-musl

docker run --rm \
    --volume "${PWD}/sample":/root/src \
    --workdir /root/src \
      joseluisq/rust-linux-darwin-builder:1.82.0 \
        sh -c "cargo build --release --target aarch64-unknown-linux-musl"

aarch64-apple-darwin

docker run --rm \
    --volume "${PWD}/sample":/root/src \
    --workdir /root/src \
      joseluisq/rust-linux-darwin-builder:1.82.0 \
        sh -c "cargo build --release --target aarch64-apple-darwin"

Cargo Home advice

It's known that the CARGO_HOME points to $HOME/.cargo by default (/root/.cargo in this case). However, if you want to use a custom Cargo home directory then make sure to copy the Cargo config file to the particular directory like cp "$HOME/.cargo/config" "$CARGO_HOME/" before to cross-compile your program. Otherwise, you could face a linking error when for example you want to cross-compile to an x86_64-apple-darwin target.

Dockerfile

You can also use the image as a base for your Dockerfile:

FROM joseluisq/rust-linux-darwin-builder:1.82.0

OSXCross

You can also use o32-clang(++) and o64-clang(++) as a normal compiler.

Notes:

  • The current 11.3 SDK does not support i386 anymore. Use <= 10.13 SDK if you rely on i386 support.
  • The current 11.3 SDK does not support libstdc++ anymore. Use <= 10.13 SDK if you rely on libstdc++ support.

Examples:

Example usage:

Example 1: CC=o32-clang ./configure --host=i386-apple-darwin22.4
Example 2: CC=i386-apple-darwin22.4-clang ./configure --host=i386-apple-darwin22.4
Example 3: o64-clang -Wall test.c -o test
Example 4: x86_64-apple-darwin22.4-strip -x test

!!! Use aarch64-apple-darwin22.4-* instead of arm64-* when dealing with Automake !!!
!!! CC=aarch64-apple-darwin22.4-clang ./configure --host=aarch64-apple-darwin22.4 !!!
!!! CC="aarch64-apple-darwin22.4-clang -arch arm64e" ./configure --host=aarch64-apple-darwin22.4 !!!

Cross-compilation example

Below is a simple example of using a Makefile to cross-compile a Rust app.

Notes:

  • A hello world app is used.
  • A custom directory is used below as a working directory instead of /root/src.

Create a Makefile:

compile:
	@docker run --rm -it \
		-v $(PWD):/app/src \
		-w /app/src \
			joseluisq/rust-linux-darwin-builder:1.82.0 \
				make cross-compile
.PHONY: compile

cross-compile:
	@echo
	@echo "1. Cross compiling example..."
	@rustc -vV
	@echo
	@echo "2. Compiling application (linux-musl x86_64)..."
	@cargo build --manifest-path=tests/hello-world/Cargo.toml --release --target x86_64-unknown-linux-musl
	@du -sh tests/hello-world/target/x86_64-unknown-linux-musl/release/helloworld
	@echo
	@echo "3. Compiling application (apple-darwin x86_64)..."
	@cargo build --manifest-path=tests/hello-world/Cargo.toml --release --target x86_64-apple-darwin
	@du -sh tests/hello-world/target/x86_64-apple-darwin/release/helloworld
.PHONY: cross-compile

Just run the makefile compile target, then you will see two release binaries x86_64-unknown-linux-musl and x86_64-apple-darwin.

make compile
# 1. Cross compiling example...
# rustc 1.82.0 (f6e511eec 2024-10-15)
# binary: rustc
# commit-hash: f6e511eec7342f59a25f7c0534f1dbea00d01b14
# commit-date: 2024-10-15
# host: x86_64-unknown-linux-gnu
# release: 1.82.0
# LLVM version: 19.1.1

# 2. Compiling application (linux-musl x86_64)...
#     Finished release [optimized] target(s) in 0.01s
# 1.2M	tests/hello-world/target/x86_64-unknown-linux-musl/release/helloworld

# 3. Compiling application (apple-darwin x86_64)...
#     Finished release [optimized] target(s) in 0.01s
# 240K	tests/hello-world/target/x86_64-apple-darwin/release/helloworld

For more details take a look at Cross-compiling Rust from Linux to macOS by James Waples.

Macos ARM64

See joseluisq/rust-linux-darwin-builder#7

Building *-sys crates

If some of your crates require C bindings and you run into a compilation or linking error, try to use Clang for C/C++ builds.

For example to cross-compile to Macos:

CC=o64-clang \
CXX=o64-clang++ \
	cargo build --target x86_64-apple-darwin
  # Or
	cargo build --target aarch64-apple-darwin

OpenSSL release advice

Until v1.42.0 of this project, one old OpenSSL release v1.0.2 was used.
Now, since v1.43.x or greater, OpenSSL v1.1.1 (LTS) is used which is supported until 2023-09-11.
View more at https://www.openssl.org/policies/releasestrat.html.

Contributions

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in current work by you, as defined in the Apache-2.0 license, shall be dual licensed as described below, without any additional terms or conditions.

Feel free to send some Pull request or file an issue.

License

This work is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0).

© 2019-present Jose Quintana