Title.
What are the specific steps to compile and link C/C++ and Rust under the same WASM binary for wasm32-unknown-unknown
while using wasm-bindgen
?
Context
wasm32-unknown-emscripten
is a legacy target and seldom maintained by one part-time person, but until recently, it was the only target capable of compiling and linking libraries that use both Rust and C.- The Rust+WASM community largely moved towards the
wasm32-unknown-unknown
target with close collaboration with thewasm-bindgen
project. A big part of the Rust+WASM ecosystem, includingwinit
andwgpu
gravitates towards that. There’s good support and documentation all around.
Problem
The Rust compiler used to produce an incompatible C ABI for the wasm32-unknown-unknown
target, that does not follow the specs-compliant clang’s C ABI.
As wasm-bindgen
depends on the Rust compiler, it also produced a WASM binary that was fundamentally incompatible and could not be linked together with binaries created by compliant C compilers.
Current State of the Ecosystem
There has been significant progress towards a solution. In April 2024, the Rust compiler team introduced a perma-unstable --wasm_c_abi
flag that tells the compiler to produce compliant C ABI for WASM targets, and wasm-bindgen
started to support compliant C ABI starting from version 0.2.88. This is the relevant tracking issue.
This flag should be available in nightly Rust and will be removed in a future version, where the compiler will produce compliant C ABI by default.
Up until April 2024, you needed to use wasm32-unknown-emscripten
or wasm32-wasi
targets to link C and Rust under the same binary.
Now that the Rust compiler team Merged a PR introducing the perma-unstable wasm_c_abi
flag, it’s now possible to compile Rust+C for the wasm32-unknown-unknown
target with Rust nightly and use wasm-bindgen
with external C dependencies. This will be the default behavior in the near future.
Here’s a minimal example of a Rust+C WASM lib.
The build process boils down to:
export RUSTFLAGS="--cfg=web_sys_unstable_apis --Z wasm_c_abi=spec"
cargo +nightly build --target=wasm32-unknown-unknown --release
cp target/wasm32-unknown-unknown/release/hello.rlib hello.a
clang
--target=wasm32
-c
-o world.o
world.c
wasm-ld
--no-entry
--export-all
-o hello_world.wasm
hello.a
world.o