1# Cross Compiling
2
3When contributing to Wasmtime and Cranelift you may run into issues that only
4reproduce on a different architecture from your development machine. Luckily,
5`cargo` makes cross compilation and running tests under [QEMU] pretty easy.
6
7[QEMU]: https://www.qemu.org/
8
9This guide will assume you are on an x86-64 with Ubuntu/Debian as your OS. The
10basic approach (with commands, paths, and package names appropriately tweaked)
11applies to other Linux distributions as well.
12
13On Windows you can install build tools for AArch64 Windows, but targeting
14platforms like Linux or macOS is not easy. While toolchains exist for targeting
15non-Windows platforms you'll have to hunt yourself to find the right one.
16
17On macOS you can install, through Xcode, toolchains for iOS but the main
18`x86_64-apple-darwin` is really the only easy target to install. You'll need to
19hunt for toolchains if you want to compile for Linux or Windows.
20
21## Install Rust Targets
22
23First, use `rustup` to install Rust targets for the other architectures that
24Wasmtime and Cranelift support:
25
26```console
27rustup target add \
28    s390x-unknown-linux-gnu \
29    riscv64gc-unknown-linux-gnu \
30    aarch64-unknown-linux-gnu
31```
32
33## Install GCC Cross-Compilation Toolchains
34
35Next, you'll need to install a `gcc` for each cross-compilation target to serve
36as a linker for `rustc`.
37
38```console
39sudo apt install \
40    gcc-s390x-linux-gnu \
41    gcc-riscv64-linux-gnu \
42    gcc-aarch64-linux-gnu
43```
44
45## Install `qemu`
46
47You will also need to install `qemu` to emulate the cross-compilation targets.
48
49```console
50sudo apt install qemu-user
51```
52
53## Configure Cargo
54
55The final bit to get out of the way is to configure `cargo` to use the
56appropriate `gcc` and `qemu` when cross-compiling and running tests for other
57architectures.
58
59Add this to `.cargo/config.toml` in the Wasmtime repository (or create that file
60if none already exists).
61
62```toml
63[target.aarch64-unknown-linux-gnu]
64linker = "aarch64-linux-gnu-gcc"
65runner = "qemu-aarch64 -L /usr/aarch64-linux-gnu -E LD_LIBRARY_PATH=/usr/aarch64-linux-gnu/lib -E WASMTIME_TEST_NO_HOG_MEMORY=1"
66
67[target.riscv64gc-unknown-linux-gnu]
68linker = "riscv64-linux-gnu-gcc"
69runner = "qemu-riscv64 -L /usr/riscv64-linux-gnu -E LD_LIBRARY_PATH=/usr/riscv64-linux-gnu/lib -E WASMTIME_TEST_NO_HOG_MEMORY=1"
70
71[target.s390x-unknown-linux-gnu]
72linker = "s390x-linux-gnu-gcc"
73runner = "qemu-s390x -L /usr/s390x-linux-gnu -E LD_LIBRARY_PATH=/usr/s390x-linux-gnu/lib -E WASMTIME_TEST_NO_HOG_MEMORY=1"
74```
75
76## Cross-Compile Tests and Run Them!
77
78Now you can use `cargo build`, `cargo run`, and `cargo test` as you normally
79would for any crate inside the Wasmtime repository, just add the appropriate
80`--target` flag!
81
82A few examples:
83
84* Build the `wasmtime` binary for `aarch64`:
85
86  ```console
87  cargo build --target aarch64-unknown-linux-gnu
88  ```
89
90* Run the tests under `riscv` emulation:
91
92  ```console
93  cargo test --target riscv64gc-unknown-linux-gnu
94  ```
95
96* Run the `wasmtime` binary under `s390x` emulation:
97
98  ```console
99  cargo run --target s390x-unknown-linux-gnu -- compile example.wasm
100  ```
101