Compiling Rust to WebAssembly is still difficult. On macOS, there are weird bugs that require reinstalling LLVM and moving files around. On Linux, the official Emscripten binary in many cases isn’t bundled with the right LLVM, and the fix is to compile from scratch, a multi-hour process. In Travis CI, the standard “solution” is to install an Alpine Linux chroot to get the latest Emscripten. It’s a clever workaround, but shouldn’t there be a better way?

wargo is a drop in wrapper for cargo that automatically installs and configures Emscripten for you (on macOS or Linux), avoiding or autofixing all of the above bugs. It can also automatically run your tests in a real web browser using WebDriver! The source code is on GitHub. To install, use npm with Node 6 or newer:1

npm install -g wargo

Let’s compile our first WebAssembly project! With wargo , it’s pretty simple:

cargo new --bin meow cd meow wargo build

With just a single command, wargo downloads the appropriate Emscripten binary, checks for dependencies, configures environment variables, and runs cargo build . You can find your freshly compiled wasm files in the target/wasm32-unknown-emscripten directory.

Testing Locally

Another command, wargo test , automatically uses WebDriver to test your WebAssembly code. If you’ve got chromedriver installed (on macOS, brew install chromedriver ) you can run this to start the WebDriver server:

chromedriver --port=4445 --url-base=/wd/hub

Once the server is up and running2 on port 4445, you can run

wargo test

in your project. We’ll automatically build a test binary and run it with WebDriver. This lets you write tests just like you would any other Rust project! Console output from the browser appears in your terminal:

$ wargo test Setup wasm checking dependencies... Setup wasm found emsdk installation in ~/.emsdk Setup wasm setting environment... (...) Setup wasm running 'cargo test --target=wasm32-unknown-emscripten --no-run --message-format=json' Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Setup wasm running tests... pre-main prep time: 566 ms running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Right now, we don’t have any tests, so none were run. But if we added a standard one with Rust’s #[test] macro, it would run here!

Testing in Travis

With a free-for-open-source Sauce Labs account, you can easily test your WebAssembly project in Travis CI, even with multiple browsers! Just put this in your .travis.yml :

language: rust rust: stable install: - npm install -g wargo # install recent cmake, since Trusty only ships with an old version - (cd ~; curl -sSL https://cmake.org/files/v3.5/cmake-3.5.2-Linux-x86_64.tar.gz | tar -xz) - sudo mv /usr/bin/cmake /usr/bin/cmake.old - sudo ln -s ~/cmake-3.5.2-Linux-x86_64/bin/cmake /usr/bin/cmake script: - wargo build --verbose - wargo test --verbose addons: sauce_connect: username: "TODO your Sauce Labs username" access_key: "TODO your Sauce Labs access key"

If you want to test in a different type of browser, you can put Sauce Labs configuration JSON in the WEBDRIVER_CAPABILITIES environment variable. For instance, you could add this line under install: to test in Chrome 60 running on Windows 8:

- export WEBDRIVER_CAPABILITIES='{"browserName": "chrome", "platform": "Windows 8", "version": "60.0"}'

Using with Webpack

There is also the wargo-loader package for use with Webpack, based off rust-emscripten-loader by Matt Dziuban.

cargo new --bin meow cd meow

We’ll create a package.json file with the autowasm dependency and some helper scripts:

echo '{ "devDependencies": { "http-server": "^0.10.0", "wargo-loader": "^0.3.0", "webpack": "^3.7.1" }, "scripts": { "compile": "webpack --progress", "serve": "http-server" } }' > package.json

We’ll next create a index.js file to load in the WebAssembly, as well as a simple index.html file and a Webpack config file.

echo ' const wasm = require("./main.rs") wasm.initialize({noExitRuntime: true}).then(module => { // you can call module.cwrap here to get function wrappers for Rust functions }) ' > src/index.js echo '<!DOCTYPE html> <script src="build/bundle.js"></script>' > index.html curl -L https://git.io/vdNTe > webpack.config.js

With all the files in place, we just need to install the dependencies, run webpack with the compile script, and start the server.

npm install npm run compile npm run serve

If you open localhost:8080, you’ll just see a blank screen. But open up the JavaScript console, and you should see your “Hello, World!” from Rust!

Please Help Bugtest!