Expand description
§Bevy Simple Subsecond System
Hotpatch your Bevy systems, allowing you to change their code while the app is running and directly seeing the results! This is a intermediate solution you can use until Bevy has implement this feature upstream.
Powered by Dioxus’ subsecond
Please report all hotpatch-related problems to them :)
⚠️ Should work on Windows somehow, but I haven’t yet figured out how! Let me know if you made it!
https://github.com/user-attachments/assets/a44e446b-b2bb-4e10-81c3-3f20cccadea0
§First Time Installation
First, we’ll install cargo-binstall. It’s not strictly required, but it will make the setup much quicker. Click your OS below on instructions for how to do this
Windows
Set-ExecutionPolicy Unrestricted -Scope Process; iex (iwr "https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.ps1").ContentmacOS
brew install cargo-binstallor, if you don’t use brew, same as on Linux.
Linux
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bashBuild from source
cargo install cargo-binstallNow, we need to install the Dioxus CLI of the newest alpha build:
cargo binstall dioxus-cli@0.7.0-alpha.0Then make sure you’re not using LD as your linker. Click your OS below on instructions for how to do this
In case you already configured a linker, setting
rustflags = ["-C", "link-arg=-fuse-ld=/path/to/your/linker"]is surprisingly not enough!
Windows
Sorry friend, I didn’t test this. All I know is that you can install rust-lld.exe by running
cargo binstall cargo-binutils
rustup component add llvm-tools-previewmacOS
You’re in luck! The default linker on macOS is already something other than LD. You don’t have to change a thing :)
Linux
Download clang and mold for your distribution, e.g.
sudo apt-get install clang moldThen, replace your system ld with a symlink to mold. The most brutal way to do this is:
cd /usr/bin
sudo mv ld ld-real
sudo ln -s mold ldOn NixOS you can do this in a shell by replacing:
pkgs.mkShell {
# ..
}with:
pkgs.mkShell.override {
stdenv = pkgs.stdenvAdapters.useMoldLinker pkgs.clangStdenv;
} {
# ..
}§Usage
Add the crate to your dependencies:
cargo add bevy_simple_subsecond_systemThen add the plugin to your app:
use bevy::prelude::*;
use bevy_simple_subsecond_system::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(SimpleSubsecondPlugin::default())
// rest of the setup
.run();
}
Now you can annotate your systems with #[hot] to enable hotpatching for them:
use bevy_simple_subsecond_system::prelude::*;
#[hot]
fn greet() {
info!("Hello from a hotpatched system! Try changing this string while the app is running!")
}Note that greet is a regular Bevy system, so use whatever parameters you’d like.
After adding the system to your app, run it with
dx serve --hot-patchNow try changing the string and saving the file while the app is running. If all goes well, it should print your new string!
Full code
use bevy::prelude::*;
use bevy_simple_subsecond_system::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(SimpleSubsecondPlugin::default())
.add_systems(Update, greet)
.run();
}
#[hot]
fn greet() {
info!("Hello from a hotpatched system! Try changing this string while the app is running!")
}§Examples
Run the examples with
dx serve --hot-patch --example name_of_the_examplee.g.
dx serve --hot-patch --example patch_on_update§Known Limitations
- Cannot combine mold as your Rust linker with a global target dir
- Using this breaks dynamic linking
- A change in the definition of structs that appear in hot-patched systems at runtime will result in your query failing to match, as that new type does not exist in
Worldyet.- Practically speaking, this means you should not change the definition of
Resources andComponents of your system at runtime
- Practically speaking, this means you should not change the definition of
- All hotpatched systems run as exclusive systems, meaning they won’t run in parallel
- Only the topmost binary is hotpatched, meaning your app is not allowed to have a
lib.rsor a workspace setup. - Attaching a debugger is problaby not going to work. Let me know if you try!
- I did not test all possible ways in which systems can be used. Does piping work? Does
bevy_mod_debugdumpstill work? Maybe. Let me know! - Some signatures are not supported, see the tests. Some have
#[hot]commented out to indicate this - Only functions that exist when the app is launched are considered while hotpatching. This means that if you have a system
Athat calls a functionB, changingBwill only work at runtime if that function existed already when the app was launched.
§Compatibility
| bevy | bevy_simple_subsecond_system |
|---|---|
| 0.16 | 0.1 |
Re-exports§
pub use dioxus_devtools;
Modules§
- prelude
- Everything you need to use hotpatching
Structs§
- HotPatched
- Event sent when the hotpatch is applied.
- Simple
Subsecond Plugin - The plugin you need to add to your app: