From 63b92d38150ec7072b00470721fe8acfe6fd0f66 Mon Sep 17 00:00:00 2001 From: Aeodyn Date: Fri, 8 Jan 2021 19:48:41 -0500 Subject: [PATCH 1/2] Add support for passing commandline arguments set in mkxp.json to the Ruby environment. --- binding/binding-mri.cpp | 21 ++++++++++++--------- mkxp.json | 6 ++++++ src/config.cpp | 4 +++- src/config.h | 2 ++ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/binding/binding-mri.cpp b/binding/binding-mri.cpp index abce48ca..50a08707 100644 --- a/binding/binding-mri.cpp +++ b/binding/binding-mri.cpp @@ -780,6 +780,8 @@ static void showExc(VALUE exc, const BacktraceData &btData) { } static void mriBindingExecute() { + Config &conf = shState->rtData().config; + #if RAPI_MAJOR >= 2 /* Normally only a ruby executable would do a sysinit, * but not doing it will lead to crashes due to closed @@ -791,16 +793,19 @@ static void mriBindingExecute() { RUBY_INIT_STACK; ruby_init(); rb_enc_set_default_external(rb_enc_from_encoding(rb_utf8_encoding())); + + std::vector rubyArgsC{""}; + for(const auto& string : conf.rubyArgs) + rubyArgsC.push_back(string.c_str()); + rubyArgsC.push_back("-e "); + + void *node = ruby_process_options(rubyArgsC.size(), const_cast(rubyArgsC.data())); + int state; + bool valid = ruby_executable_node(node, &state); + state = ruby_exec_node(node); #else ruby_init(); rb_eval_string("$KCODE='U'"); -#ifdef MKXPZ_JIT - const char *rubyOpts[] = {"--jit-verbose=1"}; - void *node = ruby_process_options(1, const_cast(rubyOpts); - int state; - bool valid = ruby_executable_node(node, &state); - state = ruby_exec_node(node); -#endif #endif #if defined(MKXPZ_ESSENTIALS_DEBUG) && !defined(__WIN32__) @@ -809,8 +814,6 @@ static void mriBindingExecute() { setenv("TEMP", tmpdir, false); #endif - Config &conf = shState->rtData().config; - VALUE lpaths = rb_gv_get(":"); if (!conf.rubyLoadpaths.empty()) { /* Setup custom load paths */ diff --git a/mkxp.json b/mkxp.json index 8a07e085..70c733e2 100644 --- a/mkxp.json +++ b/mkxp.json @@ -284,6 +284,12 @@ // "rubyLoadpath": ["/usr/lib64/ruby/", // "/usr/local/share/ruby/site_ruby"], + // Commandline arguments to pass to Ruby, such as to enable JIT. + // Only supported for Ruby ≥2. + // (default: none) + // + // "rubyArg": ["--jit-verbose=1"], + // SoundFont to use for midi playback (via fluidsynth) // (default: none) diff --git a/src/config.cpp b/src/config.cpp index b85c643e..b8cc0bd5 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -90,7 +90,8 @@ void Config::read(int argc, char *argv[]) { {"preloadScript", json::array({})}, {"RTP", json::array({})}, {"fontSub", json::array({})}, - {"rubyLoadpath", json::array({})} + {"rubyLoadpath", json::array({})}, + {"rubyArg", json::array({})} }).as_object(); #define GUARD(exp) \ @@ -177,6 +178,7 @@ try { exp } catch (...) {} fillStringVec(opts["RTP"], rtps); fillStringVec(opts["fontSub"], fontSubs); fillStringVec(opts["rubyLoadpath"], rubyLoadpaths); + fillStringVec(opts["rubyArg"], rubyArgs); rgssVersion = clamp(rgssVersion, 0, 3); SE.sourceCount = clamp(SE.sourceCount, 1, 64); diff --git a/src/config.h b/src/config.h index 9b1156d7..bec07dae 100644 --- a/src/config.h +++ b/src/config.h @@ -86,6 +86,8 @@ struct Config { std::vector rubyLoadpaths; + std::vector rubyArgs; + /* Editor flags */ struct { bool debug; From a08fea1574b601a3a78df0cd4d926f0a3b7d93db Mon Sep 17 00:00:00 2001 From: Aeodyn Date: Fri, 8 Jan 2021 23:32:30 -0500 Subject: [PATCH 2/2] Add exception handling to rubyArgs. --- binding/binding-mri.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/binding/binding-mri.cpp b/binding/binding-mri.cpp index 50a08707..ca54bef5 100644 --- a/binding/binding-mri.cpp +++ b/binding/binding-mri.cpp @@ -802,7 +802,24 @@ static void mriBindingExecute() { void *node = ruby_process_options(rubyArgsC.size(), const_cast(rubyArgsC.data())); int state; bool valid = ruby_executable_node(node, &state); - state = ruby_exec_node(node); + if (valid) + state = ruby_exec_node(node); + if (state || !valid) { + #if RAPI_FULL > 187 + VALUE exc = rb_errinfo(); + #else + VALUE exc = rb_gv_get("$!"); + #endif + #if RAPI_FULL >= 250 + VALUE msg = rb_funcall(exc, rb_intern("full_message"), 0); + #else + VALUE msg = rb_funcall(exc, rb_intern("message"), 0); + #endif + showMsg(std::string("An argument passed to Ruby via 'rubyArg' is invalid:\n") + StringValueCStr(msg)); + ruby_cleanup(state); + shState->rtData().rqTermAck.set(); + return; + } #else ruby_init(); rb_eval_string("$KCODE='U'");