How to Cross-Compile Rust for Windows from Linux — Rust FAQ
How to Cross-Compile Rust for Windows from Linux
Cargo
2026-04-17T14:12:14+00:00
Add the Windows target with rustup and build your Rust project using the --target flag to generate a Windows executable from Linux.
Standard
In Simple Terms
You need a Windows binary. You are on Linux. You do not need a Windows machine.
You are coding on your favorite Linux distribution. The terminal is fast, the package manager is reliable, and your workflow is smooth. A request arrives: "Can you send me the Windows build?" or "The CI pipeline needs to produce an .exe." You do not have a Windows laptop. You do not want to dual-boot. You just want to produce a binary that runs on Windows from your Linux environment.
Rust handles this natively. The compiler does not care what operating system you run it on. It only cares about what operating system the output binary will run on. This separation of host and target is built into the toolchain. You can compile for Windows, macOS, ARM, WebAssembly, or embedded microcontrollers from a single Linux machine. The process is deterministic and repeatable.
Host, target, and the target triple
Rust distinguishes between the host and the target. The host is the machine running the compiler. The target is the platform where the resulting binary will execute. When you compile, you tell rustc which target to emit.
The target is specified as a "triple" string. This string encodes the architecture, the vendor, the operating system, and the ABI (Application Binary Interface). For Windows on 64-bit x86, you will see two common triples:
x86_64-pc-windows-gnu
x86_64-pc-windows-msvc
The first part x86_64 is the architecture. pc is the vendor (historically Intel/PC). windows is the OS. The final part is the ABI. gnu means the binary uses the MinGW toolchain conventions. msvc means it uses the Microsoft Visual C++ conventions.
Think of the compiler as a factory built on Linux soil. The factory has interchangeable molds for the product output. You can swap the mold to produce a widget that fits into a Windows machine. The factory adjusts the file format, the calling conventions, and the headers. The result is a binary that Windows understands, even though it was forged on Linux.
Minimal setup
You need two steps to cross-compile. First, install the target standard library. Second, build with the target flag.
# Install the Windows target standard library.<br># This downloads rust-std for the target, not the compiler.<br>rustup target add x86_64-pc-windows-gnu
# Build the project for Windows.<br># The --target flag tells cargo to emit a Windows binary.<br>cargo build --target x86_64-pc-windows-gnu --release
The build output lands in target/x86_64-pc-windows-gnu/release/. You will find a .exe file there. This file is a PE/COFF executable, the standard format for Windows. It will not run on Linux. It will run on Windows.
Convention aside: The community convention is to use cargo build --target explicitly. Some developers set environment variables like CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER to customize the linker, but the flag is the standard way to invoke cross-compilation. Stick to the flag for clarity.
What happens under the hood
When you run rustup target add, rustup downloads the rust-std component for that target. This is the standard library pre-compiled for Windows. It contains the core crates, the allocator, and the platform-specific implementations. You do not need to compile the standard library from source. The download is fast and cached.
When you run cargo build --target, cargo invokes rustc with the --target argument. rustc switches its code generation mode. It emits PE/COFF object files instead of ELF files. It adjusts the calling conventions to match the Windows ABI. It links against the Windows standard library.
For the gnu target, rustc invokes the MinGW linker. This linker knows how to produce Windows binaries on Linux. It stitches the object files together and produces the final .exe. If you are missing the MinGW linker, the build fails with a linker error.
Trust the toolchain. rustup and cargo handle the plumbing. Your job is to pick the right target and ensure the dependencies support it.
The GNU versus MSVC divide
This is where cross-compilation gets tricky. The two Windows targets are not interchangeable. They use different ABIs and different C runtimes.
The x86_64-pc-windows-gnu target uses MinGW. MinGW is a collection of GNU tools that produce Windows binaries. It is available on Linux via package managers. The resulting binary links dynamically to msvcrt.dll by default. This is the standard C runtime on Windows. The binary runs on any modern Windows system.
The x86_64-pc-windows-msvc target uses the MSVC ABI. This is the ABI used by Visual Studio. It requires the MSVC linker and libraries. On Linux, this is difficult. You need a cross-compiler that emits MSVC-compatible binaries. Such tools are rare...