diff options
| author | T <t@tjp.lol> | 2026-05-26 10:33:24 -0600 |
|---|---|---|
| committer | T <t@tjp.lol> | 2026-05-26 10:42:41 -0600 |
| commit | edad4fc123099a780d960feea4fe37efb6d979d8 (patch) | |
| tree | 7fea8bf150fb80af493d7da65417872a4df460e5 | |
| parent | c2f727e188c1558bcc6b34569af2feab3b0366c0 (diff) | |
include and link lua 5.4, smoke test in panto cli main.zig
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | build.zig | 69 | ||||
| -rw-r--r-- | build.zig.zon | 4 | ||||
| -rw-r--r-- | src/main.zig | 32 |
4 files changed, 106 insertions, 1 deletions
@@ -1,3 +1,3 @@ .zig-cache/ -libawl/.zig-cache/ zig-out/ +zig-pkg/ @@ -9,13 +9,21 @@ pub fn build(b: *std.Build) void { .optimize = optimize, }); + // Fetch upstream Lua 5.4.7 (source-only tarball from lua.org). + // Reproducibility comes from the content-addressed hash in build.zig.zon. + const lua_src = b.dependency("lua_src", .{}); + const lua = buildLua(b, target, optimize, lua_src); + // CLI executable const exe_mod = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, + .link_libc = true, }); exe_mod.addImport("panto", panto_lib_dep.module("panto")); + exe_mod.linkLibrary(lua); + exe_mod.addIncludePath(lua_src.path("src")); const exe = b.addExecutable(.{ .name = "panto", @@ -38,8 +46,11 @@ pub fn build(b: *std.Build) void { .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, + .link_libc = true, }); test_mod.addImport("panto", panto_lib_dep.module("panto")); + test_mod.linkLibrary(lua); + test_mod.addIncludePath(lua_src.path("src")); const unit_tests = b.addTest(.{ .name = "panto-tests", @@ -54,3 +65,61 @@ pub fn build(b: *std.Build) void { const lib_test_step = panto_lib_dep.builder.top_level_steps.get("test").?; test_step.dependOn(&lib_test_step.step); } + +/// Compile Lua 5.4.7 as a static library against the upstream source tarball. +/// Excludes `lua.c` (interpreter REPL) and `luac.c` (bytecode compiler) — we +/// only want the embedded library. +fn buildLua( + b: *std.Build, + target: std.Build.ResolvedTarget, + optimize: std.builtin.OptimizeMode, + lua_src: *std.Build.Dependency, +) *std.Build.Step.Compile { + const lua_mod = b.createModule(.{ + .target = target, + .optimize = optimize, + .link_libc = true, + }); + + const cflags = [_][]const u8{ + "-std=gnu99", + "-Wall", + "-Wextra", + "-Wno-unused-parameter", + }; + + lua_mod.addCSourceFiles(.{ + .root = lua_src.path("src"), + .files = &lua_files, + .flags = &cflags, + }); + + // Tell Lua which platform features are available. The macros change + // which `dlopen`/readline/etc. paths Lua compiles in. + switch (target.result.os.tag) { + .macos => lua_mod.addCMacro("LUA_USE_MACOSX", ""), + .linux => lua_mod.addCMacro("LUA_USE_LINUX", ""), + .freebsd, .netbsd, .openbsd => lua_mod.addCMacro("LUA_USE_POSIX", ""), + else => {}, + } + + return b.addLibrary(.{ + .name = "lua", + .linkage = .static, + .root_module = lua_mod, + }); +} + +// Lua 5.4.7 core VM + standard library. Excludes lua.c (interpreter entry +// point) and luac.c (compiler entry point). +const lua_files = [_][]const u8{ + // Core VM + "lapi.c", "lcode.c", "lctype.c", "ldebug.c", "ldo.c", + "ldump.c", "lfunc.c", "lgc.c", "llex.c", "lmem.c", + "lobject.c", "lopcodes.c", "lparser.c", "lstate.c", "lstring.c", + "ltable.c", "ltm.c", "lundump.c", "lvm.c", "lzio.c", + // Auxiliary + standard library + "lauxlib.c", "lbaselib.c", "lcorolib.c", "ldblib.c", "liolib.c", + "lmathlib.c", "loadlib.c", "loslib.c", "lstrlib.c", "ltablib.c", + "lutf8lib.c", "linit.c", +}; diff --git a/build.zig.zon b/build.zig.zon index 5531d78..82794fc 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -6,6 +6,10 @@ .panto = .{ .path = "libpanto", }, + .lua_src = .{ + .url = "https://www.lua.org/ftp/lua-5.4.7.tar.gz", + .hash = "N-V-__8AAIMvFABt-Qcpk24RD10ldEN743D8Q2e19Er8x3dJ", + }, }, .paths = .{ "build.zig", diff --git a/src/main.zig b/src/main.zig index 20da910..6fbdb4b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,6 +2,14 @@ const std = @import("std"); const panto = @import("panto"); const ping_tool = @import("ping_tool.zig"); +// Lua 5.4 C API. Linked statically via build.zig from the upstream lua.org +// source tarball pinned in build.zig.zon. +const lua = @cImport({ + @cInclude("lua.h"); + @cInclude("lauxlib.h"); + @cInclude("lualib.h"); +}); + const Receiver = panto.provider.Receiver; const ReceiverVTable = panto.provider.ReceiverVTable; const ContentBlockType = panto.provider.ContentBlockType; @@ -92,6 +100,26 @@ const CLIReceiver = struct { } }; +/// Spin up a Lua interpreter, run a no-op, tear it down. Catches +/// link/compile errors on the Lua dependency at the earliest moment. +/// Logs only in debug builds; release builds run silently. +fn luaSmokeCheck() void { + const L = lua.luaL_newstate() orelse { + std.log.err("lua: luaL_newstate returned null", .{}); + return; + }; + defer lua.lua_close(L); + lua.luaL_openlibs(L); + + // Push _VERSION to confirm libs loaded. + _ = lua.lua_getglobal(L, "_VERSION"); + const ver = lua.lua_tolstring(L, -1, null); + if (ver != null) { + std.log.debug("lua: {s} linked OK", .{ver}); + } + lua.lua_settop(L, 0); +} + fn loadConfig(environ_map: *const std.process.Environ.Map) !panto.config.Config { const style_str = environ_map.get("PANTO_API_STYLE") orelse "openai_chat"; const style = std.meta.stringToEnum(panto.config.APIStyle, style_str) orelse { @@ -167,6 +195,10 @@ pub fn main(init: std.process.Init) !void { const alloc = init.gpa; const io = init.io; + // Smoke test: prove Lua is linked. Slice 1 — no extension runtime + // wired up yet, this just confirms the static lib comes through. + luaSmokeCheck(); + const config = try loadConfig(init.environ_map); var stdout_buffer: [4096]u8 = undefined; |
