From e22236f201613d3e4864b4ca8af386321ec9cc7d Mon Sep 17 00:00:00 2001 From: Jaroslaw Konik Date: Tue, 27 May 2025 18:58:02 +0200 Subject: [PATCH] dynamic resolutions docs --- Cargo.toml | 1 + book/src/ruby/installation.md | 10 ++++++++++ src/lib.rs | 30 ++++++++++++++++++++++++++++++ src/runtimes/ruby.rs | 4 ++++ 4 files changed, 45 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 10f089d..ad3fc0f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ mlua = { version = "0.9.8", features = [ magnus = { version = "0.7.1", optional = true } rb-sys = { version = "*", default-features = false, features = ["link-ruby", "ruby-static"], optional = true } crossbeam-channel = "0.5.15" +libc = "0.2.172" [[example]] name = "call_function_from_rust_rhai" diff --git a/book/src/ruby/installation.md b/book/src/ruby/installation.md index 40f291e..1dc0a82 100644 --- a/book/src/ruby/installation.md +++ b/book/src/ruby/installation.md @@ -38,3 +38,13 @@ bevy_scriptum = { version = "0.8", features = ["ruby"] } If you need a different version of bevy you need to use a matching bevy_scriptum version according to the [bevy support matrix](../bevy_support_matrix.md) + +Ruby also needs dynamic symbol resolution and since `bevy_scriptum` links Ruby +statically the following `build.rs` file is needed to be present in project +root directory. + +```rust +fn main() { + println!("cargo:rustc-link-arg=-rdynamic"); +} +``` diff --git a/src/lib.rs b/src/lib.rs index 0e83be6..94bad40 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -371,6 +371,10 @@ pub trait Runtime: Resource + Default { context: &Self::CallContext, args: Vec, ) -> Result; + + fn needs_rdynamic_linking() -> bool { + false + } } pub trait FuncArgs<'a, V, R: Runtime> { @@ -433,6 +437,19 @@ impl BuildScriptingRuntime for App { /// Adds a scripting runtime. Registers required bevy systems that take /// care of processing and running the scripts. fn add_scripting(&mut self, f: impl Fn(ScriptingRuntimeBuilder)) -> &mut Self { + #[cfg(debug_assertions)] + if R::needs_rdynamic_linking() { + if !is_rdynamic_linking() { + panic!( + "Missing `-rdynamic`: symbol resolution failed.\n\ + It is needed by {:?}.\n\ + Please add `println!(\"cargo:rustc-link-arg=-rdynamic\");` to your build.rs\n\ + or set `RUSTFLAGS=\"-C link-arg=-rdynamic\"`.", + std::any::type_name::() + ); + } + } + self.world_mut() .resource_mut::() .insert_after(Update, R::Schedule::default()); @@ -495,6 +512,19 @@ impl Default for Callbacks { } } +pub extern "C" fn is_rdynamic_linking() -> bool { + unsafe { + // Get a function pointer to itself + let addr = is_rdynamic_linking as *const libc::c_void; + let mut info: libc::Dl_info = std::mem::zeroed(); + + // Try to resolve symbol info + let result = libc::dladdr(addr, &mut info); + + result != 0 && !info.dli_sname.is_null() + } +} + pub mod prelude { pub use crate::{BuildScriptingRuntime as _, Runtime as _, Script}; } diff --git a/src/runtimes/ruby.rs b/src/runtimes/ruby.rs index b41262e..1ccccdd 100644 --- a/src/runtimes/ruby.rs +++ b/src/runtimes/ruby.rs @@ -505,6 +505,10 @@ impl Runtime for RubyRuntime { Ok(RubyValue::new(result)) }) } + + fn needs_rdynamic_linking() -> bool { + true + } } pub mod magnus {