Cross-Compiling Rust Code for Multiple Platform Executables
Overview
This article introduces how to cross-compile your Rust code. Here's the environment and code I used:
- Example code: tool-clip-json-sort, a simple Rust project that sorts and formats JSON content from the clipboard, then puts it back.
- Server environment: CentOS 7 with Docker installed
Cross-Compiling for Windows Executables
Prepare your code for cross-compilation first.
Build the Image
Create a Dockerfile with the following content:
FROM rust:latest
RUN apt update && apt upgrade -y
RUN apt install -y g++-mingw-w64-x86-64
RUN rustup target add x86_64-pc-windows-gnu
RUN rustup toolchain install stable-x86_64-pc-windows-gnu
WORKDIR /app
CMD ["cargo", "build", "--release","--target", "x86_64-pc-windows-gnu"]
This Dockerfile uses the latest Rust version as the base image. It then updates the OS and installs the g++-mingw-w64-x86-64 package. This package is a MinGW cross-compilation toolchain that can build Windows binaries on a Linux host.
Next, the Dockerfile adds a Rust target named x86_64-pc-windows-gnu using the rustup command, which is a Windows 64-bit target. Finally, the Dockerfile sets the working directory to /app and defines a default command that uses cargo to build executables for the Windows 64-bit target. In this case, cargo build uses the --target option to specify the target and the --release option to generate optimized executables.
The Docker image built with this Dockerfile will provide an environment for building Windows 64-bit executables on a Linux host.
Build
docker build . -t rust_cross_compile/windows
After building, you can see the newly built image using docker images.
Cross-Compile the Project
Navigate to your project root directory, then run:
docker run --rm -v "$(pwd)":/app rust_cross_compile/windows
Docker will run a container based on the image you just built. This container mounts the current directory to the container's working directory and cross-compiles your Rust code to generate a Windows executable.
After completion, you can find the generated .exe file in the release directory under your current directory.
Cross-Compiling for Intel-MacOS Executables
After the above steps, you'll find it's actually quite simple. MacOS is similar - just build the image.
Dockerfile
FROM rust:latest
RUN rustup target add x86_64-apple-darwin
RUN rustup toolchain install stable-x86_64-apple-darwin
WORKDIR /app
CMD ["cargo", "build","--release", "--target", "x86_64-apple-darwin"]
Build the Image
docker build . -t rust_cross_compile/intel-macos
Cross-Compile the Project
docker run --rm -v "$(pwd)":/app rust_cross_compile/intel-macos
Other Platforms
Here are additional Dockerfiles for other platforms:
armv7
FROM rust:latest
RUN apt update && apt upgrade -y
RUN apt install -y g++-arm-linux-gnueabihf libc6-dev-armhf-cross
RUN rustup target add armv7-unknown-linux-gnueabihf
RUN rustup toolchain install stable-armv7-unknown-linux-gnueabihf
WORKDIR /app
ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc CC_armv7_unknown_Linux_gnueabihf=arm-linux-gnueabihf-gcc CXX_armv7_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++
CMD ["cargo", "build","--release", "--target", "armv7-unknown-linux-gnueabihf"]
aarch64
FROM rust:latest
RUN apt update && apt upgrade -y
RUN apt install -y g++-aarch64-linux-gnu libc6-dev-arm64-cross
RUN rustup target add aarch64-unknown-linux-gnu
RUN rustup toolchain install stable-aarch64-unknown-linux-gnu
WORKDIR /app
ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++
CMD ["cargo", "build", "--release","--target", "aarch64-unknown-linux-gnu"]
You might ask - what about Linux? Since it's already a Linux system, why bother with all this? Just run cargo build --release directly!