Personal life got in the way for 2 of the 5 days of Week 8, which is unfortunate but happens. I only had time to focus on one project this week, but it was a chunky one: I wrote a linker for Brick’s toolchain.
This isn’t my extremely cursed wasmtime-dl project. It’s a crate that takes multiple WASM modules, resolves any exports that match imports, smooshes them all together, and outputs a single standalone module. This is crucial for Brick’s compilation process, because I need to combine the user’s compiled program with the runtime I wrote in Rust. I rolled my own linker for three reasons:
- I thought it would be fun (it was)
- I wanted to avoid taking a massive C++ dependency
- If I write the code, I know it’s doing exactly what I need and nothing else
There are two major alternatives I considered, wasm-merge
or wasm-ld
. The first is part of the binaryen project, which is a WASM toolkit; the second is a port of lld
. Taking dependencies on either of these major projects would conflict with goal #2 and #3 above. Keeping my dependency tree purely Rust makes building and running the compiler simpler, especially if I want to build the compiler itself to WASM and embed it in a webpage.
Avoiding large dependencies decreases the overall complexity of the project; currently the only dependencies I’m taking are Rust ecosystem mainstays (rayon
, anyhow
, thiserror
, serde
) or protocol-specific crates that I could rewrite myself if necessary (wasm-encoder
, wasmparser
, lsp-server
, lsp-types
)[1]. If a newcomer wanted to understand the project end-to-end, they would be confronted with around 20,000 lines of Rust. That sounds like a lot, but Binaryen is hundreds of thousands of lines of C++ and LLVM is in the millions.
Also, this is probably minor in the scheme of things for performance, but wasm-merge
and wasm-ld
both work with objects on disk. I wanted to do the linking in-memory before I write out the final binary, for convenience and speed.
Over the weekend between Weeks 8 and 9 I also hacked on an Obsidian plugin. It was a pretty fun experience, and my web background made it very straightforward. I now have a plugin which allows me to review my diary notes from the past week, which I like to do as part of my journaling practice. You can check it out on Github, but it’s not documented or configurable in the slightest. I might come back and clean it up at some point, but no promises - it’s already doing everything I need.
Technically I also depend on wasmtime, but I could swap it out for another wasm runtime without too much trouble. I’m mostly using it as a test runner; it’s a very convenient way to run some wasm from Rust code. Nothing about the compiler toolchain requires wasmtime specifically. ↩︎