Skip to content

Commit

Permalink
Simple codegen for lua c library static inclusion (#178)
Browse files Browse the repository at this point in the history
  • Loading branch information
Trey2k committed Oct 16, 2023
1 parent 5a71e71 commit e9129f2
Show file tree
Hide file tree
Showing 14 changed files with 175 additions and 94 deletions.
5 changes: 5 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ env.tools=['mingw']
env.Append(CPPDEFINES = ['LAPI_GDEXTENSION'])
env.Append(CPPPATH = [Dir('src').abspath, Dir('external').abspath])

env['sources'] = []
Export('env')
SConscript("lua_libraries/SConscript")

sources = Glob('*.cpp')
sources.append(Glob('src/*.cpp'))
sources.append(Glob('src/classes/*.cpp'))
sources.append(env['sources'])

if env["luaapi_luaver"] == 'jit':
env.Append(CPPDEFINES=['LAPI_LUAJIT'])
Expand Down
1 change: 1 addition & 0 deletions SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ if env["luaapi_luaver"] == "jit" and env['platform']=='javascript':

Export('env_lua')
SConscript('external/SCsub')
SConscript('lua_libraries/SCsub')

if env["luaapi_luaver"] == 'jit':
env_lua.Append(CPPDEFINES=['LAPI_LUAJIT'])
Expand Down
3 changes: 2 additions & 1 deletion doc_classes/LuaAPI.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@
</description>
</method>
<method name="bind_libraries">
<return type="void" />
<return type="LuaError" />
<param index="0" name="Array" type="Array" />
<description>
Bind lua libraries to the LuaAPI Object.
Returns an error if a library fails to bind.
Note: in C#, the param Array must be a [code]Godot.Collections.Array[/code] and not a [code]System.Array[/code] class.
</description>
</method>
Expand Down
8 changes: 5 additions & 3 deletions external/SCsub
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

Import('env')
Import('env_lua')

Expand Down Expand Up @@ -74,6 +73,7 @@ if luaver == "jit":
else:
env.Append(LIBPATH=[Dir("luaJIT/src").abspath])
env.Append(LIBS=['libluajit'])
env_lua.Append(CPPPATH=[Dir('luaJIT/src').abspath])

elif luaver == "5.1":
env_lua.Append(CPPDEFINES='MAKE_LIB')
Expand All @@ -87,7 +87,8 @@ elif luaver == "5.1":
env_lua['CFLAGS'].remove('-std=gnu11')
env_lua.Append(CFLAGS=['-std=c99'])

env_lua.add_source_files(env.modules_sources,'lua/*.c')
env_lua.Append(CPPPATH=[Dir('lua51').abspath])
env_lua.add_source_files(env.modules_sources,'lua51/*.c')

else:
env_lua.Append(CPPDEFINES='MAKE_LIB')
Expand All @@ -101,5 +102,6 @@ else:
env_lua['CFLAGS'].remove('-std=gnu11')
env_lua.Append(CFLAGS=['-std=c99'])

env_lua.add_source_files(env.modules_sources,'lua/onelua.c')
env_lua.Append(CPPPATH=[Dir('lua').abspath])
env_lua.add_source_files(env.modules_sources, 'lua/onelua.c')

9 changes: 9 additions & 0 deletions lua_libraries/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
*

!.gitignore
!SCsub
!SConscript
!codegen.py
!codegen.py
!README.md
!lua_libraries.h
8 changes: 8 additions & 0 deletions lua_libraries/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## Lua Libraries
This is a code gen module which allows you to statically compile a lua C library into this addon. Its as simple as downloading the source for the addon, and adding it as a folder with the library name in this folder.

It is important that the folder name be exactly the library name in lowercase. No version numbers included.

The code gen will auto detect it next time you build the addon. Either as a module or for GDExtension.

This is very new and potentially very prone to failure. So for lpeg has been tested and confirmed to work.
10 changes: 10 additions & 0 deletions lua_libraries/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Import('env')
from codegen import code_gen

code_gen(env['luaapi_luaver'] == 'jit')

sources = ['lua_libraries.gen.cpp']
library_name = "liblualibraries{}{}".format(env['suffix'], env["LIBSUFFIX"])

env.Append(sources=["lua_libraries/lua_libraries.gen.cpp"])
env.Append(CPPPATH=[Dir('.').abspath])
9 changes: 9 additions & 0 deletions lua_libraries/SCsub
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Import('env')
Import('env_lua')

from codegen import code_gen

code_gen(env['luaapi_luaver'] == 'jit')

env_lua.add_source_files(env.modules_sources, "lua_libraries.gen.cpp")
env_lua.Append(CPPPATH=[Dir('.').abspath])
95 changes: 95 additions & 0 deletions lua_libraries/codegen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import os

def code_gen(luaJIT=False):
lua_libraries = [
"base",
"coroutine",
"debug",
"io",
"math",
"os",
"package",
"string",
"table",
"utf8"
]

luajit_libraries = [
"base",
"bit",
"debug",
"ffi",
"io",
"jit",
"math",
"os",
"package",
"string",
"string_buffer",
"table"
]

libraries = lua_libraries
lib_source_files = []

if luaJIT:
libraries = luajit_libraries

for library in os.listdir("./"):
if not os.path.isdir(library) or library == "__pycache__" or library == "bin":
continue

libraries.append(library)

for source_file in os.listdir("./%s" % library):
if source_file.endswith(".cpp") or source_file.endswith(".c"):
lib_source_files.append(os.path.join(library, source_file))

luaLibraries_gen_cpp = "#include \"lua_libraries.h\"\n#include <map>\n#include <string>\n\n"

if len(lib_source_files) > 0:
for source_file in lib_source_files:
luaLibraries_gen_cpp += "#include \"%s\"\n" % source_file
luaLibraries_gen_cpp += "\n"

luaLibraries_gen_cpp += "std::map<std::string, lua_CFunction> luaLibraries = {\n"

for library in libraries:
luaLibraries_gen_cpp += "\t{ \"%s\", luaopen_%s },\n" % (library, library)

luaLibraries_gen_cpp += "};\n"
if luaJIT:
luaLibraries_gen_cpp += """
bool loadLuaLibrary(lua_State *L, String libraryName) {
const char *lib_c_str = libraryName.ascii().get_data();
if (luaLibraries[lib_c_str] == nullptr) {
return false;
}
lua_pushcfunction(L, luaLibraries[lib_c_str]);
if (libraryName == "base") {
lua_pushstring(L, "");
} else {
lua_pushstring(L, lib_c_str);
}
lua_call(L, 1, 0);
return true;
}
"""
else:
luaLibraries_gen_cpp += """
bool loadLuaLibrary(lua_State *L, String libraryName) {
const char *lib_c_str = libraryName.ascii().get_data();
if (luaLibraries[lib_c_str] == nullptr) {
return false;
}
luaL_requiref(L, lib_c_str, luaLibraries[lib_c_str], 1);
lua_pop(L, 1);
return true;
}
"""

gen_file = open("lua_libraries.gen.cpp", "w")
gen_file.write(luaLibraries_gen_cpp)
gen_file.close()
18 changes: 18 additions & 0 deletions lua_libraries/lua_libraries.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef LUA_LIBRARIES_H
#define LUA_LIBRARIES_H

#include <lua/lua.hpp>

#ifndef LAPI_GDEXTENSION
#include "core/string/ustring.h"

#include "core/variant/variant.h"
#else
#include <godot_cpp/variant/string.hpp>

using namespace godot;
#endif

bool loadLuaLibrary(lua_State *L, String libraryName);

#endif
4 changes: 2 additions & 2 deletions src/classes/luaAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ void LuaAPI::_bind_methods() {
}

// Calls LuaState::bindLibs()
void LuaAPI::bindLibraries(Array libs) {
state.bindLibraries(libs);
Ref<LuaError> LuaAPI::bindLibraries(TypedArray<String> libs) {
return state.bindLibraries(libs);
}

void LuaAPI::setHook(Callable hook, int mask, int count) {
Expand Down
4 changes: 2 additions & 2 deletions src/classes/luaAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class LuaAPI : public RefCounted {
LuaAPI();
~LuaAPI();

void bindLibraries(Array libs);
void setHook(Callable hook, int mask, int count);

void setUseCallables(bool value);
Expand All @@ -54,8 +53,9 @@ class LuaAPI : public RefCounted {
#endif

Variant getRegistryValue(String name);
Ref<LuaError> setRegistryValue(String name, Variant var);

Ref<LuaError> setRegistryValue(String name, Variant var);
Ref<LuaError> bindLibraries(TypedArray<String> libs);
Ref<LuaError> doFile(String fileName);
Ref<LuaError> doString(String code);
Ref<LuaError> pushGlobalVariant(String name, Variant var);
Expand Down
91 changes: 7 additions & 84 deletions src/luaState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <classes/luaFunctionRef.h>
#include <classes/luaTuple.h>

#include <lua_libraries.h>

#ifndef LAPI_GDXTENSION
#include <classes/luaCallable.h>
#endif
Expand Down Expand Up @@ -46,98 +48,19 @@ lua_State *LuaState::getState() const {
return L;
}

#ifndef LAPI_LUAJIT

// Binds lua libraries with the lua state
void LuaState::bindLibraries(Array libs) {
Ref<LuaError> LuaState::bindLibraries(TypedArray<String> libs) {
for (int i = 0; i < libs.size(); i++) {
String lib = ((String)libs[i]).to_lower();
if (lib == "base") {
luaL_requiref(L, "", luaopen_base, 1);
lua_pop(L, 1);
// base will override print, so we take it back. User can still override them self
lua_register(L, "print", luaPrint);
} else if (lib == "table") {
luaL_requiref(L, LUA_TABLIBNAME, luaopen_table, 1);
lua_pop(L, 1);
} else if (lib == "string") {
luaL_requiref(L, LUA_STRLIBNAME, luaopen_string, 1);
lua_pop(L, 1);
} else if (lib == "math") {
luaL_requiref(L, LUA_MATHLIBNAME, luaopen_math, 1);
lua_pop(L, 1);
} else if (lib == "os") {
luaL_requiref(L, LUA_OSLIBNAME, luaopen_os, 1);
lua_pop(L, 1);
} else if (lib == "io") {
luaL_requiref(L, LUA_IOLIBNAME, luaopen_io, 1);
lua_pop(L, 1);
} else if (lib == "coroutine") {
luaL_requiref(L, LUA_COLIBNAME, luaopen_coroutine, 1);
lua_pop(L, 1);
} else if (lib == "debug") {
luaL_requiref(L, LUA_DBLIBNAME, luaopen_debug, 1);
lua_pop(L, 1);
} else if (lib == "package") {
luaL_requiref(L, LUA_LOADLIBNAME, luaopen_package, 1);
lua_pop(L, 1);
} else if (lib == "utf8") {
luaL_requiref(L, LUA_UTF8LIBNAME, luaopen_utf8, 1);
lua_pop(L, 1);
if (!loadLuaLibrary(L, libs[i])) {
return LuaError::newError(vformat("Library \"%s\" does not exist.", libs[i]), LuaError::ERR_RUNTIME);
}
}
}

#else

// Binds lua libraries with the lua state
void LuaState::bindLibraries(Array libs) {
for (int i = 0; i < libs.size(); i++) {
String lib = ((String)libs[i]).to_lower();
if (lib == "base") {
lua_pushcfunction(L, luaopen_base);
lua_pushstring(L, "");
lua_call(L, 1, 0);

if (libs[i] == "base") {
lua_register(L, "print", luaPrint);
} else if (lib == "table") {
lua_pushcfunction(L, luaopen_table);
lua_pushstring(L, LUA_TABLIBNAME);
lua_call(L, 1, 0);
} else if (lib == "string") {
lua_pushcfunction(L, luaopen_string);
lua_pushstring(L, LUA_STRLIBNAME);
lua_call(L, 1, 0);
} else if (lib == "math") {
lua_pushcfunction(L, luaopen_math);
lua_pushstring(L, LUA_MATHLIBNAME);
lua_call(L, 1, 0);
} else if (lib == "os") {
lua_pushcfunction(L, luaopen_os);
lua_pushstring(L, LUA_OSLIBNAME);
lua_call(L, 1, 0);
} else if (lib == "io") {
lua_pushcfunction(L, luaopen_io);
lua_pushstring(L, LUA_IOLIBNAME);
lua_call(L, 1, 0);
} else if (lib == "debug") {
lua_pushcfunction(L, luaopen_debug);
lua_pushstring(L, LUA_DBLIBNAME);
lua_call(L, 1, 0);
} else if (lib == "package") {
lua_pushcfunction(L, luaopen_package);
lua_pushstring(L, LUA_LOADLIBNAME);
lua_call(L, 1, 0);
} else if (lib == "ffi") {
lua_pushcfunction(L, luaopen_ffi);
lua_pushstring(L, LUA_FFILIBNAME);
lua_call(L, 1, 0);
}
}
return nullptr;
}

#endif

void LuaState::setHook(Callable hook, int mask, int count) {
if (hook.is_null()) {
lua_sethook(L, nullptr, 0, 0);
Expand Down
4 changes: 2 additions & 2 deletions src/luaState.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ class LuaAPI;
class LuaState {
public:
void setState(lua_State *state, LuaAPI *lua, bool bindAPI);
void bindLibraries(Array libs);
void setHook(Callable hook, int mask, int count);

bool luaFunctionExists(String functionName);
Expand All @@ -30,8 +29,9 @@ class LuaState {
Variant callFunction(String functionName, Array args);

Variant getRegistryValue(String name);
Ref<LuaError> setRegistryValue(String name, Variant var);

Ref<LuaError> setRegistryValue(String name, Variant var);
Ref<LuaError> bindLibraries(TypedArray<String> libs);
Ref<LuaError> pushVariant(Variant var) const;
Ref<LuaError> pushGlobalVariant(String name, Variant var);
Ref<LuaError> handleError(int lua_error) const;
Expand Down

0 comments on commit e9129f2

Please sign in to comment.