summaryrefslogtreecommitdiff
path: root/binary/all_in_one
diff options
context:
space:
mode:
Diffstat (limited to 'binary/all_in_one')
-rwxr-xr-xbinary/all_in_one503
1 files changed, 503 insertions, 0 deletions
diff --git a/binary/all_in_one b/binary/all_in_one
new file mode 100755
index 0000000..9b675eb
--- /dev/null
+++ b/binary/all_in_one
@@ -0,0 +1,503 @@
+#!/usr/bin/env lua
+--[[
+
+All-in-one packager for LuaRocks
+ * by Hisham Muhammad <hisham@gobolinux.org>
+ * licensed under the same terms as Lua (MIT license).
+
+Based on:
+
+* srlua.c - Lua interpreter for self-running programs
+ * by Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
+ * 03 Nov 2014 15:31:43
+ * srlua.c is placed in the public domain.
+* bin2c.lua - converts a binary to a C string that can be embedded
+ * by Mark Edgar
+ * http://lua-users.org/wiki/BinTwoCee
+ * bin2c.lua is licensed under the same terms as Lua (MIT license).
+* lua.c - Lua stand-alone interpreter
+ * by Luiz Henrique de Figueiredo, Waldemar Celes, Roberto Ierusalimschy
+ * lua.c is licensed under the same terms as Lua (MIT license).
+* luastatic - builds a standalone executable from a Lua program
+ * by Eric R. Schulz
+ * https://github.com/ers35/luastatic
+ * luastatic is licensed under the CC0 1.0 Universal license
+
+]]
+
+local MAIN_PROGRAM = arg[1] or "src/bin/luarocks"
+local LUA_DIR = arg[2] or "/usr"
+local EXCLUDE = arg[3] or "^src/luarocks/admin/"
+local SYSCONFDIR = arg[4] or "/etc/luarocks"
+local TARGET_DIR = arg[5] or "build-binary"
+local FORCE_CONFIG = (arg[6] == "yes")
+local MY_PLATFORM = arg[7] or "unix"
+local CC = arg[8] or "gcc"
+local NM = arg[9] or "nm"
+local CROSSCOMPILER_SYSROOT = arg[10] or "/usr/lib/mingw-w64-sysroot/i686-w64-mingw32"
+local TRIPLET = arg[11] or CROSSCOMPILER_SYSROOT:gsub(".*/", "")
+local PROCESSOR = arg[12] or TRIPLET:gsub("%-.*", "")
+if PROCESSOR == "i686" then
+ PROCESSOR = "x86"
+end
+
+local LUA_MODULES = TARGET_DIR .. "/lua_modules"
+local CONFIG_DIR = TARGET_DIR .. "/.luarocks"
+
+package.path = "./src/?.lua;" .. package.path
+
+local fs = require("luarocks.fs")
+local cfg = require("luarocks.core.cfg")
+local cmd = require("luarocks.cmd")
+local deps = require("luarocks.deps")
+local path = require("luarocks.path")
+local manif = require("luarocks.manif")
+local queries = require("luarocks.queries")
+local persist = require("luarocks.persist")
+local sysdetect = require("luarocks.core.sysdetect")
+
+--------------------------------------------------------------------------------
+
+local function if_platform(plat, val)
+ if MY_PLATFORM == plat then
+ return val
+ end
+end
+
+local function reindent_c(input)
+ local out = {}
+ local indent = 0
+ local previous_is_blank = true
+ for line in input:gmatch("([^\n]*)") do
+ line = line:match("^[ \t]*(.-)[ \t]*$")
+
+ local is_blank = (#line == 0)
+ local do_print =
+ (not is_blank) or
+ (not previous_is_blank and indent == 0)
+
+ if line:match("^[})]") then
+ indent = indent - 1
+ if indent < 0 then indent = 0 end
+ end
+ if do_print then
+ table.insert(out, string.rep(" ", indent))
+ table.insert(out, line)
+ table.insert(out, "\n")
+ end
+ if line:match("[{(]$") then
+ indent = indent + 1
+ end
+
+ previous_is_blank = is_blank
+ end
+ return table.concat(out)
+end
+
+local hexdump
+do
+ local numtab = {}
+ for i = 0, 255 do
+ numtab[string.char(i)] = ("%-3d,"):format(i)
+ end
+ function hexdump(str)
+ return (str:gsub(".", numtab):gsub(("."):rep(80), "%0\n"))
+ end
+end
+
+local c_preamble = [[
+
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* portable alerts, from srlua */
+#ifdef _WIN32
+#include <windows.h>
+#define alert(message) MessageBox(NULL, message, progname, MB_ICONERROR | MB_OK)
+#define getprogname() char name[MAX_PATH]; argv[0]= GetModuleFileName(NULL,name,sizeof(name)) ? name : NULL;
+#else
+#define alert(message) fprintf(stderr,"%s: %s\n", progname, message)
+#define getprogname()
+#endif
+
+static int registry_key;
+
+/* fatal error, from srlua */
+static void fatal(const char* message) {
+ alert(message);
+ exit(EXIT_FAILURE);
+}
+
+]]
+
+local function bin2c_file(out, filename)
+ local fd = io.open(filename, "rb")
+ local content = fd:read("*a"):gsub("^#![^\n]+\n", "")
+ fd:close()
+ table.insert(out, ("static const unsigned char code[] = {"))
+ table.insert(out, hexdump(content))
+ table.insert(out, ("};"))
+end
+
+local function write_hardcoded_module(dir)
+
+ local system, processor
+ if if_platform("unix", true) then
+ system, processor = sysdetect.detect()
+ else
+ system, processor = "windows", PROCESSOR
+ end
+
+ local hardcoded = {
+ SYSTEM = system,
+ PROCESSOR = processor,
+ FORCE_CONFIG = FORCE_CONFIG,
+ IS_BINARY = true,
+
+ SYSCONFDIR = if_platform("unix", SYSCONFDIR),
+ }
+
+ local name = dir .. "/luarocks/core/hardcoded.lua"
+ persist.save_as_module(name, hardcoded)
+ return name
+end
+
+local function declare_modules(out, dirs, skip)
+ skip = skip or {}
+ table.insert(out, [[
+ static void declare_modules(lua_State* L) {
+ lua_settop(L, 0); /* */
+ lua_newtable(L); /* modules */
+ lua_pushlightuserdata(L, (void*) &registry_key); /* modules registry_key */
+ lua_pushvalue(L, 1); /* modules registry_key modules */
+ lua_rawset(L, LUA_REGISTRYINDEX); /* modules */
+ ]])
+ for _, dir in ipairs(dirs) do
+ for _, name in ipairs(fs.find(dir)) do
+ local run = true
+ for _, pat in ipairs(skip) do
+ if name:match(pat) then
+ run = false
+ break
+ end
+ end
+ if run then
+ local filename = dir .. "/" .. name
+ if fs.is_file(filename) then
+ print(name)
+ local modname = name:gsub("%.lua$", ""):gsub("/", ".")
+ table.insert(out, ("/* %s */"):format(modname))
+ table.insert(out, ("{"))
+ bin2c_file(out, filename)
+ table.insert(out, ("luaL_loadbuffer(L, code, sizeof(code), %q);"):format(filename))
+ table.insert(out, ("lua_setfield(L, 1, %q);"):format(modname))
+ table.insert(out, ("}"))
+ end
+ end
+ end
+ end
+ table.insert(out, [[
+ lua_settop(L, 0); /* */
+ }
+ ]])
+end
+
+local function nm(filename)
+ local pd = io.popen(NM .. " " .. filename)
+ local out = pd:read("*a")
+ pd:close()
+ return out
+end
+
+local function declare_libraries(out, dir)
+ local a_files = {}
+ local externs = {}
+ local fn = {}
+ table.insert(fn, [[
+ static void declare_libraries(lua_State* L) {
+ lua_getglobal(L, "package"); /* package */
+ lua_getfield(L, -1, "preload"); /* package package.preload */
+ ]])
+ for _, name in ipairs(fs.find(dir)) do
+ local filename = dir .. "/" .. name
+ if name:match("%.a$") then
+ table.insert(a_files, filename)
+ local nmout = nm(filename)
+ for luaopen in nmout:gmatch("[^dD] _?(luaopen_[%a%p%d]+)") do
+
+ -- FIXME what about module names with underscores?
+ local modname = luaopen:gsub("^_?luaopen_", ""):gsub("_", ".")
+
+ table.insert(externs, "extern int " .. luaopen .. "(lua_State* L);")
+ table.insert(fn, "lua_pushcfunction(L, " .. luaopen .. ");")
+ table.insert(fn, "lua_setfield(L, -2, \"" .. modname .. "\");")
+ end
+ end
+ end
+ local pd = io.popen("find " .. dir .. " -name '*.a'", "r")
+ for line in pd:lines() do
+ table.insert(a_files, line)
+ end
+ pd:close()
+ table.insert(fn, [[
+ lua_settop(L, 0); /* */
+ }
+ ]])
+
+ table.insert(out, "\n")
+ for _, line in ipairs(externs) do
+ table.insert(out, line)
+ end
+ table.insert(out, "\n")
+ for _, line in ipairs(fn) do
+ table.insert(out, line)
+ end
+ table.insert(out, "\n")
+
+ return a_files
+end
+
+local function load_main(out, main_program, program_name)
+ table.insert(out, [[static void load_main(lua_State* L) {]])
+ bin2c_file(out, main_program)
+ table.insert(out, ("if(luaL_loadbuffer(L, code, sizeof(code), %q) != LUA_OK) {"):format(program_name))
+ table.insert(out, (" fatal(lua_tostring(L, -1));"))
+ table.insert(out, ("}"))
+ table.insert(out, [[}]])
+ table.insert(out, [[]])
+end
+
+local c_main = [[
+
+/* custom package loader */
+static int pkg_loader(lua_State* L) {
+ lua_pushlightuserdata(L, (void*) &registry_key); /* modname ? registry_key */
+ lua_rawget(L, LUA_REGISTRYINDEX); /* modname ? modules */
+ lua_pushvalue(L, -1); /* modname ? modules modules */
+ lua_pushvalue(L, 1); /* modname ? modules modules modname */
+ lua_gettable(L, -2); /* modname ? modules mod */
+ if (lua_type(L, -1) == LUA_TNIL) {
+ lua_pop(L, 1); /* modname ? modules */
+ lua_pushvalue(L, 1); /* modname ? modules modname */
+ lua_pushliteral(L, ".init"); /* modname ? modules modname ".init" */
+ lua_concat(L, 2); /* modname ? modules modname..".init" */
+ lua_gettable(L, -2); /* modname ? mod */
+ }
+ return 1;
+}
+
+static void install_pkg_loader(lua_State* L) {
+ lua_settop(L, 0); /* */
+ lua_getglobal(L, "table"); /* table */
+ lua_getfield(L, -1, "insert"); /* table table.insert */
+ lua_getglobal(L, "package"); /* table table.insert package */
+ lua_getfield(L, -1, "searchers"); /* table table.insert package package.searchers */
+ if (lua_type(L, -1) == LUA_TNIL) {
+ lua_pop(L, 1);
+ lua_getfield(L, -1, "loaders"); /* table table.insert package package.loaders */
+ }
+ lua_copy(L, 4, 3); /* table table.insert package.searchers */
+ lua_settop(L, 3); /* table table.insert package.searchers */
+ lua_pushnumber(L, 1); /* table table.insert package.searchers 1 */
+ lua_pushcfunction(L, pkg_loader); /* table table.insert package.searchers 1 pkg_loader */
+ lua_call(L, 3, 0); /* table */
+ lua_settop(L, 0); /* */
+}
+
+/* main script launcher, from srlua */
+static int pmain(lua_State *L) {
+ int argc = lua_tointeger(L, 1);
+ char** argv = lua_touserdata(L, 2);
+ int i;
+ load_main(L);
+ lua_createtable(L, argc, 0);
+ for (i = 0; i < argc; i++) {
+ lua_pushstring(L, argv[i]);
+ lua_rawseti(L, -2, i);
+ }
+ lua_setglobal(L, "arg");
+ luaL_checkstack(L, argc - 1, "too many arguments to script");
+ for (i = 1; i < argc; i++) {
+ lua_pushstring(L, argv[i]);
+ }
+ lua_call(L, argc - 1, 0);
+ return 0;
+}
+
+/* error handler, from luac */
+static int msghandler (lua_State *L) {
+ /* is error object not a string? */
+ const char *msg = lua_tostring(L, 1);
+ if (msg == NULL) {
+ /* does it have a metamethod that produces a string */
+ if (luaL_callmeta(L, 1, "__tostring") && lua_type(L, -1) == LUA_TSTRING) {
+ /* then that is the message */
+ return 1;
+ } else {
+ msg = lua_pushfstring(L, "(error object is a %s value)", luaL_typename(L, 1));
+ }
+ }
+ /* append a standard traceback */
+ luaL_traceback(L, L, msg, 1);
+ return 1;
+}
+
+/* main function, from srlua */
+int main(int argc, char** argv) {
+ lua_State* L;
+ getprogname();
+ if (argv[0] == NULL) {
+ fatal("cannot locate this executable");
+ }
+ L = luaL_newstate();
+ if (L == NULL) {
+ fatal("not enough memory for state");
+ }
+ luaL_openlibs(L);
+ install_pkg_loader(L);
+ declare_libraries(L);
+ declare_modules(L);
+ lua_pushcfunction(L, &msghandler);
+ lua_pushcfunction(L, &pmain);
+ lua_pushinteger(L, argc);
+ lua_pushlightuserdata(L, argv);
+ if (lua_pcall(L, 2, 0, -4) != 0) {
+ fatal(lua_tostring(L, -1));
+ }
+ lua_close(L);
+ return EXIT_SUCCESS;
+}
+
+]]
+
+local function filter_in(f, xs)
+ for i = #xs, 1, -1 do
+ if not f(xs[i]) then
+ table.remove(xs, i)
+ end
+ end
+ return xs
+end
+
+local function nonnull(x) return x ~= nil end
+
+local function generate(main_program, dir, skip)
+ local program_name = main_program:gsub(".*/", "")
+
+ local hardcoded = write_hardcoded_module(dir)
+
+ local out = {}
+ table.insert(out, ([[static const char* progname = %q;]]):format(program_name))
+ table.insert(out, c_preamble)
+ load_main(out, main_program, program_name)
+ local lua_modules = LUA_MODULES .. "/share/lua/" .. cfg.lua_version
+ declare_modules(out, { dir, lua_modules }, skip)
+ local a_files = declare_libraries(out, LUA_MODULES .. "/lib/lua/" .. cfg.lua_version)
+ table.insert(out, c_main)
+
+ os.remove(hardcoded)
+
+ local c_filename = TARGET_DIR .. "/" .. program_name .. ".exe.c"
+ local fd = io.open(c_filename, "w")
+ fd:write(reindent_c(table.concat(out, "\n")))
+ fd:close()
+
+ assert(deps.check_lua_incdir(cfg.variables))
+ assert(deps.check_lua_libdir(cfg.variables))
+
+ cmd = table.concat(filter_in(nonnull, {
+ CC, "-o", TARGET_DIR .. "/" .. program_name .. ".exe",
+ "-I", cfg.variables.LUA_INCDIR,
+ if_platform("unix", "-rdynamic"),
+ "-Os",
+ c_filename,
+ "-L", cfg.variables.LUA_LIBDIR,
+ table.concat(a_files, " "),
+ --if_platform("unix", cfg.variables.LUA_LIBDIR .. "/" .. cfg.variables.LUALIB:gsub("%.so.*$", ".a")),
+ --if_platform("windows", "mingw/liblua.a"), -- FIXME
+ cfg.variables.LUA_LIBDIR .. "/" .. cfg.variables.LUALIB:gsub("%.so.*$", ".a"),
+ if_platform("unix", "-ldl"),
+ if_platform("unix", "-lpthread"),
+ if_platform("windows", "-mconsole -mwindows"),
+ "-lm"
+ }), " ")
+ print(cmd)
+ os.execute(cmd)
+end
+
+--------------------------------------------------------------------------------
+
+local function main()
+
+ os.remove("src/luarocks/core/hardcoded.lua")
+ cfg.init()
+ cfg.variables.LUA_DIR = LUA_DIR
+ cfg.variables.LUA_INCDIR = nil -- let it autodetect later
+ cfg.variables.LUA_LIBDIR = nil -- let it autodetect later
+ fs.init()
+ path.use_tree(LUA_MODULES)
+
+ local CONFIG_FILE = CONFIG_DIR .. "/config-" .. cfg.lua_version .. ".lua"
+
+ fs.make_dir(CONFIG_DIR)
+
+ persist.save_from_table(CONFIG_FILE, {
+ lib_extension = "a",
+ external_lib_extension = "a",
+ variables = {
+ CC = fs.current_dir() .. "/binary/static-gcc",
+ LD = fs.current_dir() .. "/binary/static-gcc",
+ LIB_EXTENSION = "a",
+ LUA_DIR = LUA_DIR,
+ LIBFLAG = "-static",
+ PWD = "pwd",
+ MKDIR = "mkdir",
+ },
+ platforms = if_platform("windows", { "windows", "win32", "mingw32" }),
+ external_deps_dirs = if_platform("windows", { CROSSCOMPILER_SYSROOT, fs.current_dir() .. "/windows-deps-" .. TRIPLET }),
+ })
+
+ local dependencies = {
+ md5 = "md5",
+ luasocket = "./binary/luasocket-3.1.0-1.rockspec",
+ luasec = "./binary/luasec-1.3.2-1.rockspec",
+ ["lua-zlib"] = "./binary/lua-zlib-1.2-0.rockspec",
+ ["lua-bz2"] = "./binary/lua-bz2-0.2.1-1.rockspec",
+ luaposix = if_platform("unix", "./binary/luaposix-35.1-1.rockspec"),
+ luafilesystem = "luafilesystem",
+ }
+
+ local dependency_order = {
+ "md5",
+ "luasocket", "luasec",
+ "lua-zlib",
+ "lua-bz2",
+ "luaposix",
+ "luafilesystem",
+ }
+
+ fs.make_dir(LUA_MODULES)
+ for _, name in ipairs(dependency_order) do
+ local use = dependencies[name]
+ if use then
+ print("----------------------------------------------------------------")
+ print(name)
+ print("----------------------------------------------------------------")
+ local vers = manif.get_versions(queries.from_dep_string(name), "one")
+ if not next(vers) then
+ local ok = os.execute("LUAROCKS_CONFIG='" .. CONFIG_FILE .. "' ./luarocks install --no-project '--tree=" .. LUA_MODULES .. "' " .. use)
+ if ok ~= 0 and ok ~= true then
+ error("Failed building dependency: " .. name)
+ end
+ end
+ end
+ end
+
+ generate(MAIN_PROGRAM, "src", { EXCLUDE, "^bin/?" })
+end
+
+main()