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
?
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.wasm32-unknown-unknown
target with close collaboration with the wasm-bindgen
project. A big part of the Rust+WASM ecosystem, including winit
and wgpu
gravitates towards that. There's good support and documentation all around.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.
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 is 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