Binary patching rust hot-reloading, sub-second rebuilds, independent server/client hot-reload
Inlines the work from https://github.com/jkelleyrtp/ipbp to bring pure rust hot-reloading to Dioxus.
https://github.com/user-attachments/assets/8db62f65-00eb-4cc6-9678-1bebeea4845d
The approach we're taking works across all platforms though each will require some bespoke logic. The object crate is thankfully generic over mac/win/linux/wasm, though we need to handle system linkers differently.
This change also enables dx to operate as a faster linker allowing sub-second (in many cases, sub 200ms) incremental rebuilds.
Todo:
- [x] Add logic to the devtools types and generic integration
- [x] Wire up desktop
- [x] Rework existing hot-reload engine to be properly compatible
- [x] Remove old binaries
- [x] Wire up iOS
- [x] Wire up macOS
- [x] Wire up Android
- [x] Wire up Linux
- [x] Wire up wasm
- [x] Wire up windows
- [x] Wire up server
- [x] clean up app/server impl (support more than 2 exe-s in prep for dioxus.json)
- [ ] fix integration with old hot-reload engine
Notes:
This unfortunately brings a very large refactor to the build system since we need to persist app bundles while allowing new builds to be "merged" into them. I ended up flattening BuildRequest + Bundle together and Runner + Builder together since we need knowledge of previous bundles and currently running processes to get patching to work properly.
progress update
I've migrated everything over from ipbp so now anyone should be able to run the demos in macOS/iOS. Going to add linux + android support next.
I've been tinkering with the syntax for subsecond a bit and am generally happy now with the API. You can wrap any closure with ::call() and that closure is now "hot":
pub fn launch() {
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
subsecond::call(|| tick());
}
}
fn tick() {
println!("boom!");
}
If you need more granular support over "hot" functions then you'll want to use ::current(closure) which gives you a HotFn with extra flags and methods for running a callback. It also lets you run closures which are FnOnce since ::call() currently does not.
::call() taking an FnMut is meant to provide an "unwind" point that our assembly-diffing logic can bounce up to by emitting panics. This is meant to support cases where you might add a field to a struct and need to "rebuild" the app from a higher checkpoint (aka re-instancing).
For example, a TUI app with some state:
struct App {
should_exit: bool,
temperatures: Vec<u8>,
}
might implement a "run" method that calls subsecond:
fn run(&mut self, terminal: &mut DefaultTerminal) -> Result<()> {
while !self.should_exit {
subsecond::call(|| self.tick(terminal))?;
}
Ok(())
}
If the struct's size/layout change, then we want to rebuild the app from scratch. Alternatively, we could somehow migrate it, which is out of scope for this PR, but implementations can be found in libraries like dexterous. We might end up taking an approach that unwinds the stack to the app's constructor and then copies it to a new size/layout, merging the new fields in. TODO on what this should look like.
Here's a vide of the tui_demo in the subsecond_harness crate:
https://github.com/user-attachments/assets/367d805e-add5-4066-baa0-1db035eba7b6
runtime integration
Originally I wanted to use LLDB to drive the patching system - and we still might need to for proper "patching" - but I ran into a bunch of segfaults and LLDB crashes when we sigstopped the program in the middle of malloc/demalloc. Apparently there's a large list of things you cannot do when a program is sigstopped and using allocators is one such thing. We could look into using a dedicated bump allocator and continue using lldb, but for now I have an adapter build on websockets. We might end up migrating to a shared-memory system such that the HOST and DUT can share the patch table freely. The challenge with these approaches is that they're not very portable and websockets seem to be available literally everywhere.
zero-link / thinlink
One cool thing spun out of this work is "zerolink" (thinlink maybe?): our new approach for drastically speeding up rust compile times by automatically using dynamic linking. This is super useful for tests, benchmarks, and general development since we can automatically split your workspace crates from your "true" dependencies and skip linking your dependencies on every build.
This means you can turn up opt levels and leave debug symbols (two things that generally slow down builds) which incurs a one-time cost and then continuously dynamically link your incremental object files against the dependencies dylib. Most OSes support a dyld_cache equivalent which keeps your dependencies.dylib memory mapped and cached between invocations which also greatly speed up launch times.
ZeroLink isn't really an "incremental linker" per se, but it behaves like one thanks to Rust's incremental compile system. In spirit it's very similar to marking a crate as a dylib crate in your crate graph (see bevy/dynamic) but it doesn't require you to change any of your crates and it supports WASM.
dx is standalone
I wanted to use zerolink with non-dioxus projects, so this PR also makes dx a standalone rust runner. You can dx run your project and dioxus does not need to be part of your crate graph for it to work. This lets us bootstrap dx by running dx with itself and making it easy to update the TUI without fully rebuilding the CLI.
wasm work
WASM does not support dynamic linking so we need to mess with the binaries ourselves. Fortunately this is as simple as linking the deps together to a relocatable object file, lifting the symbols into the export table, and recording the element segments.
When the patches load they need two things
- addresses within the ifunc table for ifuncs
- imports from the main module
unfortunately the wasm-bindgen pass runs ::gc so I don't think there's any cool combination of flags we can use against wasm-ld to do this for us automatically. However, all the work we put into wasm_split really comes in handy.
What's left
There's three avenues of work left here:
- Propagating the change graph through the
HotFnpoints - More platform support (windows, wasm, server_fn)
- Bugs (better handling of statics, destructors, renaming symbols, changing signatures, and dioxus integration like Global)
I expect Windows + WASM to take the longest to get proper support and will prioritize that over propagating the change graph. Dioxus can function properly without a sophisticated change graph, but other libraries will want the richer detail available.
Awesome work here! I might recommend adding .arg("-Zcodegen-backend=cranelift") as an optional user-facing argument when hot reloading.
I found on my M3 Pro Macbook it brings down the average times from ~600ms to ~300ms. The backend ships as a cargo component now so it should be a drop in replacement for desktop or possibly mobile platforms.
Awesome work here! I might recommend adding
.arg("-Zcodegen-backend=cranelift")as an optional user-facing argument when hot reloading.I found on my M3 Pro Macbook it brings down the average times from ~600ms to ~300ms. The backend ships as a cargo component now so it should be a drop in replacement for desktop or possibly mobile platforms.
Wow that's incredible!
On my M1 I've been getting around 900ms on the dioxus harness with default dev profile and then 500-600 with the subsecond-dev profile:
[profile.subsecond-dev]
inherits = "dev"
debug = 0
strip = "debuginfo"
I'll add the cranelift backend option and then report back. In the interim you can check to see if that profile speeds up your cranelift builds at all.
I did some profiling of rustc and about 100-300ms is spent copying incremental artifacts on disk. That's pretty substantial given the whole process is like 500ms. Hopefully this is improved here:
https://github.com/rust-lang/rust/pull/128320
I would like to see that time drop to 0ms at some point and then we'd basically have "blink and you miss it" hotpatching.
I tried the profile and with or without it, its consistently ~300ms on my Mac. ~When doing self-profile I noticed that register allocation takes a huge portion of the total time spent~
~I discovered this (https://docs.wasmtime.dev/api/cranelift_codegen/settings/enum.RegallocAlgorithm.html) which might help if its been backported to codegen_clif as a flag or option.~
That seemed to be a fluke in testing and actually the remaining time is mostly incremental cache related file IO. Not sure how much can be done about that.
Regardless, this is super exciting work, let me know if there's any other way I can help.
I switched to a slightly modified approach (lower level, faster, more reliable, more complex).
This is implemented to work around a number of very challenging android issues
- pointer tagging
- mte
- linker namespaces
- read/write permissions
Since this is more flexible it should work across linux and windows (android and linux are the same). Last target is wasm.
Here's the android demo:
https://github.com/user-attachments/assets/8880f647-25a9-45a8-bd6f-2cf01650c141
iOS:
https://github.com/user-attachments/assets/68da485c-8127-4bc8-875a-05402b3c94e2
I'm trying this out on Linux Mint rustc 1.85.1 and am encountering a few issues:
- Had to comment out tests at the end of
packages/subsecond/subsecond-cli-support/src/wasm.rssince I don't have the files that areinclude_bytes!
Desktop app had these issues:
- asset files weren't included
asset!macros panic on rebuilds (hot patches?).- When it successfully builds, it writes the patch and outputs symbol not found
_Unwind_Resumeand symbol not foundmemcpy. and build failsbuild panicked, not yet implemented
Trying wasm and first build fails rust-lld with note: rust-lld: error: unknown argument: -Wl,--whole-archive,-Wl,--no-gc-sections,-Wl,--export-all and a bunch of warnings: warning x archive member y is neither wasm object file nor llvm bitcode
Edit: looks like wasm might not have been ready yet.
there were some issues with wasm that have now been fixed.
It should be possible to run the mini-cli I built for the harness with
RUST_LOG=info cargo run --package subsecond-cli -- --target wasm32-unknown-unknown
currently we aren't running the manganis step on the patch to register new assets. we need to do that. I haven't tried it with asset!() at all so I guess there might be other panics too, potentially related to hashes changing.
Also the todo!() on patching on x86 is expected to be not working right now since I've only tinkered with ld64 to know what args to pass to it:
https://github.com/DioxusLabs/dioxus/blob/84f98fe7e75449e8f99d2a26cbefd1cba665b466/packages/subsecond/subsecond-cli/src/main.rs#L498-L555
I'm assuming the error about memcpy is due to a similar reason (not passing linker flags for x86 at all):
https://github.com/DioxusLabs/dioxus/blob/84f98fe7e75449e8f99d2a26cbefd1cba665b466/packages/subsecond/subsecond-cli/src/main.rs#L346
Though I think some of these are actually fixed with dx itself though wasm isn't properly integrated yet.
There are some pretty bag bugs in wasm that seem to be squashed now. Our state-preservation engine is naive right now (invalidates every hotpatch call) so we need to wire it up to the object file diffing logic from here:
https://github.com/DioxusLabs/dioxus/blob/84f98fe7e75449e8f99d2a26cbefd1cba665b466/packages/subsecond/subsecond-cli-support/src/partial.rs#L53
I was hardcoding the wasm linker before which I shouldn't be doing anymore. The fact that those args are being rejected seems to be a mismatch in linker or us incorrectly generating the stub object file (probably due to a panic or early bail).
Here's a little video of wasm now with all its bugs fixed:
https://github.com/user-attachments/assets/a5636fa7-4e3a-41dd-a0f3-3e73a54d576d
https://github.com/rust-lang/rust/issues/139265
I'm not sure if this has already been noted, but if not: the usage of __rust_alloc will break in the upcoming stable rust release as that symbol will be mangled.
https://github.com/user-attachments/assets/b81f1a60-b6b2-422d-a536-d9e0bcd75221
LOTS of improvements.
- WASM patches are fully relocatable, not requiring any offset information from the CLI
- WASM support in dx now!
- WASM patches itself, not requiring any JS glue
I've now tested that the CLI patches all platforms I can test (mac/linux/android/ios/wasm). Will need to test windows before releasing.
I have yet to wire up fullstack + assets but hopeful those should go quickly.
https://github.com/user-attachments/assets/a1e53c1c-aa8b-488c-8d5c-6ce4a425c5b2
Probably the final update since things are getting close. Simultaneous frontend and frontend hotpatching!
Now I mostly just need to clean things up and make a few things more bullet-proof:
- better runtime integration (nuking components whose hooks have changed)
- more "correct" about passing linker flags to the target
- more "chrome" - ie a toast icon
- running manganis on the patch
- resolving merge conflicts and updating to axum 0.8
- better errors
- better configuration
- wasm loading patches on page reload
I would really like to make regular patches relocatable since the websocket requirement now means the CLI needs to remember state about connected clients. Would be ideal if the patching system could just modify the GOT directly. This is basically what we do with WASM now, but by intercepting the import map.
Just saw this PR out of draft so thought of giving it a shot. In MacOS, IOS everything looks amazing and hotpatching is working. But in wasm, i am having this when trying to change even basic string from fullstack basic example.
18:57:31 [server] DEBUG pooling idle connection for ("https", httpbin.org)
18:57:31 [dev] [200] /apple-touch-icon.png
18:57:31 [server] DEBUG pooling idle connection for ("https", httpbin.org)
18:57:31 [dev] [200] /apple-touch-icon-precomposed.png
18:57:31 [dev] [200] /wasm/dx_test_bg.wasm
18:57:31 [server] DEBUG pooling idle connection for ("https", httpbin.org)
18:57:31 [dev] [200] /favicon.ico
18:57:42 [dev] Failed to hot-patch app: Failed to perform hotpatch: Expected to find GOT.func entry in ifunc table but it was missing: _ZN4core3fmt3num3imp54_$LT$impl$u20$core..fmt..Display$u20$for$u20$usize$GT$3fmt17h6d9dbc09b6dc47c8E -> Ok(Id { Did all symbols make it into the static lib?
18:57:42 [dev] Starting full rebuild: Failed to perform hotpatch: Expected to find GOT.func entry in ifunc table but it was missing: _ZN4core3fmt3num3imp54_$LT$impl$u20$core..fmt..Display$u20$for$u20$usize$GT$3fmt17h6d9dbc09b6dc47c8E -> Ok(Id { idDid all symbols make it into the static lib?
18:57:50 [server] DEBUG Listening on 127.0.0.1:49312
18:57:49 [dev] Build completed in 3629ms
18:57:50 [server] DEBUG connecting to 18.205.89.57:443
18:57:50 [server] DEBUG connected to 18.205.89.57:443
18:57:50 [server] DEBUG pooling idle connection for ("https", httpbin.org)
Just saw this PR out of draft so thought of giving it a shot. In MacOS, IOS everything looks amazing and hotpatching is working. But in wasm, i am having this when trying to change even basic string from fullstack basic example.
18:57:31 [server] DEBUG pooling idle connection for ("https", httpbin.org) 18:57:31 [dev] [200] /apple-touch-icon.png 18:57:31 [server] DEBUG pooling idle connection for ("https", httpbin.org) 18:57:31 [dev] [200] /apple-touch-icon-precomposed.png 18:57:31 [dev] [200] /wasm/dx_test_bg.wasm 18:57:31 [server] DEBUG pooling idle connection for ("https", httpbin.org) 18:57:31 [dev] [200] /favicon.ico 18:57:42 [dev] Failed to hot-patch app: Failed to perform hotpatch: Expected to find GOT.func entry in ifunc table but it was missing: _ZN4core3fmt3num3imp54_$LT$impl$u20$core..fmt..Display$u20$for$u20$usize$GT$3fmt17h6d9dbc09b6dc47c8E -> Ok(Id { Did all symbols make it into the static lib? 18:57:42 [dev] Starting full rebuild: Failed to perform hotpatch: Expected to find GOT.func entry in ifunc table but it was missing: _ZN4core3fmt3num3imp54_$LT$impl$u20$core..fmt..Display$u20$for$u20$usize$GT$3fmt17h6d9dbc09b6dc47c8E -> Ok(Id { idDid all symbols make it into the static lib? 18:57:50 [server] DEBUG Listening on 127.0.0.1:49312 18:57:49 [dev] Build completed in 3629ms 18:57:50 [server] DEBUG connecting to 18.205.89.57:443 18:57:50 [server] DEBUG connected to 18.205.89.57:443 18:57:50 [server] DEBUG pooling idle connection for ("https", httpbin.org)
Hmmmm looked into it and it seems to be an issue with code de-duplication and wasm-bindgen exports/imports lying around. The default opt-level the wasm-dev profile uses is 1 which causes this particular issue with fullstack builds. Non-fullstack builds don't run into it immediately, so I'm assuming somewhere in the dependency path, we're pulling in some code that leaves wasm-bindgen artifacts in the patch.
This means we probably do need to run wasm-bindgen on the patches, but we don't necessarily want to use any of the output JS (just the transforms) unless we can find a way to merge the JS together. WASM is the only platform with a significant post-processing step and has been the most challenging thus far.
If you try it out with opt-level 0 on WASM I think it should work today.
Pure web hello world example, stuck for a quite long time in writing Type and finally (Similar behaviour for fullstack app as well)
15:29:07 [dev] Jump table: {}
15:29:07 [dev] Hot-patching: src/main.rs took 93237ms
Opt Level:
[profile.wasm-dev]
inherits = "dev"
opt-level = 0
Client is not updated
Tracing
"/Users/wheregmis/.rustup/toolchains/stable-aarch64-apple-darwin/bin/rustc",
"--crate-name",
"dx_test",
"--edition=2021",
"src/main.rs",
"--error-format=json",
"--json=diagnostic-rendered-ansi,artifacts,future-incompat",
"--crate-type",
"bin",
"--emit=dep-info,link",
"-C",
"embed-bitcode=no",
"-C",
"debuginfo=2",
"--cfg",
"feature=\"web\"",
"--check-cfg",
"cfg(docsrs,test)",
"--check-cfg",
"cfg(feature, values(\"default\", \"desktop\", \"mobile\", \"web\"))",
"-C",
"metadata=c69cd75cbf517ac9",
"-C",
"extra-filename=-004504ce2889265d",
"--out-dir",
"/Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps",
"--target",
"wasm32-unknown-unknown",
"-C",
"incremental=/Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/incremental",
"-L",
"dependency=/Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps",
"-L",
"dependency=/Users/wheregmis/Documents/GitHub/dx_test/target/wasm-dev/deps",
"--extern",
"dioxus=/Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/libdioxus-9328d7c3eea62339.rlib",
"-Clinker=/Users/wheregmis/.cargo/bin/dx",
"-Csave-temps=true",
"-Clink-dead-code",
"-Clink-arg=--no-gc-sections",
"-Clink-arg=--growable-table",
"-Clink-arg=--whole-archive",
"-Clink-arg=--export-table",
"-Clink-arg=--export-memory",
"-Clink-arg=--emit-relocs",
"-Clink-arg=--export=__stack_pointer",
"-Clink-arg=--export=__heap_base",
"-Clink-arg=--export=__data_end",
"-Crelocation-model=pic",
]
15:27:34 [cargo] {"$message_type":"diagnostic","message":"failed to connect to jobserver from environment variable `CARGO_MAKEFLAGS=\"-j --jobserver-fds=8,9 --jobserver-auth=8,9\"`: cannot open file descriptor 8 from the jobserver environment variable value: Bad file descriptor (os error 9)","code":null,"level":"warning","spans":[],"children":[{"message":"the build environment is likely misconfigured","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: failed to connect to jobserver from environment variable `CARGO_MAKEFLAGS=\"-j --jobserver-fds=8,9 --jobserver-auth=8,9\"`: cannot open file descriptor 8 from the jobserver environment variable value: Bad file descriptor (os error 9)\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: the build environment is likely misconfigured\u001b[0m\n\n"}
15:27:34 [cargo] {"$message_type":"artifact","artifact":"/Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.d","emit":"dep-info"}
15:27:34 [cargo] {"$message_type":"artifact","artifact":"/Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.wasm","emit":"link"}
15:27:34 [dev] Linker output during thin linking: rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.008cb87q20ajeurs5q5am7360.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.05v0m86sppmeam3k1ee9lxhxl.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.0g4v8gq5nh5iuvc7zuaib2qo4.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.0lg9zddquj2b9dc3ctkfxb11s.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.0t5qq1z9q31lvzlaensilvfj0.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.1fy4qqkublmy6o49blzettp1a.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.1njcts7j83ro4mx987f2bb6du.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.1qony8w2h2px9ad0z3h9tqep4.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.35i76j7fchflks2oswhysqvgk.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.35rjtyrdint6w8k6ctbdma91y.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3g61dldmxw00vawtnxu71cpv6.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3gtwmtucc5zi88ujih8d678ez.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3nhr790py7ck7iklpnfs33cih.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3odgahmc14qb1s11r12zvgebf.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3w1s5za49s0hpmudeagpcmx3q.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3y5hanxd544pchaep57sfphrn.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.4b0pofh8bpcpa4y9s23mtrnek.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.4e45rvu79pyivz5867iz4ecco.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.4oqxxn1jh4tgt3te23n5y0ooh.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.4scmqsovnpwgzxiz4ls1kxls7.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.4t2ntvoykmho2pv7xz4h0zf0v.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.50pjswy3ima3r0rjx5lr688nl.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.5kssxgetn83d8561oqwa57bjc.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.5uthm6v2y9gl1uoac0e3jtp1l.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.69znwe656rgrcxeehmwd9bhzu.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.6ya4q6k4dq4n82fxr5opzhhcj.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.6yw6mc05mhz06lfiw9nd50ujc.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.72sw1pr9nlfopo4oti89nqcu9.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.7ds8ixk6oqa628ta6c9elffxs.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.8m84thoie654mr2je3ain5vgy.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.8x9ycq2797x9nxh6vkuf4hi9f.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.9fa1ku0atiup9pnhun6khv2z0.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.9noa7fs52z60r4838xqd5p1pm.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.9q172lj4uc4ay6p9c8ilc5lun.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.9vhtasoqz9zyhm9m9tc82yz54.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.9x4ih0vtolahy4juzkhjvvlxh.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.arl09yqyyduimwfuefq3qwlss.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.aw0rpnq08bbszh2j3tw0n2cdg.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.b0y0ry4w16iqip49vma9n7c80.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.b545sfebx8cz14ywlxr0ccyzn.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.bcwcsmk0xv4ymuhv5z7f6m0c5.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.beef7knoyq4nxvyags36wzzmf.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.bqrnxu73t0gvvf6e9wytn5s1j.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.bt4ti6e8bnecbyvokgpx9742x.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.bvh8bhokay1celoqzu8edrlwt.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.bydy48t44sbeoz4mizll5zyf7.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.cihep6yctkbp5ckejx3svefe9.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.clom9cgrr3spltj1delyd760x.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.djrgkcf0wwxjgk0cfb8b0umub.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.ehnowmxbwijcx0r03w8owyvme.rcgu.o
rust-lld: Loading: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.f4ob0tb8ukctsto4f2xvg4chi.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.008cb87q20ajeurs5q5am7360.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.05v0m86sppmeam3k1ee9lxhxl.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.0g4v8gq5nh5iuvc7zuaib2qo4.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.0lg9zddquj2b9dc3ctkfxb11s.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.0t5qq1z9q31lvzlaensilvfj0.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.1fy4qqkublmy6o49blzettp1a.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.1njcts7j83ro4mx987f2bb6du.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.1qony8w2h2px9ad0z3h9tqep4.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.35i76j7fchflks2oswhysqvgk.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.35rjtyrdint6w8k6ctbdma91y.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3g61dldmxw00vawtnxu71cpv6.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3gtwmtucc5zi88ujih8d678ez.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3nhr790py7ck7iklpnfs33cih.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3odgahmc14qb1s11r12zvgebf.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3w1s5za49s0hpmudeagpcmx3q.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.3y5hanxd544pchaep57sfphrn.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.4b0pofh8bpcpa4y9s23mtrnek.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.4e45rvu79pyivz5867iz4ecco.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.4oqxxn1jh4tgt3te23n5y0ooh.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.4scmqsovnpwgzxiz4ls1kxls7.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.4t2ntvoykmho2pv7xz4h0zf0v.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.50pjswy3ima3r0rjx5lr688nl.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.5kssxgetn83d8561oqwa57bjc.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.5uthm6v2y9gl1uoac0e3jtp1l.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.69znwe656rgrcxeehmwd9bhzu.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.6ya4q6k4dq4n82fxr5opzhhcj.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.6yw6mc05mhz06lfiw9nd50ujc.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.72sw1pr9nlfopo4oti89nqcu9.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.7ds8ixk6oqa628ta6c9elffxs.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.8m84thoie654mr2je3ain5vgy.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.8x9ycq2797x9nxh6vkuf4hi9f.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.9fa1ku0atiup9pnhun6khv2z0.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.9noa7fs52z60r4838xqd5p1pm.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.9q172lj4uc4ay6p9c8ilc5lun.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.9vhtasoqz9zyhm9m9tc82yz54.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.9x4ih0vtolahy4juzkhjvvlxh.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.arl09yqyyduimwfuefq3qwlss.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.aw0rpnq08bbszh2j3tw0n2cdg.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.b0y0ry4w16iqip49vma9n7c80.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.b545sfebx8cz14ywlxr0ccyzn.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.bcwcsmk0xv4ymuhv5z7f6m0c5.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.beef7knoyq4nxvyags36wzzmf.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.bqrnxu73t0gvvf6e9wytn5s1j.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.bt4ti6e8bnecbyvokgpx9742x.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.bvh8bhokay1celoqzu8edrlwt.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.bydy48t44sbeoz4mizll5zyf7.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.cihep6yctkbp5ckejx3svefe9.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.clom9cgrr3spltj1delyd760x.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.djrgkcf0wwxjgk0cfb8b0umub.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.ehnowmxbwijcx0r03w8owyvme.rcgu.o
rust-lld: Processing: /Users/wheregmis/Documents/GitHub/dx_test/target/wasm32-unknown-unknown/wasm-dev/deps/dx_test-004504ce2889265d.f4ob0tb8ukctsto4f2xvg4chi.rcgu.o
rust-lld: -- processStubLibrariesPreLTO
rust-lld: -- processStubLibraries
rust-lld: -- done processStubLibraries
rust-lld: -- createOutputSegments
rust-lld: -- createSyntheticSections
rust-lld: -- layoutMemory
rust-lld: mem: global base = 0
rust-lld: mem: .rodata offset=0 size=2249 align=2
rust-lld: mem: .data offset=2252 size=588 align=2
rust-lld: mem: .bss offset=2840 size=88 align=2
rust-lld: mem: static data = 2928
rust-lld: mem: total pages = 1
rust-lld: -- populateTargetFeatures
rust-lld: Allowed feature: mutable-globals
rust-lld: Allowed feature: reference-types
rust-lld: Allowed feature: multivalue
rust-lld: Allowed feature: sign-ext
rust-lld: -- combineOutputSegments
rust-lld: -- createSyntheticSectionsPostLayout
rust-lld: -- populateProducers
rust-lld: -- calculateImports
rust-lld: -- scanRelocations
rust-lld: -- finalizeIndirectFunctionTable
rust-lld: -- createSyntheticInitFunctions
rust-lld: -- assignIndexes
rust-lld: -- calculateInitFunctions
rust-lld: -- calculateTypes
rust-lld: -- calculateExports
rust-lld: -- calculateCustomSections
rust-lld: calculateCustomSections
rust-lld: -- populateSymtab
rust-lld: -- checkImportExportTargetFeatures
rust-lld: -- addSections
rust-lld: addSection: CUSTOM(dylink.0)
rust-lld: addSection: TYPE
rust-lld: addSection: IMPORT
rust-lld: addSection: FUNCTION
rust-lld: addSection: GLOBAL
rust-lld: addSection: EXPORT
rust-lld: addSection: START
rust-lld: addSection: ELEM
rust-lld: addSection: CODE
rust-lld: addSection: DATA
rust-lld: createCustomSections
rust-lld: addSection: CUSTOM(.debug_abbrev)
rust-lld: addSection: CUSTOM(.debug_info)
rust-lld: addSection: CUSTOM(.debug_ranges)
rust-lld: addSection: CUSTOM(.debug_str)
rust-lld: addSection: CUSTOM(.debug_line)
rust-lld: addSection: CUSTOM(.debug_loc)
rust-lld: addSection: CUSTOM(name)
rust-lld: addSection: CUSTOM(producers)
rust-lld: addSection: CUSTOM(target_features)
rust-lld: Defined Functions: 179
rust-lld: Defined Globals : 9
rust-lld: Defined Tags : 0
rust-lld: Defined Tables : 0
rust-lld: Function Imports : 95
rust-lld: Global Imports : 9
rust-lld: Tag Imports : 0
rust-lld: Table Imports : 1
rust-lld: -- finalizeSections
rust-lld: createHeader: CUSTOM(dylink.0) body=16 total=18
rust-lld: createHeader: TYPE body=163 total=166
rust-lld: createHeader: IMPORT body=8988 total=8991
rust-lld: createHeader: FUNCTION body=181 total=184
rust-lld: createHeader: GLOBAL body=54 total=56
rust-lld: createHeader: EXPORT body=16992 total=16996
rust-lld: createHeader: START body=1 total=3
rust-lld: createHeader: ELEM body=31 total=33
rust-lld: createHeader: CODE body=52998 total=53002
rust-lld: Data segment: size=2928, startVA=0, name=.data
rust-lld: createHeader: DATA body=2935 total=2938
rust-lld: createHeader: CUSTOM(.debug_abbrev) body=18356 total=18360
rust-lld: createHeader: CUSTOM(.debug_info) body=329596 total=329600
rust-lld: createHeader: CUSTOM(.debug_ranges) body=4998 total=5001
rust-lld: createHeader: CUSTOM(.debug_str) body=133849 total=133853
rust-lld: createHeader: CUSTOM(.debug_line) body=31482 total=31486
rust-lld: createHeader: CUSTOM(.debug_loc) body=40 total=42
rust-lld: createHeader: CUSTOM(name) body=24961 total=24965
rust-lld: createHeader: CUSTOM(producers) body=77 total=79
rust-lld: createHeader: CUSTOM(target_features) body=73 total=75
rust-lld: -- writeMapFile
rust-lld: -- openFile
rust-lld: writing: /Users/wheregmis/Documents/GitHub/dx_test/target/dx/dx_test/debug/web/public/wasm/libdx_test-patch-1745954854218.wasm
rust-lld: -- writeSections
rust-lld: writing IMPORT
rust-lld: writing FUNCTION
rust-lld: writing START
rust-lld: writing CUSTOM(.debug_info) offset=100755 size=329600 chunks=50
rust-lld: writing CUSTOM(producers)
rust-lld: writing CUSTOM(name)
rust-lld: writing CUSTOM(target_features)
rust-lld: writing CUSTOM(.debug_loc) offset=600695 size=42 chunks=1
rust-lld: writing CUSTOM(.debug_line) offset=569209 size=31486 chunks=50
rust-lld: writing CUSTOM(.debug_ranges) offset=430355 size=5001 chunks=34
rust-lld: writing CUSTOM(.debug_abbrev) offset=82395 size=18360 chunks=50
rust-lld: writing DATA offset=79457 size=2938 body=2935
rust-lld: writing CODE offset=26455 size=53002
rust-lld: headersize=4
rust-lld: codeheadersize=2
rust-lld: writing ELEM
rust-lld: writing EXPORT
rust-lld: writing GLOBAL
rust-lld: writing CUSTOM(dylink.0)
rust-lld: writing CUSTOM(.debug_str) offset=435356 size=133853 chunks=1
rust-lld: writing TYPE
Pure web hello world example, stuck for a quite long time in writing Type and finally (Similar behaviour for fullstack app as well)
Think I figured out what was going on, two issues in wasm-bindgen itself that we need to work around (see the tagged issues). I'm going to continue and clean it up but it should work now with opt-level=1:
https://github.com/user-attachments/assets/3bc36fdb-e161-4d7b-a817-2e53e9406d7b
also fwiw the reason the client isn't updating is because it's most likely missing an import (which was the underlying issue) but you should see that in the console logs.
Magical 🎉
The docsite now works under hotpatch :)
https://github.com/user-attachments/assets/385d49f7-11a2-46e6-baa4-bbb888c35e53
Ran into a few bugs and had to fix a few things along the way:
- wasm-bindgen transformations don't work on dynamic modules
- wasm-bindgen snippets cause crazy imports if not handled properly
- high opt-levels cause code folding and merging which can subtlety break the jump table
- low opt-levels cause "too many locals" bug in some functions
- gemini wrote some code for me that had a very subtle bug:
for (i, param) in params.iter().enumerate() {
body.local_get(module.locals.add(*param));
}
body.call(funcid);
let local_func = builder.local_func(params.iter().map(|ty| module.locals.add(*ty)).collect());
// vs
let locals = params
.iter()
.map(|ty| module.locals.add(*ty))
.collect::<Vec<_>>();
for l in locals.iter() {
body.local_get(*l);
}
body.call(funcid);
let local_func = builder.local_func(locals);
ANYWAYS, things should be working smoothly across web, desktop, and mobile with all the bells and whistles.
https://github.com/user-attachments/assets/e0412098-2bc1-471e-a366-bb34223a663d
UPDATE: added some caching - the docsite patches in 1.3s
https://github.com/user-attachments/assets/4fa822b9-1a8a-4434-983a-6fe8dcebc7ed
https://github.com/user-attachments/assets/9a6f7423-1e08-4464-9842-21b81a5f4c89
did not realize windows had a different calling convention (and a number of other annoyances...) - but windows support is properly tested on arm. we now have https://liveplusplus.tech but for Rust and all platforms.
Two and half months for Rust hot patching isn’t so bad :)
Hoping to get an alpha out for 0.7 tomorrow!
Will there be guides to integrate this into other Rust programs, such as Bevy / Leptos, or even just axum projects?
I'd love to use a generic-ish library and get magical hot reloading in Rust