some stuff
This commit is contained in:
2
Makefile
2
Makefile
@@ -10,7 +10,7 @@ LDARGS_LUA ?= $(shell pkg-config --libs lua5.4)
|
|||||||
CCARGS += $(CCARGS_LUA)
|
CCARGS += $(CCARGS_LUA)
|
||||||
LDARGS += $(LDARGS_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_FLAGS += --main
|
||||||
|
|
||||||
MKLUA_ENTRIES += mklua
|
MKLUA_ENTRIES += mklua
|
||||||
|
|||||||
189
src/mklua.lua
189
src/mklua.lua
@@ -13,7 +13,10 @@ Flags:
|
|||||||
--libs - outputs a list of native libraries the entries depend on
|
--libs - outputs a list of native libraries the entries depend on
|
||||||
--makefile - generates a makefile
|
--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
|
--output=<file> (-o <file>) - the file to write to
|
||||||
--debug (-g) - emits debugging data in the lua bytecode
|
--debug (-g) - emits debugging data in the lua bytecode
|
||||||
|
|
||||||
@@ -21,47 +24,57 @@ Flags:
|
|||||||
--cpath - specifies a c path to search
|
--cpath - specifies a c path to search
|
||||||
]];
|
]];
|
||||||
|
|
||||||
local main_format = [[
|
local entry_format = [[
|
||||||
#ifndef MKLUA_MAIN_NAME
|
#ifndef MKLUA_ENTRY_NAME
|
||||||
#define MKLUA_MAIN_NAME main
|
#define MKLUA_ENTRY_NAME mklua_entry
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
%s
|
%s
|
||||||
|
|
||||||
int MKLUA_MAIN_NAME(int argc, const char **argv) {
|
MKLUA_EXPORT int MKLUA_ENTRY_NAME(lua_State *ctx, int argc, const char **argv) {
|
||||||
lua_State *ctx = luaL_newstate();
|
int larg, lerrcb, i, ok;
|
||||||
luaL_openlibs(ctx);
|
|
||||||
lua_checkstack(ctx, argc + 16);
|
lua_checkstack(ctx, argc + 16);
|
||||||
|
|
||||||
/* Emit other requiref-s */
|
/* Emit other requiref-s */
|
||||||
%s
|
%s
|
||||||
|
|
||||||
lua_createtable(ctx, argc, 0);
|
lua_createtable(ctx, argc, 0);
|
||||||
int larg = lua_gettop(ctx);
|
larg = lua_gettop(ctx);
|
||||||
|
|
||||||
lua_pushvalue(ctx, larg);
|
lua_pushvalue(ctx, larg);
|
||||||
lua_setglobal(ctx, "arg");
|
lua_setglobal(ctx, "arg");
|
||||||
|
|
||||||
luaL_requiref(ctx, "__err_handle", %s, false);
|
luaL_requiref(ctx, "__err_handle", %s, 0);
|
||||||
int lerrcb = lua_gettop(ctx);
|
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_pushstring(ctx, argv[i]);
|
||||||
lua_pushvalue(ctx, -1);
|
lua_pushvalue(ctx, -1);
|
||||||
lua_seti(ctx, larg, i);
|
lua_seti(ctx, larg, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lua_pcall(ctx, argc - 1, 0, lerrcb)) {
|
ok = !lua_pcall(ctx, argc - 1, 0, lerrcb);
|
||||||
fprintf(stderr, "lua error: %%s\n", lua_tostring(ctx, -1));
|
if (!ok) fprintf(stderr, "lua error: %%s\n", lua_tostring(ctx, -1));
|
||||||
lua_close(ctx);
|
|
||||||
return 1;
|
return ok;
|
||||||
}
|
}
|
||||||
else {
|
]];
|
||||||
lua_close(ctx);
|
|
||||||
return 0;
|
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 lines = {};
|
||||||
local bc = string.dump(func or assert(loadfile(filename)), not debug);
|
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
|
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");
|
table.insert(lines, "\tlua_pop(ctx, 1);\n");
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -202,7 +215,7 @@ local function emit_luaopen(f, entry, name, path, cpath, debug, passed)
|
|||||||
return funcname;
|
return funcname;
|
||||||
elseif type == "c" then
|
elseif type == "c" then
|
||||||
local funcname = "luaopen_" .. name:gsub("[.%-]", "_");
|
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;
|
passed[name] = funcname;
|
||||||
return funcname;
|
return funcname;
|
||||||
elseif is_entry then
|
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");
|
error("entry '" .. name .. "' couldn't be resolved");
|
||||||
end
|
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("\treturn ", funcname, "(ctx);\n");
|
||||||
f:write("}\n\n");
|
f:write("}\n\n");
|
||||||
end
|
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 */
|
f:write [[/* Generated by mklua */
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lualib.h>
|
#include <lualib.h>
|
||||||
#include <lauxlib.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 = {};
|
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);
|
emit_luaopen(f, in_name, out_name, path, cpath, g, passed);
|
||||||
end
|
end
|
||||||
|
|
||||||
if main then
|
if entry then
|
||||||
local requiref_calls = {};
|
local requiref_calls = {};
|
||||||
|
|
||||||
for i = 2, #entries do
|
for i = 2, #entries do
|
||||||
local in_name, out_name = entries[i][1], entries[i][2];
|
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
|
end
|
||||||
|
|
||||||
local func_name, func = emit_lua("__err_handle", "<internal>", {}, function ()
|
local func_name, func = emit_lua("__err_handle", "<internal>", {}, function ()
|
||||||
return debug.traceback;
|
return debug.traceback;
|
||||||
end);
|
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
|
||||||
end
|
end
|
||||||
--- @param path string
|
--- @param path string
|
||||||
--- @param cpath 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 flags = {};
|
||||||
local entries_opts = {};
|
local entries_opts = {};
|
||||||
for i = 1, #entries do
|
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);
|
local cpath = fix_path(cpath, package.cpath);
|
||||||
|
|
||||||
if path then
|
if path then
|
||||||
table.insert(flags, "MKLUA_FLAGS += " .. "--path \"" .. path .. "\"");
|
table.insert(flags, "MKLUA_FLAGS += --path \"" .. path .. "\"");
|
||||||
end
|
end
|
||||||
if cpath then
|
if cpath then
|
||||||
table.insert(flags, "MKLUA_FLAGS += " .. "--cpath \"" .. cpath .. "\"");
|
table.insert(flags, "MKLUA_FLAGS += --cpath \"" .. cpath .. "\"");
|
||||||
end
|
end
|
||||||
if main then
|
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
|
end
|
||||||
|
|
||||||
f:write(make_format:format(table.concat(flags, "\n"), table.concat(entries_opts, "\n"), table.concat(entries_opts, " ")));
|
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
|
||||||
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 (...)
|
return function (...)
|
||||||
local path = package.path;
|
local path = package.path;
|
||||||
local cpath = package.cpath;
|
local cpath = package.cpath;
|
||||||
local main;
|
local main, entry;
|
||||||
local out_path;
|
local c_path, makefile_path;
|
||||||
local mode = "c";
|
local deps, libs, header;
|
||||||
local g = false;
|
local g = false;
|
||||||
|
|
||||||
local entries = {};
|
local entries = {};
|
||||||
@@ -356,9 +394,6 @@ return function (...)
|
|||||||
["debug"] = function ()
|
["debug"] = function ()
|
||||||
g = true;
|
g = true;
|
||||||
end,
|
end,
|
||||||
["main"] = function (arg)
|
|
||||||
main = true;
|
|
||||||
end,
|
|
||||||
["path"] = function (arg)
|
["path"] = function (arg)
|
||||||
path = assert(arg())
|
path = assert(arg())
|
||||||
:gsub("^;;", path .. ";")
|
:gsub("^;;", path .. ";")
|
||||||
@@ -372,22 +407,52 @@ return function (...)
|
|||||||
:gsub(";;", ";" .. cpath .. ";");
|
:gsub(";;", ";" .. cpath .. ";");
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
main = function (arg)
|
||||||
|
entry = true;
|
||||||
|
main = true;
|
||||||
|
end,
|
||||||
|
entry = function (arg)
|
||||||
|
entry = true;
|
||||||
|
end,
|
||||||
|
|
||||||
output = function (arg)
|
output = function (arg)
|
||||||
if out_path then
|
if c_path then
|
||||||
error "--output may be specified once";
|
error "--output may be specified once";
|
||||||
end
|
end
|
||||||
|
|
||||||
out_path = assert(arg());
|
c_path = assert(arg());
|
||||||
end,
|
end,
|
||||||
|
|
||||||
makefile = function (arg)
|
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,
|
end,
|
||||||
deps = function (arg)
|
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,
|
end,
|
||||||
libs = function (arg)
|
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,
|
end,
|
||||||
|
|
||||||
o = "output",
|
o = "output",
|
||||||
@@ -395,24 +460,22 @@ return function (...)
|
|||||||
h = "help",
|
h = "help",
|
||||||
} (...);
|
} (...);
|
||||||
|
|
||||||
if #entries == 0 then
|
if not c_path and not makefile_path and not libs and not deps then
|
||||||
print(help_msg);
|
print(help_msg);
|
||||||
return;
|
return;
|
||||||
end
|
end
|
||||||
|
|
||||||
local f = io.stdout;
|
if c_path then
|
||||||
|
local f, close = open_w(c_path);
|
||||||
if out_path and out_path ~= "-" then
|
gen_c(f, entries, path, cpath, g, main, entry, header);
|
||||||
f = assert(io.open(out_path, "w"));
|
close(f);
|
||||||
end
|
end
|
||||||
|
if makefile_path then
|
||||||
if mode == "makefile" then
|
local f, close = open_w(c_path);
|
||||||
return gen_makefile(f, entries, path, cpath, g, main);
|
gen_makefile(f, entries, path, cpath, g, main, header);
|
||||||
elseif mode == "deps" then
|
close(f);
|
||||||
return gen_deps(f, entries, path, cpath, g, main, false);
|
end
|
||||||
elseif mode == "libs" then
|
if deps or libs then
|
||||||
return gen_deps(f, entries, path, cpath, g, main, true);
|
gen_deps(io.stdout, entries, path, cpath, g, main, libs);
|
||||||
else
|
|
||||||
return gen_c(f, entries, path, cpath, g, main);
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user