Hi everyone! We wanted to let you know about some changes to the Rust compiler’s Emscripten support.
Background
Rust has been able to emit asm.js using Emscripten and has been able to emit WebAssembly using either Emscripten or the unknown triple (wasm32-unknown-unknown). The unknown triple is the preferred approach in general, especially when writing some new Rust code especially for the Web. But the Emscripten path is very useful when porting Rust programs that were originally written to run natively - for example, a Rust game engine using SDL2 and OpenGL can be compiled to the Web using Emscripten’s port of SDL2 and its OpenGL compatibility layer. And in general a mixed project of both Rust and C/C++ may be easier to port using Emscripten due to the C/C++ support there. Emscripten may also be useful if you want built-in integration for features like Asyncify.
What’s Changing
Emscripten has supported two backends for a while now, the “fastcomp” asm.js backend, and the LLVM wasm backend. The wasm backend and its integration in Emscripten has gotten very good and we currently recommend people use it, as it has several advantages like emitting smaller and faster code, and much faster linking. In particular, the wasm backend fixes several bugs with Rust+Emscripten (like IR compatibility issues, as fastcomp was very tailored to the LLVM IR from Clang).
We are migrating Emscripten in general from fastcomp to the wasm backend, and we’d like to do that in Rust as well. Aside from the benefits already mentioned, a major benefit for Rust here is that this change will allow removal of the fastcomp LLVM build. Besides that internal change, you shouldn’t see much change when using the new backend (except some speedups!) but there are a few known bugs.
One thing that does change significantly is the asm.js support, which was only present in fastcomp. Emscripten’s wasm backend support has an option to emit non-asm.js JavaScript, which uses Binaryen’s wasm2js to convert the wasm to JS. This is smaller than the old asm.js in most cases, and generally preferable, but it doesn’t benefit from asm.js optimizations, so if you benchmark it in a browser with asm.js optimizations (most of them these days) it may appear slower. Because this isn’t asm.js, we are planning to remove the separate asmjs-unknown-emscripten target. To get the JS output, you can instead use the emscripten target normally and add -s WASM=0
to the link-time flags. Alternatively, if the community prefers, we can rename the asmjs-unknown-emscripten
target to js-unknown-emscripten
but keep it as a separate target.
As a result, after this change you will have the following targets:
-
wasm32-unknown-unknown (self-contained binaries)
-
wasm32-unknown-emscripten (full applications with dependencies)
-
wasm32-wasi (experimental wasm-native platform)
-
js-unknown-emscripten (If the community prefers this over linker flags)
- Thomas and Alon