I spent a while trying to get a Rust toolchain working on an iPad without sending code to a server, and this is where it ended up: rustc 1.98, cargo and lld compiled to WebAssembly (wasm32-unknown-emscripten), running inside WKWebView, with a build driver written in Swift that handles dependency resolution, feature unification, fingerprints and an incremental target/ directory. User code compiles to wasm32-wasip1 and runs in the app's sandbox.
Rough timings on an iPad Air M3, for whatever they are worth:
- single file, compile and run: about 0.3 s
- Cargo project with rand (proc-macros, build scripts), cold: under 40 s
- same project after editing main.rs: about 2 s
The parts that took the longest, in case they are useful to anyone attempting something similar:
Proc-macros. No processes, no dlopen. Each one is compiled to a self-contained wasm reactor and called through a synchronous host hook, watt style. Hygiene was the subtle part: a macro_rules! marked local_inner_macros that invokes a proc-macro had rustc resolving stringify! inside the wrong crate, and it took a while to find.
Memory. Between rustc's wasm heap and JavaScriptCore's limits, a cold build spends more time recycling processes than compiling. The driver keeps a pool and persists fingerprints so a killed process resumes rather than starting over.
No threads, no real filesystem. WASI shims for what std expects, a synchronous bridge for stdin, a native one for sockets.
What it is not: there is no rust-analyzer. I did compile RA to wasm and measured it, but proc-macro expansion and std sources cost more than I was willing to spend on a tablet, so the editor side is a tree-sitter engine I wrote instead: semantic tokens, go-to-definition across files and into crate sources, hover, inferred type hints, rustc quick fixes, rename, references. There is no debugger either.
And the constraint that shapes everything: your programs are wasm, not arm64. iOS does not allow executing natively generated code, so on-device compilation has to target a sandbox. Firmware for Raspberry Pi Pico is the exception, since that binary runs on the microcontroller rather than the iPad; it works and I have verified it on hardware, but it is not in this build yet. Crates with native dependencies often will not build for wasi.
It is a paid app, free for single files, and I would rather say that here than have someone find out after installing. If you want to try it: https://testflight.apple.com/join/4Yaujqd5
What I am actually after is where it falls over. Crates that fail to build, builds that die halfway, anything that behaves differently from cargo on a desktop.