diff --git a/Cargo.toml b/Cargo.toml index 944221c7dd..61524ca720 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,8 @@ members = [ "examples/mobile", # Examples of using Bevy on no_std platforms. "examples/no_std/*", + # Examples of compiling Bevy with automatic reflect type registration for platforms without `inventory` support. + "examples/reflection/auto_register_static", # Benchmarks "benches", # Internal tools that are not published. @@ -2669,6 +2671,17 @@ description = "Demonstrates how to create and use type data" category = "Reflection" wasm = false +[[example]] +name = "auto_register_static" +path = "examples/reflection/auto_register_static/src/main.rs" +doc-scrape-examples = true + +[package.metadata.example.auto_register_static] +name = "Automatic types registartion" +description = "Demonstrates how to set up automatic reflect types registration for platforms without `inventory` support" +category = "Reflection" +wasm = false + # Scene [[example]] name = "scene" diff --git a/examples/reflection/auto_register_static/Cargo.toml b/examples/reflection/auto_register_static/Cargo.toml new file mode 100644 index 0000000000..a72120a7d3 --- /dev/null +++ b/examples/reflection/auto_register_static/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "auto_register_static" +version = "0.1.0" +edition = "2024" + +[lib] +# Our app must be a lib for static auto registration to work. +crate-type = ["lib"] + +[[bin]] +# Name of the binary must be the same as the name of the lib. +name = "auto_register_static" + +[dependencies] +bevy = { path = "../../../" } + +[lints] +workspace = true diff --git a/examples/reflection/auto_register_static/Makefile b/examples/reflection/auto_register_static/Makefile new file mode 100644 index 0000000000..7b47a20e13 --- /dev/null +++ b/examples/reflection/auto_register_static/Makefile @@ -0,0 +1,4 @@ +.PHONEY: run + +run: + BEVY_REFLECT_AUTO_REGISTER_STATIC=1 cargo run --features bevy/reflect_auto_register_static \ No newline at end of file diff --git a/examples/reflection/auto_register_static/README.md b/examples/reflection/auto_register_static/README.md new file mode 100644 index 0000000000..ac9f506116 --- /dev/null +++ b/examples/reflection/auto_register_static/README.md @@ -0,0 +1,16 @@ +# Automatic registration example for platforms without inventory support + +This example illustrates how to use automatic type registration of `bevy_reflect` on platforms that don't support `inventory`. + +To run the example, use the provided `Makefile` with `make run` or run manually by setting env var and enabling the required feature: +```sh +BEVY_REFLECT_AUTO_REGISTER_STATIC=1 cargo run --features bevy/reflect_auto_register_static +``` +This approach should generally work on all platforms, however it is less convenient and a slows down linking and it's recommended to use it only as a fallback. + +Here's a list of caveats of this approach: +1. `load_type_registrations!` macro must be called before constructing `App` or using `TypeRegistry::register_derived_types`. +2. All of the types to be automatically registered must be declared in a separate from `load_type_registrations!` crate. This is why this example uses separate `lib` and `bin` setup. +3. Registration function names are cached in `target/type_registrations`. Due to incremental compilation the only way to rebuild this cache is to build without `bevy/reflect_auto_register_static` (or `auto_register_static` if just using `bevy_reflect`) feature enabled and then rebuild again with this feature and `BEVY_REFLECT_AUTO_REGISTER_STATIC=1` environment variable set. Running `cargo clean` before recompiling is also an option, but it is even slower to do. + +If you're experiencing linking issues try running `cargo clean` before rebuilding. diff --git a/examples/reflection/auto_register_static/src/lib.rs b/examples/reflection/auto_register_static/src/lib.rs new file mode 100644 index 0000000000..e43f563e95 --- /dev/null +++ b/examples/reflection/auto_register_static/src/lib.rs @@ -0,0 +1,44 @@ +//! Demonstrates how to set up automatic reflect types registration for platforms without `inventory` support +use bevy::prelude::*; + +// The type that should be automatically registered. +// All types subject to automatic registration must be defined in `lib`, +// any `#[derive(Reflect)]` registration without the `bin` are not guaranteed to be registered automatically. +#[derive(Reflect)] +struct Struct { + a: i32, +} + +mod private { + mod very_private { + use bevy::prelude::*; + + // Works with private types too! + #[derive(Reflect)] + struct PrivateStruct { + a: i32, + } + } +} + +/// This is the main entrypoint, bin just forwards to it. +pub fn main() { + App::new() + .add_plugins(DefaultPlugins) + .add_systems(Startup, startup) + .run(); +} + +fn startup(reg: Res) { + let registry = reg.read(); + info!( + "Is `Struct` get registered? {}", + registry.contains(core::any::TypeId::of::()) + ); + info!( + "Type info of `PrivateStruct`: {:?}", + registry + .get_with_short_type_path("PrivateStruct") + .expect("Not registered") + ); +} diff --git a/examples/reflection/auto_register_static/src/main.rs b/examples/reflection/auto_register_static/src/main.rs new file mode 100644 index 0000000000..b9359d11a0 --- /dev/null +++ b/examples/reflection/auto_register_static/src/main.rs @@ -0,0 +1,10 @@ +//! Demonstrates how to set up automatic reflect types registration for platforms without `inventory` support +use auto_register_static::main as lib_main; +use bevy::reflect::load_type_registrations; + +fn main() { + // This must be called before our main to collect all type registration functions. + load_type_registrations!(); + // After running load_type_registrations! we just forward to our main. + lib_main(); +}