Don't build MiniFFI on 64-bit Windows

MiniFFI/Win32API is now optional, and requires
sizeof(void*) == sizeof(long)
This commit is contained in:
Inori 2019-12-31 13:42:44 -05:00 committed by Inori
parent 7ff906c507
commit 796ceabe9c
5 changed files with 530 additions and 573 deletions

View file

@ -19,24 +19,23 @@
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/
#include "binding.h"
#include "audio.h"
#include "binding-util.h"
#include "sharedstate.h"
#include "binding.h"
#include "config.h"
#include "debugwriter.h"
#include "eventthread.h"
#include "filesystem.h"
#include "util.h"
#include "sdl-util.h"
#include "debugwriter.h"
#include "graphics.h"
#include "config.h"
#include "audio.h"
#include "lang-fun.h"
#include "sdl-util.h"
#include "sharedstate.h"
#include "util.h"
#include "boost-hash.h"
#include <vector>
extern "C"
{
extern "C" {
#include <ruby.h>
#ifndef OLD_RUBY
@ -48,9 +47,9 @@ extern "C"
#include <string>
#include <zlib.h>
#include <SDL_cpuinfo.h>
#include <SDL_filesystem.h>
#include <SDL_power.h>
#include <SDL_cpuinfo.h>
#ifdef __WIN32__
#define NULL_IO "NUL"
@ -66,12 +65,8 @@ static void mriBindingExecute();
static void mriBindingTerminate();
static void mriBindingReset();
ScriptBinding scriptBindingImpl =
{
mriBindingExecute,
mriBindingTerminate,
mriBindingReset
};
ScriptBinding scriptBindingImpl = {mriBindingExecute, mriBindingTerminate,
mriBindingReset};
ScriptBinding *scriptBinding = &scriptBindingImpl;
@ -93,7 +88,7 @@ void graphicsBindingInit();
void fileIntBindingInit();
#ifdef OLD_RUBY
#ifdef USE_MINIFFI
void MiniFFIBindingInit();
#endif
@ -120,8 +115,7 @@ RB_METHOD(mriRgssMain);
RB_METHOD(mriRgssStop);
RB_METHOD(_kernelCaller);
static void mriBindingInit()
{
static void mriBindingInit() {
tableBindingInit();
etcBindingInit();
fontBindingInit();
@ -130,13 +124,10 @@ static void mriBindingInit()
viewportBindingInit();
planeBindingInit();
if (rgssVer == 1)
{
if (rgssVer == 1) {
windowBindingInit();
tilemapBindingInit();
}
else
{
} else {
windowVXBindingInit();
tilemapVXBindingInit();
}
@ -147,7 +138,7 @@ static void mriBindingInit()
fileIntBindingInit();
#ifdef OLD_RUBY
#ifdef USE_MINIFFI
MiniFFIBindingInit();
#endif
@ -155,8 +146,7 @@ static void mriBindingInit()
DiscordBindingInit();
#endif
if (rgssVer >= 3)
{
if (rgssVer >= 3) {
_rb_define_module_function(rb_mKernel, "rgss_main", mriRgssMain);
_rb_define_module_function(rb_mKernel, "rgss_stop", mriRgssStop);
@ -164,13 +154,12 @@ static void mriBindingInit()
_rb_define_module_function(rb_mKernel, "msgbox_p", mriP);
rb_define_global_const("RGSS_VERSION", rb_str_new_cstr("3.0.1"));
}
else
{
} else {
_rb_define_module_function(rb_mKernel, "print", mriPrint);
_rb_define_module_function(rb_mKernel, "p", mriP);
rb_define_alias(rb_singleton_class(rb_mKernel), "_mkxp_kernel_caller_alias", "caller");
rb_define_alias(rb_singleton_class(rb_mKernel), "_mkxp_kernel_caller_alias",
"caller");
_rb_define_module_function(rb_mKernel, "caller", _kernelCaller);
}
@ -209,20 +198,16 @@ static void mriBindingInit()
rb_gv_set("BTEST", rb_bool_new(shState->config().editor.battleTest));
}
static void
showMsg(const std::string &msg)
{
static void showMsg(const std::string &msg) {
shState->eThread().showMessageBox(msg.c_str());
}
static void printP(int argc, VALUE *argv,
const char *convMethod, const char *sep)
{
static void printP(int argc, VALUE *argv, const char *convMethod,
const char *sep) {
VALUE dispString = rb_str_buf_new(128);
ID conv = rb_intern(convMethod);
for (int i = 0; i < argc; ++i)
{
for (int i = 0; i < argc; ++i) {
VALUE str = rb_funcall2(argv[i], conv, 0, NULL);
rb_str_buf_append(dispString, str);
@ -233,8 +218,7 @@ static void printP(int argc, VALUE *argv,
showMsg(RSTRING_PTR(dispString));
}
RB_METHOD(mriPrint)
{
RB_METHOD(mriPrint) {
RB_UNUSED_PARAM;
printP(argc, argv, "to_s", "");
@ -242,8 +226,7 @@ RB_METHOD(mriPrint)
return Qnil;
}
RB_METHOD(mriP)
{
RB_METHOD(mriP) {
RB_UNUSED_PARAM;
printP(argc, argv, "inspect", "\n");
@ -251,8 +234,7 @@ RB_METHOD(mriP)
return Qnil;
}
RB_METHOD(mkxpDataDirectory)
{
RB_METHOD(mkxpDataDirectory) {
RB_UNUSED_PARAM;
const std::string &path = shState->config().customDataPath;
@ -265,8 +247,7 @@ RB_METHOD(mkxpDataDirectory)
return ret;
}
RB_METHOD(mkxpSetTitle)
{
RB_METHOD(mkxpSetTitle) {
RB_UNUSED_PARAM;
VALUE s;
@ -277,8 +258,7 @@ RB_METHOD(mkxpSetTitle)
return s;
}
RB_METHOD(mkxpPuts)
{
RB_METHOD(mkxpPuts) {
RB_UNUSED_PARAM;
const char *str;
@ -289,46 +269,41 @@ RB_METHOD(mkxpPuts)
return Qnil;
}
RB_METHOD(mkxpRawKeyStates)
{
RB_METHOD(mkxpRawKeyStates) {
RB_UNUSED_PARAM;
VALUE str = rb_str_new(0, sizeof(EventThread::keyStates));
memcpy(RSTRING_PTR(str), EventThread::keyStates, sizeof(EventThread::keyStates));
memcpy(RSTRING_PTR(str), EventThread::keyStates,
sizeof(EventThread::keyStates));
return str;
}
RB_METHOD(mkxpMouseInWindow)
{
RB_METHOD(mkxpMouseInWindow) {
RB_UNUSED_PARAM;
return rb_bool_new(EventThread::mouseState.inWindow);
}
RB_METHOD(mkxpPlatform)
{
RB_METHOD(mkxpPlatform) {
RB_UNUSED_PARAM;
return rb_str_new_cstr(SDL_GetPlatform());
}
RB_METHOD(mkxpUserLanguage)
{
RB_METHOD(mkxpUserLanguage) {
RB_UNUSED_PARAM;
return rb_str_new_cstr(getUserLanguage());
}
RB_METHOD(mkxpGameTitle)
{
RB_METHOD(mkxpGameTitle) {
RB_UNUSED_PARAM;
return rb_str_new_cstr(shState->config().game.title.c_str());
}
RB_METHOD(mkxpPowerState)
{
RB_METHOD(mkxpPowerState) {
RB_UNUSED_PARAM;
int secs, pct;
@ -336,17 +311,19 @@ RB_METHOD(mkxpPowerState)
VALUE hash = rb_hash_new();
rb_hash_aset(hash, ID2SYM(rb_intern("seconds")), (secs > -1) ? INT2NUM(secs) : RUBY_Qnil);
rb_hash_aset(hash, ID2SYM(rb_intern("seconds")),
(secs > -1) ? INT2NUM(secs) : RUBY_Qnil);
rb_hash_aset(hash, ID2SYM(rb_intern("percent")), (pct > -1) ? INT2NUM(pct) : RUBY_Qnil);
rb_hash_aset(hash, ID2SYM(rb_intern("percent")),
(pct > -1) ? INT2NUM(pct) : RUBY_Qnil);
rb_hash_aset(hash, ID2SYM(rb_intern("discharging")), rb_bool_new(ps == SDL_POWERSTATE_ON_BATTERY));
rb_hash_aset(hash, ID2SYM(rb_intern("discharging")),
rb_bool_new(ps == SDL_POWERSTATE_ON_BATTERY));
return hash;
}
RB_METHOD(mkxpSettingsMenu)
{
RB_METHOD(mkxpSettingsMenu) {
RB_UNUSED_PARAM;
shState->eThread().requestSettingsMenu();
@ -354,56 +331,48 @@ RB_METHOD(mkxpSettingsMenu)
return Qnil;
}
RB_METHOD(mkxpCpuCount)
{
RB_METHOD(mkxpCpuCount) {
RB_UNUSED_PARAM;
return INT2NUM(SDL_GetCPUCount());
}
RB_METHOD(mkxpSystemMemory)
{
RB_METHOD(mkxpSystemMemory) {
RB_UNUSED_PARAM;
return INT2NUM(SDL_GetSystemRAM());
}
static VALUE rgssMainCb(VALUE block)
{
static VALUE rgssMainCb(VALUE block) {
rb_funcall2(block, rb_intern("call"), 0, 0);
return Qnil;
}
static VALUE rgssMainRescue(VALUE arg, VALUE exc)
{
VALUE *excRet = (VALUE*) arg;
static VALUE rgssMainRescue(VALUE arg, VALUE exc) {
VALUE *excRet = (VALUE *)arg;
*excRet = exc;
return Qnil;
}
static void processReset()
{
static void processReset() {
shState->graphics().reset();
shState->audio().reset();
shState->rtData().rqReset.clear();
shState->graphics().repaintWait(shState->rtData().rqResetFinish,
false);
shState->graphics().repaintWait(shState->rtData().rqResetFinish, false);
}
RB_METHOD(mriRgssMain)
{
RB_METHOD(mriRgssMain) {
RB_UNUSED_PARAM;
while (true)
{
while (true) {
VALUE exc = Qnil;
rb_rescue2((VALUE(*)(ANYARGS)) rgssMainCb, rb_block_proc(),
(VALUE(*)(ANYARGS)) rgssMainRescue, (VALUE) &exc,
rb_eException, (VALUE) 0);
rb_rescue2((VALUE(*)(ANYARGS))rgssMainCb, rb_block_proc(),
(VALUE(*)(ANYARGS))rgssMainRescue, (VALUE)&exc, rb_eException,
(VALUE)0);
if (NIL_P(exc))
break;
@ -417,8 +386,7 @@ RB_METHOD(mriRgssMain)
return Qnil;
}
RB_METHOD(mriRgssStop)
{
RB_METHOD(mriRgssStop) {
RB_UNUSED_PARAM;
while (true)
@ -427,11 +395,11 @@ RB_METHOD(mriRgssStop)
return Qnil;
}
RB_METHOD(_kernelCaller)
{
RB_METHOD(_kernelCaller) {
RB_UNUSED_PARAM;
VALUE trace = rb_funcall2(rb_mKernel, rb_intern("_mkxp_kernel_caller_alias"), 0, 0);
VALUE trace =
rb_funcall2(rb_mKernel, rb_intern("_mkxp_kernel_caller_alias"), 0, 0);
if (!RB_TYPE_P(trace, RUBY_T_ARRAY))
return trace;
@ -453,45 +421,39 @@ RB_METHOD(_kernelCaller)
return trace;
/* RMXP does this, not sure if specific or 1.8 related */
VALUE args[] = { rb_str_new_cstr(":in `<main>'"), rb_str_new_cstr("") };
rb_funcall2(rb_ary_entry(trace, len-1), rb_intern("gsub!"), 2, args);
VALUE args[] = {rb_str_new_cstr(":in `<main>'"), rb_str_new_cstr("")};
rb_funcall2(rb_ary_entry(trace, len - 1), rb_intern("gsub!"), 2, args);
return trace;
}
#ifndef OLD_RUBY
static VALUE newStringUTF8(const char *string, long length)
{
static VALUE newStringUTF8(const char *string, long length) {
return rb_enc_str_new(string, length, rb_utf8_encoding());
}
#else
#define newStringUTF8 rb_str_new
#endif
struct evalArg
{
struct evalArg {
VALUE string;
VALUE filename;
};
static VALUE evalHelper(evalArg *arg)
{
VALUE argv[] = { arg->string, Qnil, arg->filename };
static VALUE evalHelper(evalArg *arg) {
VALUE argv[] = {arg->string, Qnil, arg->filename};
return rb_funcall2(Qnil, rb_intern("eval"), ARRAY_SIZE(argv), argv);
}
static VALUE evalString(VALUE string, VALUE filename, int *state)
{
evalArg arg = { string, filename };
return rb_protect((VALUE (*)(VALUE))evalHelper, (VALUE)&arg, state);
static VALUE evalString(VALUE string, VALUE filename, int *state) {
evalArg arg = {string, filename};
return rb_protect((VALUE(*)(VALUE))evalHelper, (VALUE)&arg, state);
}
static void runCustomScript(const std::string &filename)
{
static void runCustomScript(const std::string &filename) {
std::string scriptData;
if (!readFileSDL(filename.c_str(), scriptData))
{
if (!readFileSDL(filename.c_str(), scriptData)) {
showMsg(std::string("Unable to open '") + filename + "'");
return;
}
@ -502,8 +464,7 @@ static void runCustomScript(const std::string &filename)
VALUE kernelLoadDataInt(const char *filename, bool rubyExc, bool raw);
struct BacktraceData
{
struct BacktraceData {
/* Maps: Ruby visible filename, To: Actual script name */
BoostHash<std::string, std::string> scriptNames;
};
@ -511,20 +472,17 @@ struct BacktraceData
#ifndef MARIN
#define SCRIPT_SECTION_FMT (rgssVer >= 3 ? "{%04ld}" : "Section%03ld")
static void runRMXPScripts(BacktraceData &btData)
{
static void runRMXPScripts(BacktraceData &btData) {
const Config &conf = shState->rtData().config;
const std::string &scriptPack = conf.game.scripts;
const char *platform = SDL_GetPlatform();
if (scriptPack.empty())
{
if (scriptPack.empty()) {
showMsg("No game scripts specified (missing Game.ini?)");
return;
}
if (!shState->fileSystem().exists(scriptPack.c_str()))
{
if (!shState->fileSystem().exists(scriptPack.c_str())) {
showMsg("Unable to open '" + scriptPack + "'");
return;
}
@ -533,18 +491,14 @@ static void runRMXPScripts(BacktraceData &btData)
/* We checked if Scripts.rxdata exists, but something might
* still go wrong */
try
{
try {
scriptArray = kernelLoadDataInt(scriptPack.c_str(), false, false);
}
catch (const Exception &e)
{
} catch (const Exception &e) {
showMsg(std::string("Failed to read script data: ") + e.msg);
return;
}
if (!RB_TYPE_P(scriptArray, RUBY_T_ARRAY))
{
if (!RB_TYPE_P(scriptArray, RUBY_T_ARRAY)) {
showMsg("Failed to read script data");
return;
}
@ -556,8 +510,7 @@ static void runRMXPScripts(BacktraceData &btData)
std::string decodeBuffer;
decodeBuffer.resize(0x1000);
for (long i = 0; i < scriptCount; ++i)
{
for (long i = 0; i < scriptCount; ++i) {
VALUE script = rb_ary_entry(scriptArray, i);
if (!RB_TYPE_P(script, RUBY_T_ARRAY))
@ -569,31 +522,29 @@ static void runRMXPScripts(BacktraceData &btData)
int result = Z_OK;
unsigned long bufferLen;
while (true)
{
unsigned char *bufferPtr =
reinterpret_cast<unsigned char*>(const_cast<char*>(decodeBuffer.c_str()));
while (true) {
unsigned char *bufferPtr = reinterpret_cast<unsigned char *>(
const_cast<char *>(decodeBuffer.c_str()));
const unsigned char *sourcePtr =
reinterpret_cast<const unsigned char*>(RSTRING_PTR(scriptString));
reinterpret_cast<const unsigned char *>(RSTRING_PTR(scriptString));
bufferLen = decodeBuffer.length();
result = uncompress(bufferPtr, &bufferLen,
sourcePtr, RSTRING_LEN(scriptString));
result = uncompress(bufferPtr, &bufferLen, sourcePtr,
RSTRING_LEN(scriptString));
bufferPtr[bufferLen] = '\0';
if (result != Z_BUF_ERROR)
break;
decodeBuffer.resize(decodeBuffer.size()*2);
decodeBuffer.resize(decodeBuffer.size() * 2);
}
if (result != Z_OK)
{
if (result != Z_OK) {
static char buffer[256];
snprintf(buffer, sizeof(buffer), "Error decoding script %ld: '%s'",
i, RSTRING_PTR(scriptName));
snprintf(buffer, sizeof(buffer), "Error decoding script %ld: '%s'", i,
RSTRING_PTR(scriptName));
showMsg(buffer);
@ -615,20 +566,18 @@ static void runRMXPScripts(BacktraceData &btData)
return;
#endif
while (true)
{
while (true) {
#if defined(OLD_RUBY) && defined(NO_CONSOLE)
VALUE iostr = rb_str_new2(NULL_IO);
// Sysinit isn't a thing yet, so send io to /dev/null instead
rb_funcall(rb_gv_get("$stderr"), rb_intern("reopen"), 1, iostr);
rb_funcall(rb_gv_get("$stdout"), rb_intern("reopen"), 1, iostr);
#endif
for (long i = 0; i < scriptCount; ++i)
{
for (long i = 0; i < scriptCount; ++i) {
VALUE script = rb_ary_entry(scriptArray, i);
VALUE scriptDecoded = rb_ary_entry(script, 3);
VALUE string = newStringUTF8(RSTRING_PTR(scriptDecoded),
RSTRING_LEN(scriptDecoded));
VALUE string =
newStringUTF8(RSTRING_PTR(scriptDecoded), RSTRING_LEN(scriptDecoded));
VALUE fname;
const char *scriptName = RSTRING_PTR(rb_ary_entry(script, 1));
@ -652,17 +601,16 @@ static void runRMXPScripts(BacktraceData &btData)
// Adding a 'not' symbol means it WON'T run on that
// platform (i.e. |!W| won't run on Windows)
if (scriptName[0] == '|')
{
if (scriptName[0] == '|') {
int len = strlen(scriptName);
if (len > 2)
{
if (scriptName[1] == '!' && len > 3 && scriptName[3] == scriptName[0])
{
if (len > 2) {
if (scriptName[1] == '!' && len > 3 &&
scriptName[3] == scriptName[0]) {
if (toupper(scriptName[2]) == platform[0])
continue;
}
if (scriptName[2] == scriptName[0] && toupper(scriptName[1]) != platform[0])
if (scriptName[2] == scriptName[0] &&
toupper(scriptName[1]) != platform[0])
continue;
}
}
@ -683,15 +631,14 @@ static void runRMXPScripts(BacktraceData &btData)
}
#endif
static void showExc(VALUE exc, const BacktraceData &btData)
{
static void showExc(VALUE exc, const BacktraceData &btData) {
VALUE bt = rb_funcall2(exc, rb_intern("backtrace"), 0, NULL);
VALUE msg = rb_funcall2(exc, rb_intern("message"), 0, NULL);
VALUE bt0 = rb_ary_entry(bt, 0);
VALUE name = rb_class_path(rb_obj_class(exc));
VALUE ds = rb_sprintf("%" PRIsVALUE ": %" PRIsVALUE " (%" PRIsVALUE ")",
bt0, exc, name);
VALUE ds = rb_sprintf("%" PRIsVALUE ": %" PRIsVALUE " (%" PRIsVALUE ")", bt0,
exc, name);
/* omit "useless" last entry (from ruby:1:in `eval') */
for (long i = 1, btlen = RARRAY_LEN(bt) - 1; i < btlen; ++i)
rb_str_catf(ds, "\n\tfrom %" PRIsVALUE, rb_ary_entry(bt, i));
@ -719,8 +666,8 @@ static void showExc(VALUE exc, const BacktraceData &btData)
* SectionXXX:YY: in 'blabla' */
*e = '\0';
strncpy(line, *p ? p+1 : p, sizeof(line));
line[sizeof(line)-1] = '\0';
strncpy(line, *p ? p + 1 : p, sizeof(line));
line[sizeof(line) - 1] = '\0';
*e = ':';
e = p;
@ -742,8 +689,7 @@ static void showExc(VALUE exc, const BacktraceData &btData)
showMsg(ms);
}
static void mriBindingExecute()
{
static void mriBindingExecute() {
#ifndef OLD_RUBY
/* Normally only a ruby executable would do a sysinit,
* but not doing it will lead to crashes due to closed
@ -761,17 +707,16 @@ static void mriBindingExecute()
#if defined(USE_FAKEAPI) && !defined(__WIN32__)
char *tmpdir = getenv("TMPDIR");
if (tmpdir) setenv("TEMP", tmpdir, false);
if (tmpdir)
setenv("TEMP", tmpdir, false);
#endif
Config &conf = shState->rtData().config;
VALUE lpaths = rb_gv_get(":");
if (!conf.rubyLoadpaths.empty())
{
if (!conf.rubyLoadpaths.empty()) {
/* Setup custom load paths */
for (size_t i = 0; i < conf.rubyLoadpaths.size(); ++i)
{
for (size_t i = 0; i < conf.rubyLoadpaths.size(); ++i) {
std::string &path = conf.rubyLoadpaths[i];
VALUE pathv = rb_str_new(path.c_str(), path.size());
@ -779,8 +724,7 @@ static void mriBindingExecute()
}
}
#ifdef MARIN
else
{
else {
rb_ary_push(lpaths, rb_str_new_cstr("ruby/extensions/2.5.0"));
rb_ary_push(lpaths, rb_str_new_cstr("ruby/extensions/2.5.0/i386-mingw32"));
}
@ -815,12 +759,6 @@ static void mriBindingExecute()
shState->rtData().rqTermAck.set();
}
static void mriBindingTerminate()
{
rb_raise(rb_eSystemExit, " ");
}
static void mriBindingTerminate() { rb_raise(rb_eSystemExit, " "); }
static void mriBindingReset()
{
rb_raise(getRbData()->exc[Reset], " ");
}
static void mriBindingReset() { rb_raise(getRbData()->exc[Reset], " "); }

View file

@ -29,12 +29,15 @@ binding_source = [files(
'module_rpg.cpp',
'filesystem-binding.cpp',
'windowvx-binding.cpp',
'tilemapvx-binding.cpp',
'miniffi-binding.cpp'
'tilemapvx-binding.cpp'
)]
if discord == true
binding_source += files('discord-binding.cpp')
endif
if miniffi == true
binding_source += files('miniffi-binding.cpp')
endif
global_sources += binding_source

View file

@ -53,6 +53,20 @@ if compilers['objc'].get_id() == 'clang'
global_args += ['-Wno-undefined-var-template', '-Wno-delete-non-abstract-non-virtual-dtor']
endif
# Decide whether or not to use MiniFFI
miniffi = get_option('use_miniffi')
if miniffi == true
if compilers['cpp'].sizeof('void*') == compilers['cpp'].sizeof('long')
miniffi = true
global_args += '-DUSE_MINIFFI'
else
warning('64-bit MiniFFI is only supported on Linux and macOS.')
warning('To use MiniFFI/Win32API on Windows, target 32-bit.')
miniffi = false
endif
endif
# Defines
if get_option('workdir_current')
global_args += '-DWORKDIR_CURRENT'
endif
@ -61,7 +75,7 @@ if get_option('independent_appimage')
global_args += '-DINDEPENDENT_APPIMAGE'
endif
if get_option('use_fakeapi')
if get_option('use_fakeapi') == true and miniffi == true
global_args += '-DUSE_FAKEAPI'
endif
@ -73,6 +87,7 @@ if get_option('mk')
global_args += '-DMARIN'
endif
# Objectify our C
global_args += run_command(objfw,'--cppflags').stdout().split()
add_project_arguments(run_command(objfw,'--objcflags').stdout().split(), language:['objc','objcpp'])

View file

@ -6,7 +6,8 @@ option('macos_min_version', type: 'string', value: '10.10', description: 'Minimu
option('shared_fluid', type: 'boolean', value: false, description: 'Dynamically link fluidsynth at build time')
option('cjk_fallback_font', type: 'boolean', value: false, description: 'Use WenQuanYi Micro Hei as the fallback font')
option('use_fakeapi', type: 'boolean', value: false, description: 'Attempt to repair Win32API calls that do not work with MKXP')
option('use_miniffi', type: 'boolean', value: true, description: 'Enable MiniFFI Ruby module (Win32API)')
option('use_fakeapi', type: 'boolean', value: false, description: 'Attempt to repair Win32API calls that do not work with MKXP. Requires MiniFFI')
option('default_framerate', type: 'boolean', value: false, description: 'Disable syncToRefreshrate and fixedFramerate configuration options')
option('no_preload_scripts', type: 'boolean', value: false, description: 'Disable the preloadScript configuration option')
option('workdir_current', type: 'boolean', value: false, description: 'Keep current directory on startup')

View file

@ -83,7 +83,7 @@ main_source = files(
'lang-fun.mm'
)
if get_option('use_fakeapi') == true
if get_option('use_fakeapi') == true and miniffi == true
main_source += files('fake-api.mm')
endif