neovim

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

gen_steps.zig (9504B)


      1 const std = @import("std");
      2 const LazyPath = std.Build.LazyPath;
      3 
      4 pub const SourceItem = struct { name: []u8, api_export: bool };
      5 
      6 pub fn nvim_gen_sources(
      7    b: *std.Build,
      8    nlua0: *std.Build.Step.Compile,
      9    nvim_sources: *std.ArrayList(SourceItem),
     10    nvim_headers: *std.ArrayList([]u8),
     11    api_headers: *std.ArrayList(LazyPath),
     12    versiondef_git: LazyPath,
     13    version_lua: LazyPath,
     14 ) !struct { *std.Build.Step.WriteFile, LazyPath } {
     15    const gen_headers = b.addWriteFiles();
     16 
     17    for (nvim_sources.items) |s| {
     18        const api_export = if (s.api_export) api_headers else null;
     19        const input_file = b.path(b.fmt("src/nvim/{s}", .{s.name}));
     20        _ = try generate_header_for(b, s.name, input_file, api_export, nlua0, gen_headers, false);
     21    }
     22 
     23    for (nvim_headers.items) |s| {
     24        const input_file = b.path(b.fmt("src/nvim/{s}", .{s}));
     25        _ = try generate_header_for(b, s, input_file, null, nlua0, gen_headers, true);
     26    }
     27 
     28    {
     29        const gen_step = b.addRunArtifact(nlua0);
     30        gen_step.addFileArg(b.path("src/gen/gen_ex_cmds.lua"));
     31        _ = gen_header(b, gen_step, "ex_cmds_enum.generated.h", gen_headers);
     32        _ = gen_header(b, gen_step, "ex_cmds_defs.generated.h", gen_headers);
     33        gen_step.addFileArg(b.path("src/nvim/ex_cmds.lua"));
     34    }
     35 
     36    {
     37        const gen_step = b.addRunArtifact(nlua0);
     38        gen_step.addFileArg(b.path("src/gen/gen_options.lua"));
     39        _ = gen_header(b, gen_step, "options.generated.h", gen_headers);
     40        _ = gen_header(b, gen_step, "options_enum.generated.h", gen_headers);
     41        _ = gen_header(b, gen_step, "options_map.generated.h", gen_headers);
     42        _ = gen_header(b, gen_step, "option_vars.generated.h", gen_headers);
     43        gen_step.addFileArg(b.path("src/nvim/options.lua"));
     44 
     45        const test_gen_step = b.step("wipopt", "debug one nlua0 (options)");
     46        test_gen_step.dependOn(&gen_step.step);
     47    }
     48 
     49    {
     50        const gen_step = b.addRunArtifact(nlua0);
     51        gen_step.addFileArg(b.path("src/gen/gen_events.lua"));
     52        _ = gen_header(b, gen_step, "auevents_enum.generated.h", gen_headers);
     53        _ = gen_header(b, gen_step, "auevents_name_map.generated.h", gen_headers);
     54        gen_step.addFileArg(b.path("src/nvim/auevents.lua"));
     55    }
     56 
     57    {
     58        const gen_step = b.addRunArtifact(nlua0);
     59        gen_step.addFileArg(b.path("src/gen/gen_keycodes.lua"));
     60        _ = gen_header(b, gen_step, "keycode_names.generated.h", gen_headers);
     61        gen_step.addFileArg(b.path("src/nvim/keycodes.lua"));
     62    }
     63 
     64    {
     65        const gen_step = b.addRunArtifact(nlua0);
     66        gen_step.addFileArg(b.path("src/gen/gen_char_blob.lua"));
     67        // TODO(bfredl): LUAC_PRG is missing. tricky with cross-compiling..
     68        // gen_step.addArg("-c");
     69        _ = gen_header(b, gen_step, "lua/vim_module.generated.h", gen_headers);
     70        // NB: vim._init_packages and vim.inspect must be be first and second ones
     71        // respectively, otherwise --luamod-dev won't work properly.
     72        const names = [_][]const u8{
     73            "_init_packages",
     74            "inspect",
     75            "filetype",
     76            "fs",
     77            "F",
     78            "keymap",
     79            "loader",
     80            "text",
     81        };
     82        for (names) |n| {
     83            gen_step.addFileArg(b.path(b.fmt("runtime/lua/vim/{s}.lua", .{n})));
     84            gen_step.addArg(b.fmt("vim.{s}", .{n}));
     85        }
     86 
     87        // Dynamically add all Lua _core/ modules (like CMakeLists.txt does)
     88        if (b.build_root.handle.openDir("runtime/lua/vim/_core", .{ .iterate = true })) |core_dir_handle| {
     89            var core_dir = core_dir_handle;
     90            defer core_dir.close();
     91 
     92            var iter = core_dir.iterate();
     93            var core_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 0);
     94            defer core_files.deinit(b.allocator);
     95 
     96            while (try iter.next()) |entry| {
     97                if (entry.kind == .file and std.mem.endsWith(u8, entry.name, ".lua")) {
     98                    const module_name = try b.allocator.dupe(u8, entry.name[0 .. entry.name.len - 4]);
     99                    try core_files.append(b.allocator, module_name);
    100                }
    101            }
    102 
    103            std.mem.sort([]const u8, core_files.items, {}, struct {
    104                fn lessThan(_: void, a: []const u8, c: []const u8) bool {
    105                    return std.mem.lessThan(u8, a, c);
    106                }
    107            }.lessThan);
    108 
    109            for (core_files.items) |n| {
    110                gen_step.addFileArg(b.path(b.fmt("runtime/lua/vim/_core/{s}.lua", .{n})));
    111                gen_step.addArg(b.fmt("vim._core.{s}", .{n}));
    112            }
    113        } else |err| {
    114            std.debug.print("Warning: Could not open _core directory: {}\n", .{err});
    115        }
    116    }
    117 
    118    const ui_metadata = ui_step: {
    119        const gen_step = b.addRunArtifact(nlua0);
    120        gen_step.addFileArg(b.path("src/gen/gen_api_ui_events.lua"));
    121        gen_step.addFileArg(b.path("src/nvim/api/ui_events.in.h"));
    122        _ = try gen_header_with_header(b, gen_step, "ui_events_call.generated.h", nlua0, gen_headers);
    123        _ = try gen_header_with_header(b, gen_step, "ui_events_remote.generated.h", nlua0, gen_headers);
    124        const ui_metadata = gen_step.addOutputFileArg("ui_metadata.mpack");
    125        _ = try gen_header_with_header(b, gen_step, "ui_events_client.generated.h", nlua0, gen_headers);
    126        break :ui_step ui_metadata;
    127    };
    128 
    129    const eval_funcs_metadata, const exported_funcs_metadata = dispatch_step: {
    130        const gen_step = b.addRunArtifact(nlua0);
    131        gen_step.addFileArg(b.path("src/gen/gen_api_dispatch.lua"));
    132        _ = try gen_header_with_header(b, gen_step, "api/private/dispatch_wrappers.generated.h", nlua0, gen_headers);
    133        const exported_funcs_metadata = gen_step.addOutputFileArg("exported_funcs_metadata.mpack");
    134        const eval_funcs_metadata = gen_step.addOutputFileArg("eval_funcs_metadata.mpack");
    135        _ = gen_header(b, gen_step, "lua_api_c_bindings.generated.h", gen_headers);
    136        _ = gen_header(b, gen_step, "keysets_defs.generated.h", gen_headers);
    137        gen_step.addFileArg(b.path("src/nvim/api/dispatch_deprecated.lua"));
    138        // now follows all .h files with exported functions
    139        for (api_headers.items) |h| {
    140            gen_step.addFileArg(h);
    141        }
    142 
    143        break :dispatch_step .{ eval_funcs_metadata, exported_funcs_metadata };
    144    };
    145 
    146    {
    147        const gen_step = b.addRunArtifact(nlua0);
    148        gen_step.addFileArg(b.path("src/gen/gen_api_metadata.lua"));
    149        gen_step.addFileArg(exported_funcs_metadata);
    150        gen_step.addFileArg(ui_metadata);
    151        gen_step.addFileArg(b.path("src/nvim/api/ui.h"));
    152        gen_step.addFileArg(versiondef_git);
    153        gen_step.addFileArg(version_lua);
    154        gen_step.addFileArg(b.path("src/gen/dump_bin_array.lua"));
    155        _ = gen_header(b, gen_step, "api/private/api_metadata.generated.h", gen_headers);
    156    }
    157 
    158    const funcs_data = eval_step: {
    159        const gen_step = b.addRunArtifact(nlua0);
    160        gen_step.addFileArg(b.path("src/gen/gen_eval.lua"));
    161        _ = gen_header(b, gen_step, "funcs.generated.h", gen_headers);
    162        gen_step.addFileArg(eval_funcs_metadata);
    163        const funcs_data = gen_step.addOutputFileArg("funcs_data.mpack");
    164        gen_step.addFileArg(b.path("src/nvim/eval.lua"));
    165        break :eval_step funcs_data;
    166    };
    167 
    168    return .{ gen_headers, funcs_data };
    169 }
    170 
    171 fn gen_header(
    172    b: *std.Build,
    173    gen_step: *std.Build.Step.Run,
    174    name: []const u8,
    175    gen_headers: *std.Build.Step.WriteFile,
    176 ) std.Build.LazyPath {
    177    _ = b;
    178    const header = gen_step.addOutputFileArg(name);
    179    _ = gen_headers.addCopyFile(header, name);
    180    return header;
    181 }
    182 
    183 fn gen_header_with_header(
    184    b: *std.Build,
    185    gen_step: *std.Build.Step.Run,
    186    name: []const u8,
    187    nlua0: *std.Build.Step.Compile,
    188    gen_headers: *std.Build.Step.WriteFile,
    189 ) !std.Build.LazyPath {
    190    if (name.len < 12 or !std.mem.eql(u8, ".generated.h", name[name.len - 12 ..])) return error.InvalidBaseName;
    191    const h = gen_header(b, gen_step, name, gen_headers);
    192    _ = try generate_header_for(b, b.fmt("{s}.h", .{name[0 .. name.len - 12]}), h, null, nlua0, gen_headers, false);
    193    return h;
    194 }
    195 
    196 pub const PreprocessorOptions = struct {
    197    include_dirs: []const LazyPath = &.{},
    198    c_macros: []const []const u8 = &.{},
    199    target: ?std.Build.ResolvedTarget = null,
    200 };
    201 
    202 fn generate_header_for(
    203    b: *std.Build,
    204    name: []const u8,
    205    input_file: LazyPath,
    206    api_export: ?*std.ArrayList(LazyPath),
    207    nlua0: *std.Build.Step.Compile,
    208    gen_headers: *std.Build.Step.WriteFile,
    209    nvim_header: bool,
    210 ) !*std.Build.Step.Run {
    211    if (name.len < 2 or !(std.mem.eql(u8, ".c", name[name.len - 2 ..]) or std.mem.eql(u8, ".h", name[name.len - 2 ..]))) return error.InvalidBaseName;
    212    const basename = name[0 .. name.len - 2];
    213    const run_step = b.addRunArtifact(nlua0);
    214    run_step.addFileArg(b.path("src/gen/gen_declarations.lua"));
    215    run_step.addFileArg(input_file);
    216    const gen_name = b.fmt("{s}.{s}.generated.h", .{ basename, if (nvim_header) "h.inline" else "c" });
    217    _ = gen_header(b, run_step, gen_name, gen_headers);
    218    if (nvim_header) {
    219        run_step.addArg("SKIP");
    220    } else {
    221        const h_file = gen_header(b, run_step, b.fmt("{s}.h.generated.h", .{basename}), gen_headers);
    222        if (api_export) |api_files| {
    223            try api_files.append(b.allocator, h_file);
    224        }
    225    }
    226 
    227    run_step.addArg(gen_name);
    228    return run_step;
    229 }