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 }