This package tries to adhere to semver.
The hot_module
macro now allows to customize the library filename e.g. loaded_lib_name_template = "{lib_name}_hot_{pid}_{load_counter}"
will result in a library name that is unique per process than the default {lib_name}-hot-{load_counter}
. With the optional uuid
feature you can make make the name fully random.
Thank you @CryoMyst!
notify
v6 should be more reliable
- Make it possible for users to specify what crate name is inside the generated module code.
- See #28
Change the default lib_dir
and allow expressions instead of just string literals for lib_dir
and dylib
This changes the defaults of lib_dir
and dylib
properties of the hot_module
macro.
Previously, specifying #[hot_module(dylib = "lib")]
would expand into #[hot_module(dylib = "lib", lib_dir = "target/debug")]
(debug build) or #[hot_module(dylib = "lib", lib_dir = "target/release")]
.
Now the lib_dir
value is by defaults are:
#[hot_module(dylib = "lib", lib_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/target/debug"))]
and#[hot_module(dylib = "lib", lib_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/target/release"))]
Also, both dylib
and lib_dir
can now be expressions (that should evaluate to something string like) instead of just literal strings.
Changing the defaults actually constitutes a breaking change. I'm not bumping the minor version as I assume no one depended on that. If this is not correct and that change breaks something I hereby sincerly apologies. You can get the old behavior back with
#[hot_module(
dylib = "lib",
lib_dir = if cfg!(debug_assertions) { "target/debug" } else { "target/release" },
file_watch_debounce = 500
)]
/* ... */
This change should fix the case when a program changes the current working directory and library loading doesn't work anymore thereafter. This was first reported in #22.
As reported, when using the wait functions but not calling a hot-reloadable library function, the wait functions would continue to block even if the library was changed.
This release fixes that, calling wait_for_about_to_reload
and wait_for_reload
should always return once a library change was made.
On macos spurious crashes can happen after reloading the library. In order to avoid this, we will codesign the library when the codesign
binary is available.
It is now possible to use a simple update check to test if the library was reloaded:
#[hot_lib_reloader::hot_module(dylib = "lib")]
mod hot_lib {
/* ... */
#[lib_updated]
pub fn was_updated() -> bool {}
}
This can simplify code that wants to just figure out if a change happened and would have had to use the version counter for that.
Note that this function only returns true
_onceafter a reload. The next time you call that function, if no reload has occurred again, it will return
false`.
hot_functions_from_file!("path/to/file.rs")
and define_lib_reloader!(...)
expect file path to be relative to the project root, not relative to the file they appear in.
See #13 for the background.
- The hot-lib-reloader won't log to stdout/stderr anymore in the running app. It now fully uses the
log
crate. UseRUST_LOG=hot_lib_reloader=trace
for debugging. - Fix macro expansion and code completion with rust-analyzer
- No more requirement to use Rust nightly!
- Version counter can be optionally exposed from
hot_module
:
#[hot_module(dylib = "lib")]
mod hot_lib {
/* ... */
#[lib_version]
pub fn version() -> usize {}
}
- Allow to specify the debounce duration for file changes in milliseconds. This is 500ms by default. If you see multiple updates triggerd for one recompile (can happen the library is very large), increase that value. You can try to decrease it for faster reloads. With small libraries / fast hardware 50ms or 20ms should work fine.
#[hot_module(dylib = "lib", file_watch_debounce = 50)]
/* ... */
hot_lib::version()
will then return a monotonically increasing number, starting with 0.
Each library reload will increase the counter.
Make the logging about attempted lib-loader write locks less verbose.
We used a convoluted half-baked ref counting scheme for access to symbols while not needing to mutex lock the lib loader during a call (so that recursive calls work)
This has been cleaned up with the use of RwLock
s instead. This should also fix
spurious crashes during hot updates that were likely caused by symbols actually
being used (b/c the prev solution wasn't really thread safe).
Also add a no-mangle-if-debug crate that allows to #[no_mangle]
functions but only in debug mode. The use of this is optional and nothing about hot-lib-reloader itself changes. This addresses #10.
#[lib_change_subscription]
now returns the LibReloadObserver
type that wraps the mpsc channel.
#[lib_change_subscription]
pub fn subscribe() -> hot_lib_reloader::LibReloadObserver {}
It provides multiple methods to wait for about-to-reload and reloaded events.
Also add lots of documentation, a test, and a example around that.
Added support for getting lib reload events.
Inside a hot_module
, the following creates a function that can be used to subscribe:
#[lib_change_subscription]
pub fn subscribe() -> std::sync::mpsc::Receiver<hot_lib_reloader::ChangedEvent> {}
Using file hashes to figure out when a file actually changed, notify
alone isn't enough.
The file change strategies on the different OSes seem to be quite different.
The lib might be removed or re-linked or simply overwritten.
The file change events in each case are quite different and in the case of removal, notify
does not always seem to get events when the file is recreated.
In addition, on macOS copying lib*.dylib
to lib*-hot.dylib
seems to trigger a file change event for lib*.dylib
...
So using a hash is the simplest way to figure out if the dylib actually changed and provides a reliable way to trigger a recompile.
- added the
#[hot_module]
attribute macro - manage the reloader internally
- provide hot reloadable functions as part of the hot_module with the identical interface they normally have
- tests & CI setup
- more documentation and examples
- Subscribe to lib changes with
__lib_loader_subscription()
- deprecated
define_lib_reloader
- lib reloader updates via events
- Fix how library files get renamed
- Add note to bevy example for how to use it on Windows
- Fix reloads on macOS M1
- Markdown fixes
- demo gif in readme
- Reimplemented the
define_lib_reloader
macro as proc macro. It has a somewhat different syntax now (breaking change)
define_lib_reloader
now allows to load function signatures from source files- support for hot-reloading bevy systems
- Convenience macro
define_lib_reloader!
- Windows support
- Don't load from original lib, only reload from single lib file
LibReloader
, providingnew()
,update()
,get_symbol()
.