From 54a290cd53a143d4da0c28b5ea98bab47b5d0fc8 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Wed, 16 Nov 2022 15:49:09 -0800 Subject: [PATCH] Docs: Expand cross compiling section into its own page (#5284) And fill out everything needed for all non-x64 targets supported by Wasmtime and Cranelift. --- docs/SUMMARY.md | 1 + docs/contributing-building.md | 112 --------------------------- docs/contributing-cross-compiling.md | 100 ++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 112 deletions(-) create mode 100644 docs/contributing-cross-compiling.md diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index c13b911b72..e1f68cfac7 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -55,6 +55,7 @@ - [Testing](./contributing-testing.md) - [Fuzzing](./contributing-fuzzing.md) - [CI](./contributing-ci.md) + - [Cross Compiling](./contributing-cross-compiling.md) - [Coding Guidelines](./contributing-coding-guidelines.md) - [Development Process](./contributing-development-process.md) - [Release Process](./contributing-release-process.md) diff --git a/docs/contributing-building.md b/docs/contributing-building.md index ac5460c5d3..fcbb281c89 100644 --- a/docs/contributing-building.md +++ b/docs/contributing-building.md @@ -82,115 +82,3 @@ there, without needing to supply the `-p` flag: cd crates/jit/ cargo build ``` - -## Cross Compiling Wasmtime - -By default `cargo build` will build Wasmtime for the platform you're running the -build on. You might, however, want to build Wasmtime for a different platform! -Let's say for example that you want to build Wasmtime for -`aarch64-unknown-linux-gnu`. First you'll want to acquire the Rust standard -library for this target: - -```shell -rustup target add aarch64-unknown-linux-gnu -``` - -Next you need to install a native C toolchain which has a C compiler, runtime -libraries, and linker for the desired target. This is unfortunately not very -easy to acquire on most platforms: - -* On Windows you can install build tools for AArch64 Windows, but targeting - platforms like Linux or macOS is not easy. While toolchains exist for - targeting non-Windows platforms you'll have to hunt yourself to find the right - one. - -* On macOS you can install, through Xcode, toolchains for iOS but the main - `x86_64-apple-darwin` is really the only easy target to install. You'll need - to hunt for toolchains if you want to compile for Linux or Windows. - -* On Linux you can relatively easily compile for other Linux architectures most - of the time. For example on Debian-based distributions you can install the - `gcc-aarch64-linux-gnu` package which should come with the C compiler, runtime - libraries, and linker all in one (assuming you don't explicitly request - disabling recommended packages). Other Linux distributions may have - differently named toolchains. Compiling for macOS from Linux will require - finding your own toolchain. Compiling for Windows MSVC will require finding - your own toolchain, but compiling for MinGW can work easily enough if you - install the MinGW toolchain via your package manager. - -For now we'll assume you're on Linux compiling for a different Linux -architecture. Once you've got the native toolchain, you'll want to find the C -compiler that came with it. On Debian, for example, this is called -`aarch64-linux-gnu-gcc`. Next up you'll need to configure two environment -variables to configure the Rust build: - -```shell -export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc -export CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc -``` - -The first environment variable tells Cargo to tell rustc what the correct linker -for your target is. The second configures the [`cc` Rust -crate](https://crates.io/crates/cc) for C code compiled as part of the build. - -Finally you can execute. - -```shell -cargo build --target aarch64-unknown-linux-gnu --release -``` - -The built executable will be located at -`target/aarch64-unknown-linux-gnu/release/wasmtime`. Note that you can -cross-compile the C API in the same manner as the CLI too. - -Note that if you are using these invocations regularly, you can avoid the need -to set environment variables by adding some configuration to your persistent -Cargo configuration. In the file `~/.cargo/config.toml` (in your home -directory), add the section: - -```plain -[target.aarch64-unknown-linux-gnu] -linker = 'aarch64-linux-gnu-gcc' -``` - -Then the above `cargo build --target aarch64-unknown-linux-gnu` command should -work without setting any extra environment variables beforehand. - -## Running a Cross-Compiled Wasmtime in qemu (emulation) - -Once you have cross-compiled a binary, it is possible to run it on an emulator -if you do not have access to (or do not wish to use) hardware with the given -architecture. This can be done using an emulator such as `qemu`. The `qemu` -user-space emulation support allows running, for example, a Linux/aarch64 -binary on a Linux/x86-64 host, as long as you have the system libraries for -aarch64 as well. - -To try this out, first install `qemu`, making sure that the user-space emulator -option for your target architecture is enabled. On Debian-based Linux -distributions (including Ubuntu), this is in the `qemu-user` package, for -example. - -Next, make sure that you have system libraries for the target. You will already -have these present if you cross-compiled as described above. - -Finally, you can run the `wasmtime` binary under `qemu`; the following example -is for an `aarch64` target. Adjust the library paths as appropriate; these are -correct for Ubuntu/Debian's cross-compilation packages. - -```shell -qemu-aarch64 \ - -L /usr/aarch64-linux-gnu \ - -E LD_LIBRARY_PATH=/usr/aarch64-linux-gnu/lib \ - target/aarch64-unknown-linux-gnu/release/wasmtime [ARGS] -``` - -You can add this to your persistent Cargo configuration as well. Extending the -above example in `~/.cargo/config.toml`, you can add: - -```plain -[target.aarch64-unknown-linux-gnu] -linker = 'aarch64-linux-gnu-gcc' -runner = "qemu-aarch64 -L /usr/aarch64-linux-gnu -E LD_LIBRARY_PATH=/usr/aarch64-linux-gnu/lib" -``` - -Then a simple `cargo test --target aarch64-unknown-linux-gnu` should work. diff --git a/docs/contributing-cross-compiling.md b/docs/contributing-cross-compiling.md new file mode 100644 index 0000000000..8f0239b31e --- /dev/null +++ b/docs/contributing-cross-compiling.md @@ -0,0 +1,100 @@ +# Cross Compiling + +When contributing to Wasmtime and Cranelift you may run into issues that only +reproduce on a different architecture from your development machine. Luckily, +`cargo` makes cross compilation and running tests under [QEMU] pretty easy. + +[QEMU]: https://www.qemu.org/ + +This guide will assume you are on an x86-64 with Ubuntu/Debian as your OS. The +basic approach (with commands, paths, and package names appropriately tweaked) +applies to other Linux distributions as well. + +On Windows you can install build tools for AArch64 Windows, but targeting +platforms like Linux or macOS is not easy. While toolchains exist for targeting +non-Windows platforms you'll have to hunt yourself to find the right one. + +On macOS you can install, through Xcode, toolchains for iOS but the main +`x86_64-apple-darwin` is really the only easy target to install. You'll need to +hunt for toolchains if you want to compile for Linux or Windows. + +## Install Rust Targets + +First, use `rustup` to install Rust targets for the other architectures that +Wasmtime and Cranelift support: + +```shell +$ rustup target add \ + s390x-unknown-linux-gnu \ + riscv64gc-unknown-linux-gnu \ + aarch64-unknown-linux-gnu +``` + +## Install GCC Cross-Compilation Toolchains + +Next, you'll need to install a `gcc` for each cross-compilation target to serve +as a linker for `rustc`. + +```shell +$ sudo apt install \ + gcc-s390x-linux-gnu \ + gcc-riscv64-linux-gnu \ + gcc-aarch64-linux-gnu +``` + +## Install `qemu` + +You will also need to install `qemu` to emulate the cross-compilation targets. + +```shell +$ sudo apt install qemu-user +``` + +## Configure Cargo + +The final bit to get out of the way is to configure `cargo` to use the +appropriate `gcc` and `qemu` when cross-compiling and running tests for other +architectures. + +Add this to `.cargo/config.toml` in the Wasmtime repository (or create that file +if none already exists). + +```toml +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-gcc" +runner = "qemu-aarch64 -L /usr/aarch64-linux-gnu -E LD_LIBRARY_PATH=/usr/aarch64-linux-gnu/lib -E WASMTIME_TEST_NO_HOG_MEMORY=1" + +[target.riscv64gc-unknown-linux-gnu] +linker = "riscv64-linux-gnu-gcc" +runner = "qemu-riscv64 -L /usr/riscv64-linux-gnu -E LD_LIBRARY_PATH=/usr/riscv64-linux-gnu/lib -E WASMTIME_TEST_NO_HOG_MEMORY=1" + +[target.s390x-unknown-linux-gnu] +linker = "s390x-linux-gnu-gcc" +runner = "qemu-s390x -L /usr/s390x-linux-gnu -E LD_LIBRARY_PATH=/usr/s390x-linux-gnu/lib -E WASMTIME_TEST_NO_HOG_MEMORY=1" +``` + +## Cross-Compile Tests and Run Them! + +Now you can use `cargo build`, `cargo run`, and `cargo test` as you normally +would for any crate inside the Wasmtime repository, just add the appropriate +`--target` flag! + +A few examples: + +* Build the `wasmtime` binary for `aarch64`: + + ```shell + $ cargo build --target aarch64-unknown-linux-gnu + ``` + +* Run the tests under `riscv` emulation: + + ```shell + $ cargo test --target riscv64gc-unknown-linux-gnu + ``` + +* Run the `wasmtime` binary under `s390x` emulation: + + ```shell + $ cargo run --target s390x-unknown-linux-gnu -- compile example.wasm + ```