Building

This section describes everything required to build and run Wasmtime.

Prerequisites

Before we can actually build Wasmtime, we'll need to make sure these things are installed first.

Git Submodules

The Wasmtime repository contains a number of git submodules. To build Wasmtime and most other crates in the repository, you have to ensure that those are initialized with this command:

git submodule update --init

The Rust Toolchain

Install the Rust toolchain here. This includes rustup, cargo, rustc, etc...

libclang (optional)

The wasmtime-fuzzing crate transitively depends on bindgen, which requires that your system has a libclang installed. Therefore, if you want to hack on Wasmtime's fuzzing infrastructure, you'll need libclang. Details on how to get libclang and make it available for bindgen are here.

Building the wasmtime CLI

To make an unoptimized, debug build of the wasmtime CLI tool, go to the root of the repository and run this command:

cargo build

The built executable will be located at target/debug/wasmtime.

To make an optimized build, run this command in the root of the repository:

cargo build --release

The built executable will be located at target/release/wasmtime.

You can also build and run a local wasmtime CLI by replacing cargo build with cargo run.

Building the Wasmtime C API

To build the C API of Wasmtime you can run:

cargo build --release --manifest-path crates/c-api/Cargo.toml

This will place the shared library inside of target/release. On Linux it will be called libwasmtime.{a,so}, on macOS it will be called libwasmtime.{a,dylib}, and on Windows it will be called wasmtime.{lib,dll,dll.lib}.

Building Other Wasmtime Crates

You can build any of the Wasmtime crates by appending -p wasmtime-whatever to the cargo build invocation. For example, to build the wasmtime-jit crate, execute this command:

cargo build -p wasmtime-jit

Alternatively, you can cd into the crate's directory, and run cargo build 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:

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:

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 for C code compiled as part of the build.

Finally you can execute.

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:

[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.

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:

[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.