rb static link

This commit is contained in:
Jaroslaw Konik 2025-05-19 07:00:00 +02:00
parent b2ebf08805
commit d0746fa5db
6 changed files with 31 additions and 14 deletions

7
.cargo/config.toml Normal file
View file

@ -0,0 +1,7 @@
[build]
# Without this flag, when linking static libruby, the linker removes symbols
# (such as `_rb_ext_ractor_safe`) which it thinks are dead code... but they are
# not, and they need to be included for the `embed` feature to work with static
# Ruby.
# rustflags = ["-C", "link-args=-lz", "-C", "link-dead-code=on"]
rustflags = ["-C", "link-args=-lz"]

View file

@ -13,7 +13,7 @@ keywords = ["bevy", "rhai", "scripting", "game", "gamedev"]
[features] [features]
lua = ["dep:mlua", "mlua/luajit"] lua = ["dep:mlua", "mlua/luajit"]
rhai = ["dep:rhai"] rhai = ["dep:rhai"]
ruby = ["dep:magnus"] ruby = ["dep:magnus", "dep:rb-sys"]
[dependencies] [dependencies]
bevy = { default-features = false, version = "0.16", features = ["bevy_asset", "bevy_log"] } bevy = { default-features = false, version = "0.16", features = ["bevy_asset", "bevy_log"] }
@ -32,6 +32,7 @@ mlua = { version = "0.9.8", features = [
"send", "send",
], optional = true } ], optional = true }
magnus = { version = "0.7.1", optional = true, features = ["embed"] } magnus = { version = "0.7.1", optional = true, features = ["embed"] }
rb-sys = { version = "*", default-features = false, features = ["link-ruby", "ruby-static"], optional = true }
crossbeam-channel = "0.5.15" crossbeam-channel = "0.5.15"
[[example]] [[example]]

View file

@ -1,7 +1,6 @@
function test_func(vec3) function test_func(vec3)
-- raise unless vec3.is_a?(Vec3) # TODO: BevyScriptum::Vec3 and add example how to include it globally like Sinatra does assert(vec3.x == 1.5)
-- raise unless vec3.x == 1.5 assert(vec3.y == 2.5)
-- raise unless vec3.y == 2.5 assert(vec3.z == -3.5)
-- raise unless vec3.z == -3.5
mark_success() mark_success()
end end

View file

@ -1,4 +1,5 @@
fn test_func(vec3) { fn test_func(vec3) {
// TODO: asser vec3 correctness if type_of(vec3) != "tests::rhai_tests::BevyVec3" { throw() }
mark_success() // TODO: assert x,y,z
mark_success();
} }

View file

@ -1,5 +1,5 @@
def test_func(vec3) def test_func(vec3)
raise unless vec3.is_a?(Bevy::Vec3) # TODO: BevyScriptum::Vec3 and add example how to include it globally like Sinatra does raise unless vec3.is_a?(Bevy::Vec3)
raise unless vec3.x == 1.5 raise unless vec3.x == 1.5
raise unless vec3.y == 2.5 raise unless vec3.y == 2.5
raise unless vec3.z == -3.5 raise unless vec3.z == -3.5

View file

@ -12,10 +12,13 @@ use bevy::{
tasks::futures_lite::io, tasks::futures_lite::io,
}; };
use magnus::{ use magnus::{
block::Proc, data_type_builder, function, value::Lazy, DataType, DataTypeFunctions, IntoValue, block::Proc,
Object, RClass, RModule, Ruby, TryConvert, TypedData, data_type_builder, function,
value::{Lazy, ReprValue},
DataType, DataTypeFunctions, IntoValue, Object, RClass, RModule, Ruby, TryConvert, TypedData,
}; };
use magnus::{method, prelude::*}; use magnus::{method, prelude::*};
use rb_sys::{ruby_finalize, ruby_init_stack, VALUE};
use serde::Deserialize; use serde::Deserialize;
use crate::{ use crate::{
@ -66,11 +69,18 @@ impl RubyThread {
let (sender, receiver) = crossbeam_channel::unbounded::<Box<dyn FnOnce(Ruby) + Send>>(); let (sender, receiver) = crossbeam_channel::unbounded::<Box<dyn FnOnce(Ruby) + Send>>();
let handle = thread::spawn(move || { let handle = thread::spawn(move || {
let _cleanup = unsafe { magnus::embed::init() }; unsafe {
let mut variable_in_this_stack_frame: VALUE = 0;
ruby_init_stack(&mut variable_in_this_stack_frame as *mut VALUE as *mut _);
rb_sys::ruby_init()
};
while let Ok(f) = receiver.recv() { while let Ok(f) = receiver.recv() {
let ruby = Ruby::get().expect("Failed to get a handle to Ruby API"); let ruby = Ruby::get().expect("Failed to get a handle to Ruby API");
f(ruby); f(ruby);
} }
unsafe {
ruby_finalize();
}
}); });
RubyThread { RubyThread {
@ -364,9 +374,9 @@ impl Runtime for RubyRuntime {
let ruby = magnus::Ruby::get().unwrap(); let ruby = magnus::Ruby::get().unwrap();
let method_name: magnus::value::StaticSymbol = let method_name: magnus::value::StaticSymbol =
ruby.class_object().funcall("__method__", ()).unwrap(); ruby.class_object().funcall("__method__", ()).unwrap();
let method_name = method_name.to_string(); let method_name = method_name.name().unwrap();
let callbacks = RUBY_CALLBACKS.lock().unwrap(); let callbacks = RUBY_CALLBACKS.lock().unwrap();
let f = callbacks.get(&method_name).unwrap(); let f = callbacks.get(method_name).unwrap();
let result = f( let result = f(
(), (),
args.iter() args.iter()
@ -422,7 +432,6 @@ impl Runtime for RubyRuntime {
})) }))
} }
// TODO: add test
fn call_fn_from_value( fn call_fn_from_value(
&self, &self,
value: &Self::Value, value: &Self::Value,