summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--build.zig69
-rw-r--r--build.zig.zon4
-rw-r--r--src/main.zig32
4 files changed, 106 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 495638d..03cb27d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
.zig-cache/
-libawl/.zig-cache/
zig-out/
+zig-pkg/
diff --git a/build.zig b/build.zig
index 5d4cdb6..e675859 100644
--- a/build.zig
+++ b/build.zig
@@ -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;