Hi,
I’ve been looking at using Wasm a few months ago but were not even able to properly install Emscripten. After seeing this post I tried again.
First of all, I agree with the messages above: the main pain points for me are the installation of the environment and lack of documentation. I have trouble even running my project so higher level APIs or code size are not a concern for me yet.
My use case is to use Rust to compile a library usable in Javascript, both in Node and the browser.
The Medium post Get Started with Rust, WebAssembly, and Webpack helped me but the Emscripten instructions did not work for me (emcc -v reported errors about fastcomp and a wrong version of clang, it seemed to pick my system clang instead of the one it had built). Even the instructions on the Emscripten website did not seem to be complete. They say to install and activate latest and then configure the environment, but after this step emcc wasn’t even in my PATH (there was no compilation, emscripten wasn’t in the list of installed tools when running emsdk list). I guess that latest referred to the SDK “installer” instead of the actual tools, but it’s confusing.
By mixing the instructions both in the article and Emscripten website, I managed to install Emscripten with:
# Make sure that the `emsdk-portable` directory is in the $PATH before running these commands
emsdk update
emsdk install latest
emsdk activate latest
emsdk install sdk-incoming-64bit
# Activate was missing in the article
emsdk activate sdk-incoming-64bit
# This command was also missing, not sure if it's needed, it seems to just set the env variable `EMSDK`
source emsdk_env.sh
Once this was configured, I was able to compile and run the Hello world exemple of the article as well as the Wargo loader example (it’s almost the same thing).
Starting from there, I wanted to experiment with building a small library. My goal is to port my SWF parser. I have both a Typescript and Rust implementation, I’d like to use my Rust implementation in Node or the browser using Wasm, with the same API as the Typescript version. Basically, I want to learn how write a library able to swap a JS implementation for a Wasm implementation and not break its public interface. In my example, I’d just like to start with a JS interface exposing a single async function parse that takes an ArrayBuffer and returns a JSON string representing the AST. I’d expect it to be not too hard but have no idea how to do it: it seems just a level above the add function in the hello-world example. I am not using any system dependant features, the API only uses buffers and strings.
Here are the questions I have regarding this sort of project, the Medium (and others) example and Wasm in general.
-
How do I build a Wasm library? I just want a lib.rs instead of a main.rs.
If I rename main.rs, remove the main function and update "index.js", cargo does not even compile any js file. cargo build --target=wasm32-unknown-emscripten does not even produce a .wasm or .js file. This is maybe related to this issue.
A pattern I’ve seen on a few websites is to use a main.rs but with an empty main function and the other public functions in this file. This seems like a hack but at least it allows me to expose functions. Still, when running it in my browser I get a warning:
exit(0) implicitly called by end of main(), but noExitRuntime, so not exiting the runtime (you can use emscripten_force_exit, if you want to force a true shutdown)
This seems caused by {noExitRuntime: true} but there’s no explanation about this option. If I remove it, it crashes. Does main has to run to invoke the other exported functions?
-
What does the webpack’s loader do? How can I use wasm without it? How can I use wasm in Node?
Why does Webpack runs the cargo compilation? Can’t I compile my project to wasm beforehand and then use const wasm = require("./my_lib.wasm")? I know that it needs a JS glue for the conversions, but can’t it just let me import the .wasm files and inject the glue automatically? What if I have multiple Wasm modules? Do I need a JS wrapper for each wasm file? Is it possible to load a Wasm file manually without the JS wrapper? I’ve seen WebAssembly.instantiate and new WebAssembly.Module on MDN but it’s lacking complete examples. What does the importer argument for WebAssembly.Module even do? How do I import a Wasm module in Node, do I still need Webpack?
-
How to structure my code?
In my ideal world, I would like to publish my library to npm and let others use it without even knowing that it uses Wasm. Did somebody ever do this? How do you add a fallback to asm.js? Does it play well with bundlers used by the consumers of the library? Are there some gotchas when designing the JS API such as memory leaks or initialization that must be done by the consumer? What about module formats, commonJs and ES2015 modules?
-
How do I maintain Typescript definitions? Typescript is a god-send for JS. Is it possible to emit type definitions for Wasm modules? @CryZe mentioned that some autogeneration is possible. Are there some examples? Is there some documentation?
I don’t expect answers for all these questions. I just wrote them down so you can get an idea of what kind of problems I encounter as a newcomer to Wasm. I really miss an official source documenting how to use Rust for Wasm. I feel as if all we have to work with are some hello-world examples spread accross the internet. A Github repo with a book and examples that could be maintained by the community would be great.