Compiling Rust to WebAssembly Guide

Written by chicoxyzzy | Published 2016/12/25
Tech Story Tags: javascript | webassembly | emscripten | rust

TLDRvia the TL;DR App

So you are intrigued what WebAssembly is and want to try it? Since December 22 it’s possible to compile Rust to WASM. If you don’t know anything about Rust language, I recommend you to read about it, it’s awesome! However you don’t need to know how to write programs in Rust for this guide.

I’ve been stuck many times before I ran WASM in VM. I’ve spent hours figuring out what’s wrong on each step and I want to help you save your time. So let’s start!

First of all you should install Rust language on your computer. The best way to do it is to use a tool named rustup. You can install it as easy as

curl https://sh.rustup.rs -sSf | sh

Optionally configure your [PATH](https://www.rust-lang.org/en-US/install.html) environment variable (I recommend to do it if you are going to learn and use Rust).

Install stable Rust and rustup target

rustup install stablerustup default stablerustup target add wasm32-unknown-emscripten

Installing new target is needed to cross-compile your code to WASM from your platform.

Download a portable version of Emscripten SDK, then run command below:

source .**/**emsdk_env.sh

Now check emcc version

emcc -v

Probably you’ll get Emscripten SDK (aka emsdk) version 1.35.0 installed but you need 1.37.0 (or higher) to be able to compile to WASM. Unfortunately there are no precompiled binaries (at the moment of publishing this guide) so you should compile Emscriten SDK from sources.

emsdk updateemsdk install sdk-incoming-64bitemsdk activate sdk-incoming-64bit

It will take time (about 2 hours in my case) so be patient. When it’s done check emcc -v again. It should tell you that you have (at least) 1.37.1 installed now.

From now you are all set up! Let’s try something!

rustc --target=wasm32-unknown-emscripten hello.rs -o hello.html

This will generate a bunch of files. We are only interested in three of them:

  • hello.wasm
  • hello.js
  • hello.html

First one is a WebAssembly binary. We can’t run wasm on it’s own. WebAssembly doesn’t have any I/O. So we need to wrap it into JavaScript that will load, compile and run wasm. Generated HTML file provides an environment (with canvas and console) where we can run our code.

To run WebAssembly in browser you need either Chrome Canary

Enabling WebAssembly in Chrome Canary

or Firefox Nightly

Enabling WebAssembly in Firefox Nightly

Now run python -m SimpleHTTPServer (or any other web server) and open http://localhost:8000/hello.html (port may vary) in browser. You’ll see Hello, Emscripten! in Emscripten console.

Achievement unlocked: Rust & WebAssembly hacker.

Congrats! You just ran wasm in your browser! It looks like it’s not that hard to compile Rust to wasm, but believe me, a lot of people gave up doing this. Just follow comments from Brendan Eich’s tweet. There you can find my solutions to various issues. You unlikely will have any if you follow this guide step-by-step.

Unfortunately Node.js doesn’t have full support of WebAssembly. However you can use polyfill or [interpret-wasm](https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods) Binaryen method (I had no luck with it using rustc).

Update (Jan 6, 2017): you can run wasm in Node.js! Clone this repo, then switch to vee-eight-lkgr branch and build Node.js from sources. Run hello.js script using built node with --expose-wasm option.

WebAssembly running in Node.js

Whoohoo!

Next goal: compiling Rust to WebAssembly standalone. This needs some work because I’ll need to connect rustc to emcc somehow and I don’t know how to do it yet. Ping me please if you can help!

Please let me know if you have any problems following this guide. I’ll try to help you and update guide to help other people too.

Big thanks to

About me:

GitHub digger. TypeScript user. Rust newbie. Things-I-love evangelist. Public speaker (if you speak Russian you may like my public talk about WebAssembly or other talks). Contributed to React, Babel, etc. Helping maintain compat-table and babel-preset-env. Part of MoscowJS crew, co-organizer of BeerJS Moscow. Community guy whose glass is always half-full.

Follow me on Twitter @chicoxyzzy


Published by HackerNoon on 2016/12/25