Skip to content

Commit 47577f7

Browse files
committed
Fix dlopen PluginScript library (#41)
This fixes the support for `require`ing Lua/C modules in POSIX systems
1 parent e9c8ed8 commit 47577f7

5 files changed

Lines changed: 94 additions & 24 deletions

File tree

Makefile

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@ ifneq (,$(CODE_SIGN_IDENTITY))
132132
endif
133133

134134
define GEN_TEST
135-
test-$1: $1 $(LUASRCDIET_DEST) $(LUAJIT_JITLIB_DEST) $(DIST_DEST) build/project.godot
136-
@mkdir -p $(dir build/addons/godot-lua-pluginscript/$2)
137-
cp $2 build/addons/godot-lua-pluginscript/$2
135+
test-$1: $1 $(addprefix $2/, $3) $(LUASRCDIET_DEST) $(LUAJIT_JITLIB_DEST) $(DIST_DEST) build/project.godot
136+
@mkdir -p build/addons/godot-lua-pluginscript/$2
137+
cp $(addprefix $2/, $3) build/addons/godot-lua-pluginscript/$2
138138
$(GODOT_BIN) --path build --no-window --quit --script "$(CURDIR)/src/test/init.lua"
139139
endef
140140

@@ -177,7 +177,6 @@ build/%/liblua_pluginscript.so: $(BUILT_OBJS) build/%/luajit/src/libluajit.a
177177
$(call STRIP_CMD,$@)
178178

179179
build/%/lua_pluginscript.dll: TARGET_SYS = Windows
180-
build/%/lua_pluginscript.dll: EXE = .exe
181180
build/%/lua_pluginscript.dll: $(BUILT_OBJS) build/%/lua51.dll
182181
$(_CC) -o $@ $^ -shared $(CFLAGS) $(LDFLAGS)
183182
$(call STRIP_CMD,$@)
@@ -217,6 +216,14 @@ build/compile_commands.json: Makefile
217216
echo '[{"directory":"$(CURDIR)","file":"src/language_gdnative.c","command":"$(subst ",\",$(COMPILE_COMMAND))"}]' > $@
218217

219218

219+
build/%/test_cmodule.so: src/test/test_cmodule.c
220+
$(_CC) -o $@ $^ -shared $(CFLAGS) $(LDFLAGS)
221+
build/%/test_cmodule.dll: src/test/test_cmodule.c
222+
$(_CC) -o $@ $^ -shared $(CFLAGS) $(LDFLAGS)
223+
build/%/test_cmodule.dylib: src/test/test_cmodule.c
224+
$(_CC) -o $@ $^ -shared $(CFLAGS) $(LDFLAGS)
225+
226+
220227
# Phony targets
221228
.PHONY: clean dist docs set-version unzip-to-build update-copyright-year
222229
clean:
@@ -261,26 +268,26 @@ compdb: compilation-database
261268
linux32: MAKE_LUAJIT_ARGS += CC="$(CC) -m32 -fPIC"
262269
linux32: CFLAGS += -m32 -fPIC
263270
linux32: build/linux_x86/liblua_pluginscript.so
264-
$(eval $(call GEN_TEST,linux32,build/linux_x86/liblua_pluginscript.so))
271+
$(eval $(call GEN_TEST,linux32,build/linux_x86,liblua_pluginscript.so test_cmodule.so))
265272

266273
linux64: MAKE_LUAJIT_ARGS += CC="$(CC) -fPIC"
267274
linux64: CFLAGS += -fPIC
268275
linux64: build/linux_x86_64/liblua_pluginscript.so
269-
$(eval $(call GEN_TEST,linux64,build/linux_x86_64/liblua_pluginscript.so))
276+
$(eval $(call GEN_TEST,linux64,build/linux_x86_64,liblua_pluginscript.so test_cmodule.so))
270277

271278
windows32: build/windows_x86/lua_pluginscript.dll
272-
$(eval $(call GEN_TEST,windows32,build/windows_x86/lua_pluginscript.dll))
279+
$(eval $(call GEN_TEST,windows32,build/windows_x86,lua_pluginscript.dll test_cmodule.dll))
273280
mingw-windows32: CROSS = i686-w64-mingw32-
274281
mingw-windows32: MAKE_LUAJIT_ARGS += HOST_CC="$(CC) -m32" CROSS="$(CROSS)" LDFLAGS=-static-libgcc
275282
mingw-windows32: windows32
276-
$(eval $(call GEN_TEST,mingw-windows32,build/windows_x86/lua_pluginscript.dll))
283+
$(eval $(call GEN_TEST,mingw-windows32,build/windows_x86,lua_pluginscript.dll test_cmodule.dll))
277284

278285
windows64: build/windows_x86_64/lua_pluginscript.dll
279-
$(eval $(call GEN_TEST,windows64,build/windows_x86_64/lua_pluginscript.dll))
286+
$(eval $(call GEN_TEST,windows64,build/windows_x86_64,lua_pluginscript.dll test_cmodule.dll))
280287
mingw-windows64: CROSS = x86_64-w64-mingw32-
281288
mingw-windows64: MAKE_LUAJIT_ARGS += HOST_CC="$(CC)" CROSS="$(CROSS)" LDFLAGS=-static-libgcc
282289
mingw-windows64: windows64
283-
$(eval $(call GEN_TEST,mingw-windows64,build/windows_x86_64/lua_pluginscript.dll))
290+
$(eval $(call GEN_TEST,mingw-windows64,build/windows_x86_64,lua_pluginscript.dll test_cmodule.dll))
284291

285292
osx-x86_64: MACOSX_DEPLOYMENT_TARGET ?= 10.7
286293
osx-x86_64: _ADD_CFLAGS = -isysroot '$(shell xcrun --sdk macosx --show-sdk-path)' -arch x86_64
@@ -295,7 +302,7 @@ osx-arm64: MAKE_LUAJIT_ARGS += TARGET_FLAGS="$(_ADD_CFLAGS)" MACOSX_DEPLOYMENT_T
295302
osx-arm64: build/osx_arm64/lua_pluginscript.dylib
296303

297304
osx64: osx-x86_64 osx-arm64 build/osx_arm64_x86_64/lua_pluginscript.dylib
298-
$(eval $(call GEN_TEST,osx64,build/osx_arm64_x86_64/lua_pluginscript.dylib))
305+
$(eval $(call GEN_TEST,osx64,build/osx_arm64_x86_64,lua_pluginscript.dylib test_cmodule.dylib))
299306

300307
# Note: newer OSX systems can't run i386 apps, so LuaJIT can't build properly with the current Makefile
301308
#ios-armv7s: _ADD_CFLAGS = -isysroot "$(shell xcrun --sdk iphoneos --show-sdk-path)" -arch armv7s -miphoneos-version-min=$(IOS_VERSION_MIN)

src/lua_package_extras.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,23 @@ package.path = lua_path:join(';')
193193
--
194194
-- @see searchpath
195195
package.cpath = lua_cpath:join(';')
196+
197+
--- `dlopen`s the PluginScript library with `RTLD_LAZY | RTLD_GLOBAL`.
198+
-- This is necessary for loading Lua/C modules in POSIX systems.
199+
local function dlopen_self()
200+
ffi_cdef[[
201+
void *dlopen(const char *filename, int flags);
202+
int dlclose(void *handle);
203+
]]
204+
205+
local RTLD_LAZY = 0x00001
206+
local RTLD_GLOBAL = 0x00100
207+
local currentLibraryPath = tostring(gdnativelibrary:get_current_library_path():replace("res://", execdir_repl .. '/'))
208+
-- Maintain a reference to dlopened library while PluginScript is loaded
209+
-- When the Lua state closes, GC will kick in and the library will get dlclosed
210+
pluginscript_callbacks.__dlopened_self = ffi_gc(ffi.C.dlopen(currentLibraryPath, RTLD_LAZY + RTLD_GLOBAL), ffi.C.dlclose)
211+
end
212+
213+
if Array("Android", "iOS", "OSX", "Server", "X11"):has(OS:get_name()) then
214+
xpcall(dlopen_self, GD.print_error)
215+
end

src/test/init.lua

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,55 @@ local TestRunner = {
2424
extends = 'SceneTree',
2525
}
2626

27-
function TestRunner:_init()
28-
local current_script_path = self:get_script().resource_path
29-
local current_script_filename = current_script_path:get_file()
30-
local current_script_base_dir = current_script_path:get_base_dir()
27+
local function error_handler(msg)
28+
if os.getenv('DEBUG_INTERACTIVE') then
29+
local have_dbg, dbg = pcall(require, 'debugger')
30+
if have_dbg then
31+
return dbg()
32+
end
33+
end
34+
GD.print_error(msg)
35+
end
3136

37+
function TestRunner:setup_luapath(current_script_base_dir)
3238
local additional_paths = { '../../lib/luaunit', '../../lib/debugger_lua' }
3339
for _, path in ipairs(additional_paths) do
3440
local additional_path = current_script_base_dir:plus_file(path)
35-
package.path = string.format('%s/?.lua;%s/?/init.lua;', additional_path, additional_path) .. package.path
41+
package.path = string.format('%s/?.lua;%s/?/init.lua;%s', additional_path, additional_path, package.path)
3642
end
43+
end
3744

38-
local function error_handler(msg)
39-
if os.getenv('DEBUG_INTERACTIVE') then
40-
local have_dbg, dbg = pcall(require, 'debugger')
41-
if have_dbg then
42-
return dbg()
43-
end
44-
end
45-
GD.print_error(msg)
45+
function TestRunner:setup_cpath()
46+
local additional_paths
47+
if OS:get_name() == 'Windows' then
48+
additional_paths = {
49+
'!/addons/godot-lua-pluginscript/build/windows_x86/?.dll',
50+
'!/addons/godot-lua-pluginscript/build/windows_x86_64/?.dll',
51+
}
52+
elseif OS:get_name() == 'OSX' then
53+
additional_paths = {
54+
'!/addons/godot-lua-pluginscript/build/osx_arm64_x86_64/?.dylib',
55+
}
56+
else
57+
additional_paths = {
58+
'!/addons/godot-lua-pluginscript/build/linux_x86/?.so',
59+
'!/addons/godot-lua-pluginscript/build/linux_x86_64/?.so',
60+
}
4661
end
4762

63+
for _, path in ipairs(additional_paths) do
64+
package.cpath = string.format('%s;%s', path, package.cpath)
65+
end
66+
end
67+
68+
function TestRunner:_init()
69+
local current_script_path = self:get_script().resource_path
70+
local current_script_filename = current_script_path:get_file()
71+
local current_script_base_dir = current_script_path:get_base_dir()
72+
73+
self:setup_luapath(current_script_base_dir)
74+
self:setup_cpath()
75+
4876
local dir, all_passed = Directory:new(), true
4977
assert(dir:open(current_script_base_dir) == GD.OK)
5078
dir:list_dir_begin(true)

src/test/require_luac.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
local lu = require "luaunit"
2+
3+
local Test = {}
4+
5+
function Test:test_require_luac_module()
6+
lu.assert_true(pcall(require, 'test_luac'))
7+
end
8+
9+
return Test

src/test/test_cmodule.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include "lua.h"
2+
3+
int luaopen_test_luac(lua_State *L) {
4+
lua_pushboolean(L, 1);
5+
return 1;
6+
}

0 commit comments

Comments
 (0)