some stuff

This commit is contained in:
2025-11-27 14:09:10 +02:00
parent 3381b5d657
commit 318928ddbc
2 changed files with 127 additions and 64 deletions

View File

@@ -10,7 +10,7 @@ LDARGS_LUA ?= $(shell pkg-config --libs lua5.4)
CCARGS += $(CCARGS_LUA)
LDARGS += $(LDARGS_LUA)
MKLUA_FLAGS += --path "src/main/?.lua;src/main/?/init.lua;;"
MKLUA_FLAGS += --path "src/?.lua;src/?/init.lua;;"
MKLUA_FLAGS += --main
MKLUA_ENTRIES += mklua

View File

@@ -13,7 +13,10 @@ Flags:
--libs - outputs a list of native libraries the entries depend on
--makefile - generates a makefile
--main - includes a C main function, which calls the export of the first entry
--entry - generates a mklua_entry function, which takes an initialized lua state
and executes the first entry
--main - generates a main function, which creates a lua state and runs the entry
implies `--entry`
--output=<file> (-o <file>) - the file to write to
--debug (-g) - emits debugging data in the lua bytecode
@@ -21,47 +24,57 @@ Flags:
--cpath - specifies a c path to search
]];
local main_format = [[
#ifndef MKLUA_MAIN_NAME
#define MKLUA_MAIN_NAME main
local entry_format = [[
#ifndef MKLUA_ENTRY_NAME
#define MKLUA_ENTRY_NAME mklua_entry
#endif
%s
int MKLUA_MAIN_NAME(int argc, const char **argv) {
lua_State *ctx = luaL_newstate();
luaL_openlibs(ctx);
MKLUA_EXPORT int MKLUA_ENTRY_NAME(lua_State *ctx, int argc, const char **argv) {
int larg, lerrcb, i, ok;
lua_checkstack(ctx, argc + 16);
/* Emit other requiref-s */
%s
lua_createtable(ctx, argc, 0);
int larg = lua_gettop(ctx);
larg = lua_gettop(ctx);
lua_pushvalue(ctx, larg);
lua_setglobal(ctx, "arg");
luaL_requiref(ctx, "__err_handle", %s, false);
int lerrcb = lua_gettop(ctx);
luaL_requiref(ctx, "__err_handle", %s, 0);
lerrcb = lua_gettop(ctx);
luaL_requiref(ctx, %q, %s, false);
luaL_requiref(ctx, %q, %s, 0);
for (int i = 1; i < argc; i++) {
for (i = 1; i < argc; i++) {
lua_pushstring(ctx, argv[i]);
lua_pushvalue(ctx, -1);
lua_seti(ctx, larg, i);
}
if (lua_pcall(ctx, argc - 1, 0, lerrcb)) {
fprintf(stderr, "lua error: %%s\n", lua_tostring(ctx, -1));
lua_close(ctx);
return 1;
}
else {
lua_close(ctx);
return 0;
}
ok = !lua_pcall(ctx, argc - 1, 0, lerrcb);
if (!ok) fprintf(stderr, "lua error: %%s\n", lua_tostring(ctx, -1));
return ok;
}
]];
local main_format = [[
#ifndef MKLUA_MAIN_NAME
#define MKLUA_MAIN_NAME main
#endif
MKLUA_EXPORT int MKLUA_MAIN_NAME(int argc, const char **argv) {
int ok;
lua_State *ctx = luaL_newstate();
luaL_openlibs(ctx);
ok = MKLUA_ENTRY_NAME(ctx, argc, argv);
lua_close(ctx);
return ok ? 0 : 1;
}
]];
@@ -164,10 +177,10 @@ local function emit_lua(name, filename, deps, func)
local lines = {};
local bc = string.dump(func or assert(loadfile(filename)), not debug);
table.insert(lines, "static int " .. funcname .. "(lua_State *ctx) {\n");
table.insert(lines, "MKLUA_INTERNAL int " .. funcname .. "(lua_State *ctx) {\n");
for i = 1, #deps do
table.insert(lines, ("\tluaL_requiref(ctx, %q, %s, false);\n"):format(deps[i][1], deps[i][2]));
table.insert(lines, ("\tluaL_requiref(ctx, %q, %s, 0);\n"):format(deps[i][1], deps[i][2]));
table.insert(lines, "\tlua_pop(ctx, 1);\n");
end
@@ -202,7 +215,7 @@ local function emit_luaopen(f, entry, name, path, cpath, debug, passed)
return funcname;
elseif type == "c" then
local funcname = "luaopen_" .. name:gsub("[.%-]", "_");
f:write("extern int ", funcname, "(lua_State *ctx);\n");
f:write("MKLUA_EXPORT int ", funcname, "(lua_State *ctx);\n");
passed[name] = funcname;
return funcname;
elseif is_entry then
@@ -216,21 +229,28 @@ local function emit_luaopen(f, entry, name, path, cpath, debug, passed)
error("entry '" .. name .. "' couldn't be resolved");
end
f:write("int luaopen_", name:gsub("[.%-]", "_"), "(lua_State *ctx) {\n");
f:write("MKLUA_EXPORT int luaopen_", name:gsub("[.%-]", "_"), "(lua_State *ctx) {\n");
f:write("\treturn ", funcname, "(ctx);\n");
f:write("}\n\n");
end
local function gen_c(f, entries, path, cpath, g, main)
local function gen_c(f, entries, path, cpath, g, main, entry, header)
f:write [[/* Generated by mklua */
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#ifndef MKLUA_INTERNAL
#define MKLUA_INTERNAL static
#endif
#ifndef MKLUA_EXPORT
#ifdef MKLUA_HEADER
#define MKLUA_EXPORT static
#else
#define MKLUA_EXPORT extern
#endif
#endif
]];
local passed = {};
@@ -240,24 +260,28 @@ local function gen_c(f, entries, path, cpath, g, main)
emit_luaopen(f, in_name, out_name, path, cpath, g, passed);
end
if main then
if entry then
local requiref_calls = {};
for i = 2, #entries do
local in_name, out_name = entries[i][1], entries[i][2];
table.insert(requiref_calls, ("luaL_requiref(ctx, %q, %s, false);"):format(out_name, passed[out_name]))
table.insert(requiref_calls, ("luaL_requiref(ctx, %q, %s, 0);"):format(out_name, passed[out_name]))
end
local func_name, func = emit_lua("__err_handle", "<internal>", {}, function ()
return debug.traceback;
end);
f:write(main_format:format(func, table.concat(requiref_calls, "\n\t\t"), func_name, entries[1][2], passed[entries[1][2]]));
f:write(entry_format:format(func, table.concat(requiref_calls, "\n\t\t"), func_name, entries[1][2], passed[entries[1][2]]));
if main then
f:write(main_format);
end
end
end
--- @param path string
--- @param cpath string
local function gen_makefile(f, entries, path, cpath, g, main)
local function gen_makefile(f, entries, path, cpath, g, main, entry, header)
local flags = {};
local entries_opts = {};
for i = 1, #entries do
@@ -295,13 +319,18 @@ local function gen_makefile(f, entries, path, cpath, g, main)
local cpath = fix_path(cpath, package.cpath);
if path then
table.insert(flags, "MKLUA_FLAGS += " .. "--path \"" .. path .. "\"");
table.insert(flags, "MKLUA_FLAGS += --path \"" .. path .. "\"");
end
if cpath then
table.insert(flags, "MKLUA_FLAGS += " .. "--cpath \"" .. cpath .. "\"");
table.insert(flags, "MKLUA_FLAGS += --cpath \"" .. cpath .. "\"");
end
if main then
table.insert(flags, "MKLUA_FLAGS += " .. "--main");
table.insert(flags, "MKLUA_FLAGS += --main");
elseif entry then
table.insert(flags, "MKLUA_FLAGS += --entry");
end
if header then
table.insert(flags, "MKLUA_FLAGS += --header");
end
f:write(make_format:format(table.concat(flags, "\n"), table.concat(entries_opts, "\n"), table.concat(entries_opts, " ")));
@@ -323,12 +352,21 @@ local function gen_deps(f, entries, path, cpath, g, main, only_libs)
end
end
local function open_w(path)
if path == "-" then
return io.stdout, function () end
else
local f = assert(io.open(path, "w"));
return f, f.close;
end
end
return function (...)
local path = package.path;
local cpath = package.cpath;
local main;
local out_path;
local mode = "c";
local main, entry;
local c_path, makefile_path;
local deps, libs, header;
local g = false;
local entries = {};
@@ -356,9 +394,6 @@ return function (...)
["debug"] = function ()
g = true;
end,
["main"] = function (arg)
main = true;
end,
["path"] = function (arg)
path = assert(arg())
:gsub("^;;", path .. ";")
@@ -372,22 +407,52 @@ return function (...)
:gsub(";;", ";" .. cpath .. ";");
end,
main = function (arg)
entry = true;
main = true;
end,
entry = function (arg)
entry = true;
end,
output = function (arg)
if out_path then
if c_path then
error "--output may be specified once";
end
out_path = assert(arg());
c_path = assert(arg());
end,
makefile = function (arg)
mode = "makefile";
if makefile_path then
error "--makefile may be specified once";
end
makefile_path = assert(arg());
end,
header = function (arg)
if header then
error "--header may be specified once";
end
header = true;
end,
deps = function (arg)
mode = "deps";
if deps then
error "--deps may be specified once";
elseif libs then
error "--deps and --libs are mutually-exclusive";
end
deps = true;
end,
libs = function (arg)
mode = "libs";
if libs then
error "--libs may be specified once";
elseif deps then
error "--deps and --libs are mutually-exclusive";
end
libs = true;
end,
o = "output",
@@ -395,24 +460,22 @@ return function (...)
h = "help",
} (...);
if #entries == 0 then
if not c_path and not makefile_path and not libs and not deps then
print(help_msg);
return;
end
local f = io.stdout;
if out_path and out_path ~= "-" then
f = assert(io.open(out_path, "w"));
if c_path then
local f, close = open_w(c_path);
gen_c(f, entries, path, cpath, g, main, entry, header);
close(f);
end
if mode == "makefile" then
return gen_makefile(f, entries, path, cpath, g, main);
elseif mode == "deps" then
return gen_deps(f, entries, path, cpath, g, main, false);
elseif mode == "libs" then
return gen_deps(f, entries, path, cpath, g, main, true);
else
return gen_c(f, entries, path, cpath, g, main);
if makefile_path then
local f, close = open_w(c_path);
gen_makefile(f, entries, path, cpath, g, main, header);
close(f);
end
if deps or libs then
gen_deps(io.stdout, entries, path, cpath, g, main, libs);
end
end