const std = @import("std"); pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const panto_mod = b.addModule("panto", .{ .root_source_file = b.path("src/public.zig"), .target = target, .optimize = optimize, .link_libc = true, }); addImageCDeps(b, panto_mod); const panto_tests = b.addTest(.{ .name = "panto-tests", .root_module = pantoTestModule(b, target, optimize), }); const lua_src = b.dependency("lua_src", .{}); const panto_lua = buildLuaModule(b, target, optimize, panto_mod, lua_src); const panto_lua_tests = buildLuaTests(b, target, optimize, panto_mod, lua_src); const panto_c = buildCLibrary(b, target, optimize, panto_mod); const panto_c_tests = b.addTest(.{ .name = "panto-c-tests", .root_module = cModule(b, target, optimize, panto_mod), }); b.installArtifact(panto_lua); b.installArtifact(panto_c); b.installFile("libpanto-c/include/panto.h", "include/panto.h"); const install_lua_so = b.addInstallFileWithDir( panto_lua.getEmittedBin(), .lib, "panto.so", ); b.getInstallStep().dependOn(&install_lua_so.step); const test_step = b.step("test", "Run unit tests"); test_step.dependOn(&b.addRunArtifact(panto_tests).step); test_step.dependOn(&b.addRunArtifact(panto_lua_tests).step); test_step.dependOn(&b.addRunArtifact(panto_c_tests).step); } fn pantoTestModule( b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, ) *std.Build.Module { const mod = b.createModule(.{ .root_source_file = b.path("src/public.zig"), .target = target, .optimize = optimize, .link_libc = true, }); addImageCDeps(b, mod); return mod; } fn buildLuaModule( b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, panto_mod: *std.Build.Module, lua_src: *std.Build.Dependency, ) *std.Build.Step.Compile { const mod = b.createModule(.{ .root_source_file = b.path("libpanto-lua/src/module.zig"), .target = target, .optimize = optimize, .link_libc = true, }); mod.addImport("panto", panto_mod); mod.addIncludePath(lua_src.path("src")); const lib = b.addLibrary(.{ .name = "panto_lua", .root_module = mod, .linkage = .dynamic, }); lib.rdynamic = true; allowUndefinedHostSymbols(lib, target); return lib; } fn buildLuaTests( b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, panto_mod: *std.Build.Module, lua_src: *std.Build.Dependency, ) *std.Build.Step.Compile { const mod = b.createModule(.{ .root_source_file = b.path("libpanto-lua/src/module.zig"), .target = target, .optimize = optimize, .link_libc = true, }); mod.addImport("panto", panto_mod); mod.addIncludePath(lua_src.path("src")); addLuaForTests(mod, lua_src); return b.addTest(.{ .name = "panto-lua-tests", .root_module = mod, }); } fn buildCLibrary( b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, panto_mod: *std.Build.Module, ) *std.Build.Step.Compile { const linkage = b.option(std.builtin.LinkMode, "linkage", "C library linkage: dynamic (default) or static") orelse .dynamic; const lib = b.addLibrary(.{ .name = "panto", .root_module = cModule(b, target, optimize, panto_mod), .linkage = linkage, }); if (linkage == .dynamic) { lib.rdynamic = true; } else { lib.bundle_compiler_rt = true; } return lib; } fn cModule( b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, panto_mod: *std.Build.Module, ) *std.Build.Module { const mod = b.createModule(.{ .root_source_file = b.path("libpanto-c/src/lib.zig"), .target = target, .optimize = optimize, .link_libc = true, }); mod.addImport("panto", panto_mod); return mod; } fn addImageCDeps(b: *std.Build, mod: *std.Build.Module) void { mod.addIncludePath(b.path("src/cdeps")); mod.addCSourceFile(.{ .file = b.path("src/cdeps/image_impl.c"), .flags = &.{ "-std=gnu99", "-O2", "-fno-sanitize=undefined" }, }); } fn allowUndefinedHostSymbols( lib: *std.Build.Step.Compile, target: std.Build.ResolvedTarget, ) void { switch (target.result.os.tag) { .macos => { lib.linker_allow_shlib_undefined = true; lib.root_module.addCMacro("LUA_USE_MACOSX", ""); }, .linux => lib.root_module.addCMacro("LUA_USE_LINUX", ""), .freebsd, .netbsd, .openbsd => lib.root_module.addCMacro("LUA_USE_POSIX", ""), else => {}, } } const lua_files = [_][]const u8{ "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", "lauxlib.c", "lbaselib.c", "lcorolib.c", "ldblib.c", "liolib.c", "lmathlib.c", "loadlib.c", "loslib.c", "lstrlib.c", "ltablib.c", "lutf8lib.c", "linit.c", }; fn addLuaForTests(mod: *std.Build.Module, lua_src: *std.Build.Dependency) void { const cflags = [_][]const u8{ "-std=gnu99", "-Wall", "-Wextra", "-Wno-unused-parameter", }; mod.addCSourceFiles(.{ .root = lua_src.path("src"), .files = &lua_files, .flags = &cflags, }); switch (mod.resolved_target.?.result.os.tag) { .macos => mod.addCMacro("LUA_USE_MACOSX", ""), .linux => mod.addCMacro("LUA_USE_LINUX", ""), .freebsd, .netbsd, .openbsd => mod.addCMacro("LUA_USE_POSIX", ""), else => {}, } }