What follows is a brain dump of everything I know about compiling Rust to WebAssembly. Enjoy.
Some time ago, I wrote a blog post on how to compile C to WebAssembly without Emscripten, i.e. without the default tool that makes that process easy. In Rust, the tool that makes WebAssembly easy is called wasm-bindgen, and we are going to ditch it! At the same time, Rust is a bit different in that WebAssembly has been a first-class target for a long time and the standard library is laid out to support it out of the box.
Even though Zola is written in Rust, it still relies on glibc, the GNU C Library. The update to v15 changed how the Zola binary for Linux was built, causing it to rely on newer versions of glibc. After a few emails with Vercel's support team, I confirmed that the build environment used by Vercel only had access to glibc 2.26, hence the errors when attempting to use the latest version of Zola.
Now, at this point, I had a few options if I wanted to use the latest version of Zola to build my site, but the easiest was probably setting up my Vercel project to download a custom-built version of Zola that was built against a lower version of glibc. While it certainly would have worked, and wouldn't have been too much effort, it also wasn't a fun or interesting solution.
Instead, I decided to see if I could compile Zola to WASM targeting the WebAssembly System Interface (WASI) and run it as a standard npm package.
Spoiler: I could!
What if I told you there was a way that we could ship one binary from Rust, have that work on every platform Go supports, and not have to modify the build process beyond a simple go build? Imagine how much easier that would be. It's easy to imagine that such a thing would let users not even know that Rust was involved at all, even if they consume a package or program that uses it.
I've done this with a package I call mastosan and here's why it exists as well as how I made it.
Most WebAssembly tutorials and examples you will find online focus on using it inside the browser in order to accelerate various functionality of a website or web app. However, there is an area where WebAssembly is really powerful but not talked too much about: outside the browser usage scenarios. That is what we’ll focus on in this series of posts.
We’ll be building a simple ecommerce site called “RustMart”.
I initially picked up Rust because of the fantastic work the team has done to support and push WebAssembly. The official documentation is a great resource for building an example project.
This guide will serve as an introduction to WebAssembly and a tutorial on how to set up and work in a Rust Wasm environment.
We recently learned that the WebAssembly build in our system isn't deterministic any longer. This is a short summary of what we did to chase down the bug in the hope that this helps others facing similar issues, give some help and guidance on what to try or how this kind of thing works.
As a side project, I’m writing an Europa Universalis IV (EU4) leaderboard and in-browser save file analyzer called Rakaly. No need to be familiar with the game or the app, but feel free to check Rakaly out if you want, we’re just getting started.
I’m writing this post as whenever Rust is posted on the internet, it tends to elicit polar opposite responses: the evangelists and the disillusioned. Both can be correct in their viewpoints, but when one is neck deep in a Rust side project and stumbles across a discussion that is particularly critical of Rust, self doubt may creep into thoughts. And while self doubt isn’t inherently bad (second guessing can be beneficial), too much doubt can cause one to disengage with their hobby. This post is me sharing struggles seen along the way and realizing that the wins Rust gave me far outweigh the struggles.
Pont is an online implementation of Qwirkle, a board game by Mindware Games. It was written for my parents, so they could play with friends and family during the COVID-19 stay-at-home era.
Play is split into rooms, which are identified by a three-word code (size moody shape in the image above). Within each room, the game distributes pieces, enforces the game rules, and provides a local chat window.
Our team, DeisLabs, recently released a new piece of software called Krustlet, which is a tool for running WebAssembly modules on the popular, open-source container management tool called Kubernetes. Kubernetes is used quite extensively to run cloud software across many vendors and companies and is primarily written in the Go programming language. While there have been many stories about using Rust for systems level programming, you don’t often hear stories about cloud software or Kubernetes software being written in Rust. So, we wanted to explain why we made the choice we did.
When working with Rust + Webassembly, you might want to use some crates in your project. Not all crates work out of the box with Webassembly yet, especially those that rely on System Libraries, File I/O, Networking, etc. With proposals such as WASI or WebAssembly Interface Types, these might work eventually but it isn’t the case yet.
The Rust Wasm book suggests: A good rule of thumb is that if a crate supports embedded and #![no_std] usage, it probably also supports WebAssembly.
In my last post I mentioned that pa’i was faster than Olin’s cwa binary written in go without giving any benchmarks. I’ve been working on new ways to gather and visualize these benchmarks, and here they are.
Benchmarking WebAssembly implementations is slightly hard. A lot of existing benchmark tools simply do not run in WebAssembly as is, not to mention inside the Olin ABI. However, I have created a few tasks that I feel represent common tasks that pa’i (and later wasmcloud).
One of the interesting prospects of WebAssembly is that it can be used for safe and portable sandboxing on systems that aren’t web browsers. This is somewhat undersold by at least some parts of the wasm ecosystem, in my opinion, but has some real value. Being able to distribute executables and libraries in a portable bytecode that gets locally compiled seems to me like a strict improvement on distributing platform-specific binaries, even if the programs are open source and you can just compile them from source if you really want to. Given that we’re increasingly living less in an x86_64 monoculture, with diverse good non-x86 hardware widely available, this idea seems more and more useful. So, as someone who mostly wants to write portable programs that run on desktop-style hardware, let’s try to actually use webassembly for this and see how it goes.
In a previous post, we saw how Rust WebAssembly can be integrated into a JavaFX project using the Asmble tool. Here we look at an integration of the same functionality using the Java Native Interface (JNI). Finally, we compare the two approaches in terms of convenience and performance.
The point of having Rust-based WebAssembly in Node.js is to offload some compute-heavy parts from Node.js to Rust, which runs significantly faster for tasks that require algorithmic or memory optimization. The Rust compiler is smart enough to optimize its base functions, which makes it run faster. However, the combination of a single-threaded Node.js and Rust-based WebAssembly, which also runs without threading, won’t do much to save you time or resources.
The idea is to use a Node.js module worker_threads to spin up a new Rust WebAssembly computation without having a sync operation waiting in the main thread.
This is the second part of a blog post series. You can read the first part on our website.
Rust slowly but steadily progressing into the world of web development.
Rust is easy to get started (if you wrap your head around the ownership model) and backed by an awesome community that is ready to help.
Rust provides the first class support for the WebAssembly. Rust and WebAssembly toolchain makes it easier and faster to get started with WebAssembly.
I've been studying WebAssembly recently, which has included porting some of my m4vga graphics demos. I started with the Rust and WebAssembly Tutorial, which has you use fancy tools like wasm-pack, wasm-bindgen, webpack, and npm to produce a Rust-powered webpage.
And that's great! But I want to know how things actually work, and those tools put a lot of code between me and the machine.
The resulting WebAssembly module will be less than 300 bytes. That's about the same size as the previous paragraph.
Wasm Pack is a flexible framework in the Rust ecosystem to compile code to WebAssembly. It allows web developers to outsource their most demanding data processing tasks to some safe and high-performance Rust code. But it also provides Rust developers with an easy access to Web technologies for creating GUIs for their libraries. Elm is a fairly new language that has revolutionised the way highly interactive web pages are built. This tutorial presents a way to use Elm in conjunction with Rust to produce powerful web applications.
I originally wrote Sorta Secret a year ago in Rust using actix-web and deployed it, like most services we write at FP Complete, to our Kubernetes cluster. When Rust 1.39 was released with async/await support, and then Hyper 0.13 was released using that support, I decided I wanted to try rewriting against Hyper. But that's a story for another time.
After that, more out of curiosity than anything else, I decided to rewrite it as a serverless application using Cloudflare Workers, a serverless platform that supports Rust and WASM.
This post will describe my experiences doing this, what I thought worked well (and not so well), and why you may consider doing something like this yourself.
In a project I’ve been playing around with recently, we’ve encountered the dilemma where you want to make it easy for users to write their own application logic using the system but at the same time want to keep that logic decoupled from the implementation details of whatever platform the application is running on.
Using a Rust image manipulation library via WebAssembly, service workers can manipulate images on the fly. You can see a simple example of the code here and a fully-fledged example here.
Multi-value is a proposed extension to core WebAssembly that enables functions to return many values, among other things. It is also a pre-requisite for Wasm interface types.
I’ve been adding multi-value support all over the place recently: I added multi-value support to all the various crates in the Rust and WebAssembly toolchain, so that Rust projects can compile down to Wasm code that uses multi-value features. I added multi-value support to Wasmtime, the WebAssembly runtime built on top of the Cranelift code generator, so that it can run Wasm code that uses multi-value features.
Now, as my multi-value efforts are wrapping up, it seems like a good time to reflect on the experience and write up everything that’s been required to get all this support in all these places.
Today we announce the formation of the Bytecode Alliance, a new industry partnership coming together to forge WebAssembly’s outside-the-browser future by collaborating on implementing standards and proposing new ones. Our founding members are Mozilla, Fastly, Intel, and Red Hat, and we’re looking forward to welcoming many more.
Wasmtime is a standalone wasm-only optimizing runtime for WebAssembly and WASI, using Cranelift. It runs WebAssembly code outside of the Web, and can be used both as a command-line utility or as a library embedded in a larger application.
In our last adventure we looked at C++ exceptions in WebAssembly with the emscripten compiler. Now we’re taking a look at the main error handling system for another language targeting WebAssembly, Rust. Rust has a “panic”/”unwind” system similar to C++ exceptions, but it’s generally recommended against catching panics.
View all tags