neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

build_lua.zig (6668B)


      1 const std = @import("std");
      2 const build = @import("../build.zig");
      3 const LazyPath = std.Build.LazyPath;
      4 
      5 pub fn build_nlua0(
      6    b: *std.Build,
      7    target: std.Build.ResolvedTarget,
      8    optimize: std.builtin.OptimizeMode,
      9    use_luajit: bool,
     10    ziglua: *std.Build.Dependency,
     11    lpeg: ?*std.Build.Dependency,
     12    libluv: ?*std.Build.Step.Compile,
     13    system_integration_options: build.SystemIntegrationOptions,
     14 ) !*std.Build.Step.Compile {
     15    const options = b.addOptions();
     16    options.addOption(bool, "use_luajit", use_luajit);
     17 
     18    const nlua0_exe = b.addExecutable(.{
     19        .name = "nlua0",
     20        .root_module = b.createModule(.{
     21            .root_source_file = b.path("src/nlua0.zig"),
     22            .target = target,
     23            .optimize = optimize,
     24            .link_libc = true,
     25        }),
     26    });
     27    const nlua0_mod = nlua0_exe.root_module;
     28 
     29    const exe_unit_tests = b.addTest(.{
     30        .root_module = b.createModule(.{
     31            .root_source_file = b.path("src/nlua0.zig"),
     32            .target = target,
     33            .optimize = optimize,
     34            .link_libc = true,
     35        }),
     36    });
     37 
     38    const embedded_data = b.addModule("embedded_data", .{
     39        .root_source_file = b.path("runtime/embedded_data.zig"),
     40    });
     41 
     42    for ([2]*std.Build.Module{ nlua0_mod, exe_unit_tests.root_module }) |mod| {
     43        mod.addImport("ziglua", ziglua.module("zlua"));
     44        mod.addImport("embedded_data", embedded_data);
     45        // addImport already links by itself. but we need headers as well..
     46        if (system_integration_options.lua) {
     47            const system_lua_lib = if (use_luajit) "luajit" else "lua5.1";
     48            mod.linkSystemLibrary(system_lua_lib, .{});
     49        } else {
     50            mod.linkLibrary(ziglua.artifact("lua"));
     51        }
     52        if (libluv) |luv| {
     53            mod.linkLibrary(luv);
     54        } else {
     55            mod.linkSystemLibrary("luv", .{});
     56        }
     57 
     58        mod.addOptions("options", options);
     59 
     60        mod.addIncludePath(b.path("src"));
     61        mod.addIncludePath(b.path("src/includes_fixmelater"));
     62        try add_lua_modules(b, target.result, mod, lpeg, use_luajit, true, system_integration_options);
     63    }
     64 
     65    // for debugging the nlua0 environment
     66    // like this: `zig build nlua0 -- script.lua {args}`
     67    const run_cmd = b.addRunArtifact(nlua0_exe);
     68    if (b.args) |args| {
     69        run_cmd.addArgs(args);
     70    }
     71    const run_step = b.step("nlua0", "Run nlua0 build tool");
     72    run_step.dependOn(&run_cmd.step);
     73 
     74    b.installArtifact(nlua0_exe); // DEBUG
     75 
     76    const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
     77 
     78    const test_step = b.step("test_nlua0", "Run unit tests for nlua0");
     79    test_step.dependOn(&run_exe_unit_tests.step);
     80 
     81    return nlua0_exe;
     82 }
     83 
     84 pub fn add_lua_modules(
     85    b: *std.Build,
     86    target: std.Target,
     87    mod: *std.Build.Module,
     88    lpeg_dep: ?*std.Build.Dependency,
     89    use_luajit: bool,
     90    is_nlua0: bool,
     91    system_integration_options: build.SystemIntegrationOptions,
     92 ) !void {
     93    const flags = [_][]const u8{
     94        // Standard version used in Lua Makefile
     95        "-std=gnu99",
     96        if (is_nlua0) "-DNVIM_NLUA0" else "",
     97    };
     98 
     99    if (lpeg_dep) |lpeg| {
    100        mod.addIncludePath(lpeg.path(""));
    101    }
    102    mod.addCSourceFiles(.{
    103        .files = &.{
    104            "src/mpack/lmpack.c",
    105            "src/mpack/mpack_core.c",
    106            "src/mpack/object.c",
    107            "src/mpack/conv.c",
    108            "src/mpack/rpc.c",
    109        },
    110        .flags = &flags,
    111    });
    112    if (system_integration_options.lpeg) {
    113        if (try findLpeg(b, target)) |lpeg_lib| {
    114            mod.addLibraryPath(.{ .cwd_relative = std.fs.path.dirname(lpeg_lib).? });
    115            mod.addObjectFile(.{ .cwd_relative = lpeg_lib });
    116        }
    117    } else if (lpeg_dep) |lpeg| {
    118        mod.addCSourceFiles(.{
    119            .root = .{ .dependency = .{ .dependency = lpeg, .sub_path = "" } },
    120            .files = &.{
    121                "lpcap.c",
    122                "lpcode.c",
    123                "lpcset.c",
    124                "lpprint.c",
    125                "lptree.c",
    126                "lpvm.c",
    127            },
    128            .flags = &flags,
    129        });
    130    }
    131 
    132    if (!use_luajit) {
    133        mod.addCSourceFiles(.{
    134            .files = &.{
    135                "src/bit.c",
    136            },
    137            .flags = &flags,
    138        });
    139    }
    140 }
    141 
    142 pub fn build_libluv(
    143    b: *std.Build,
    144    target: std.Build.ResolvedTarget,
    145    optimize: std.builtin.OptimizeMode,
    146    lua: ?*std.Build.Step.Compile,
    147    libuv: *std.Build.Step.Compile,
    148    use_luajit: bool,
    149 ) !*std.Build.Step.Compile {
    150    const upstream = b.lazyDependency("luv", .{});
    151    const compat53 = b.lazyDependency("lua_compat53", .{});
    152    const lib = b.addLibrary(.{
    153        .name = "luv",
    154        .linkage = .static,
    155        .root_module = b.createModule(.{
    156            .target = target,
    157            .optimize = optimize,
    158        }),
    159    });
    160 
    161    if (lua) |lua_lib| {
    162        lib.root_module.linkLibrary(lua_lib);
    163    } else {
    164        const system_lua_lib = if (use_luajit) "luajit" else "lua5.1";
    165        lib.root_module.linkSystemLibrary(system_lua_lib, .{});
    166    }
    167    lib.linkLibrary(libuv);
    168 
    169    if (upstream) |dep| {
    170        lib.addIncludePath(dep.path("src"));
    171        lib.installHeader(dep.path("src/luv.h"), "luv/luv.h");
    172        lib.addCSourceFiles(.{ .root = dep.path("src/"), .files = &.{
    173            "luv.c",
    174        } });
    175    }
    176    if (compat53) |dep| {
    177        lib.addIncludePath(dep.path("c-api"));
    178        lib.addCSourceFiles(.{ .root = dep.path("c-api"), .files = &.{
    179            "compat-5.3.c",
    180        } });
    181    }
    182 
    183    return lib;
    184 }
    185 
    186 fn findLpeg(b: *std.Build, target: std.Target) !?[]const u8 {
    187    const filenames = [_][]const u8{
    188        "lpeg_a",
    189        "lpeg",
    190        "liblpeg_a",
    191        "lpeg.so",
    192        b.fmt("lpeg{s}", .{target.dynamicLibSuffix()}),
    193    };
    194    var code: u8 = 0;
    195    const dirs_stdout = std.mem.trimEnd(u8, try b.runAllowFail(&[_][]const u8{
    196        "pkg-config",
    197        "--variable=pc_system_libdirs",
    198        "--keep-system-cflags",
    199        "pkg-config",
    200    }, &code, .Ignore), "\r\n");
    201    var paths: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 0);
    202    var path_it = std.mem.tokenizeAny(u8, dirs_stdout, " ,");
    203    while (path_it.next()) |dir| {
    204        try paths.append(b.allocator, dir);
    205        try paths.append(b.allocator, b.fmt("{s}/lua/5.1", .{dir}));
    206    }
    207    for (paths.items) |path| {
    208        var dir = std.fs.openDirAbsolute(path, .{}) catch continue;
    209        defer dir.close();
    210        for (filenames) |filename| {
    211            dir.access(filename, .{}) catch continue;
    212            return b.fmt("{s}/{s}", .{ path, filename });
    213        }
    214    }
    215    return null;
    216 }