mirror of
https://github.com/neovim/neovim.git
synced 2026-02-22 02:11:33 +10:00
Problem: We want to encourage implementing core features in Lua instead of C, but it's clumsy because: - Core Lua code (built into `nvim` so it is available even if VIMRUNTIME is missing/invalid) requires manually updating CMakeLists.txt, or stuffing it into `_editor.lua`. - Core Lua modules are not organized similar to C modules, `_editor.lua` is getting too big. Solution: - Introduce `_core/` where core Lua code can live. All Lua modules added there will automatically be included as bytecode in the `nvim` binary. - Move these core modules into `_core/*`: ``` _defaults.lua _editor.lua _options.lua _system.lua shared.lua ``` TODO: - Move `_extui/ => _core/ui2/`
230 lines
9.3 KiB
Zig
230 lines
9.3 KiB
Zig
const std = @import("std");
|
|
const LazyPath = std.Build.LazyPath;
|
|
|
|
pub const SourceItem = struct { name: []u8, api_export: bool };
|
|
|
|
pub fn nvim_gen_sources(
|
|
b: *std.Build,
|
|
nlua0: *std.Build.Step.Compile,
|
|
nvim_sources: *std.ArrayList(SourceItem),
|
|
nvim_headers: *std.ArrayList([]u8),
|
|
api_headers: *std.ArrayList(LazyPath),
|
|
versiondef_git: LazyPath,
|
|
version_lua: LazyPath,
|
|
) !struct { *std.Build.Step.WriteFile, LazyPath } {
|
|
const gen_headers = b.addWriteFiles();
|
|
|
|
for (nvim_sources.items) |s| {
|
|
const api_export = if (s.api_export) api_headers else null;
|
|
const input_file = b.path(b.fmt("src/nvim/{s}", .{s.name}));
|
|
_ = try generate_header_for(b, s.name, input_file, api_export, nlua0, gen_headers, false);
|
|
}
|
|
|
|
for (nvim_headers.items) |s| {
|
|
const input_file = b.path(b.fmt("src/nvim/{s}", .{s}));
|
|
_ = try generate_header_for(b, s, input_file, null, nlua0, gen_headers, true);
|
|
}
|
|
|
|
{
|
|
const gen_step = b.addRunArtifact(nlua0);
|
|
gen_step.addFileArg(b.path("src/gen/gen_ex_cmds.lua"));
|
|
_ = gen_header(b, gen_step, "ex_cmds_enum.generated.h", gen_headers);
|
|
_ = gen_header(b, gen_step, "ex_cmds_defs.generated.h", gen_headers);
|
|
gen_step.addFileArg(b.path("src/nvim/ex_cmds.lua"));
|
|
}
|
|
|
|
{
|
|
const gen_step = b.addRunArtifact(nlua0);
|
|
gen_step.addFileArg(b.path("src/gen/gen_options.lua"));
|
|
_ = gen_header(b, gen_step, "options.generated.h", gen_headers);
|
|
_ = gen_header(b, gen_step, "options_enum.generated.h", gen_headers);
|
|
_ = gen_header(b, gen_step, "options_map.generated.h", gen_headers);
|
|
_ = gen_header(b, gen_step, "option_vars.generated.h", gen_headers);
|
|
gen_step.addFileArg(b.path("src/nvim/options.lua"));
|
|
|
|
const test_gen_step = b.step("wipopt", "debug one nlua0 (options)");
|
|
test_gen_step.dependOn(&gen_step.step);
|
|
}
|
|
|
|
{
|
|
const gen_step = b.addRunArtifact(nlua0);
|
|
gen_step.addFileArg(b.path("src/gen/gen_events.lua"));
|
|
_ = gen_header(b, gen_step, "auevents_enum.generated.h", gen_headers);
|
|
_ = gen_header(b, gen_step, "auevents_name_map.generated.h", gen_headers);
|
|
gen_step.addFileArg(b.path("src/nvim/auevents.lua"));
|
|
}
|
|
|
|
{
|
|
const gen_step = b.addRunArtifact(nlua0);
|
|
gen_step.addFileArg(b.path("src/gen/gen_keycodes.lua"));
|
|
_ = gen_header(b, gen_step, "keycode_names.generated.h", gen_headers);
|
|
gen_step.addFileArg(b.path("src/nvim/keycodes.lua"));
|
|
}
|
|
|
|
{
|
|
const gen_step = b.addRunArtifact(nlua0);
|
|
gen_step.addFileArg(b.path("src/gen/gen_char_blob.lua"));
|
|
// TODO(bfredl): LUAC_PRG is missing. tricky with cross-compiling..
|
|
// gen_step.addArg("-c");
|
|
_ = gen_header(b, gen_step, "lua/vim_module.generated.h", gen_headers);
|
|
// NB: vim._init_packages and vim.inspect must be be first and second ones
|
|
// respectively, otherwise --luamod-dev won't work properly.
|
|
const names = [_][]const u8{
|
|
"_init_packages",
|
|
"inspect",
|
|
"filetype",
|
|
"fs",
|
|
"F",
|
|
"keymap",
|
|
"loader",
|
|
"text",
|
|
};
|
|
for (names) |n| {
|
|
gen_step.addFileArg(b.path(b.fmt("runtime/lua/vim/{s}.lua", .{n})));
|
|
gen_step.addArg(b.fmt("vim.{s}", .{n}));
|
|
}
|
|
|
|
// Dynamically add all Lua _core/ modules (like CMakeLists.txt does)
|
|
if (b.build_root.handle.openDir("runtime/lua/vim/_core", .{ .iterate = true })) |core_dir_handle| {
|
|
var core_dir = core_dir_handle;
|
|
defer core_dir.close();
|
|
|
|
var iter = core_dir.iterate();
|
|
var core_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 0);
|
|
defer core_files.deinit(b.allocator);
|
|
|
|
while (try iter.next()) |entry| {
|
|
if (entry.kind == .file and std.mem.endsWith(u8, entry.name, ".lua")) {
|
|
const module_name = try b.allocator.dupe(u8, entry.name[0 .. entry.name.len - 4]);
|
|
try core_files.append(b.allocator, module_name);
|
|
}
|
|
}
|
|
|
|
std.mem.sort([]const u8, core_files.items, {}, struct {
|
|
fn lessThan(_: void, a: []const u8, c: []const u8) bool {
|
|
return std.mem.lessThan(u8, a, c);
|
|
}
|
|
}.lessThan);
|
|
|
|
for (core_files.items) |n| {
|
|
gen_step.addFileArg(b.path(b.fmt("runtime/lua/vim/_core/{s}.lua", .{n})));
|
|
gen_step.addArg(b.fmt("vim._core.{s}", .{n}));
|
|
}
|
|
} else |err| {
|
|
std.debug.print("Warning: Could not open _core directory: {}\n", .{err});
|
|
}
|
|
}
|
|
|
|
const ui_metadata = ui_step: {
|
|
const gen_step = b.addRunArtifact(nlua0);
|
|
gen_step.addFileArg(b.path("src/gen/gen_api_ui_events.lua"));
|
|
gen_step.addFileArg(b.path("src/nvim/api/ui_events.in.h"));
|
|
_ = try gen_header_with_header(b, gen_step, "ui_events_call.generated.h", nlua0, gen_headers);
|
|
_ = try gen_header_with_header(b, gen_step, "ui_events_remote.generated.h", nlua0, gen_headers);
|
|
const ui_metadata = gen_step.addOutputFileArg("ui_metadata.mpack");
|
|
_ = try gen_header_with_header(b, gen_step, "ui_events_client.generated.h", nlua0, gen_headers);
|
|
break :ui_step ui_metadata;
|
|
};
|
|
|
|
const eval_funcs_metadata, const exported_funcs_metadata = dispatch_step: {
|
|
const gen_step = b.addRunArtifact(nlua0);
|
|
gen_step.addFileArg(b.path("src/gen/gen_api_dispatch.lua"));
|
|
_ = try gen_header_with_header(b, gen_step, "api/private/dispatch_wrappers.generated.h", nlua0, gen_headers);
|
|
const exported_funcs_metadata = gen_step.addOutputFileArg("exported_funcs_metadata.mpack");
|
|
const eval_funcs_metadata = gen_step.addOutputFileArg("eval_funcs_metadata.mpack");
|
|
_ = gen_header(b, gen_step, "lua_api_c_bindings.generated.h", gen_headers);
|
|
_ = gen_header(b, gen_step, "keysets_defs.generated.h", gen_headers);
|
|
gen_step.addFileArg(b.path("src/nvim/api/dispatch_deprecated.lua"));
|
|
// now follows all .h files with exported functions
|
|
for (api_headers.items) |h| {
|
|
gen_step.addFileArg(h);
|
|
}
|
|
|
|
break :dispatch_step .{ eval_funcs_metadata, exported_funcs_metadata };
|
|
};
|
|
|
|
{
|
|
const gen_step = b.addRunArtifact(nlua0);
|
|
gen_step.addFileArg(b.path("src/gen/gen_api_metadata.lua"));
|
|
gen_step.addFileArg(exported_funcs_metadata);
|
|
gen_step.addFileArg(ui_metadata);
|
|
gen_step.addFileArg(b.path("src/nvim/api/ui.h"));
|
|
gen_step.addFileArg(versiondef_git);
|
|
gen_step.addFileArg(version_lua);
|
|
gen_step.addFileArg(b.path("src/gen/dump_bin_array.lua"));
|
|
_ = gen_header(b, gen_step, "api/private/api_metadata.generated.h", gen_headers);
|
|
}
|
|
|
|
const funcs_data = eval_step: {
|
|
const gen_step = b.addRunArtifact(nlua0);
|
|
gen_step.addFileArg(b.path("src/gen/gen_eval.lua"));
|
|
_ = gen_header(b, gen_step, "funcs.generated.h", gen_headers);
|
|
gen_step.addFileArg(eval_funcs_metadata);
|
|
const funcs_data = gen_step.addOutputFileArg("funcs_data.mpack");
|
|
gen_step.addFileArg(b.path("src/nvim/eval.lua"));
|
|
break :eval_step funcs_data;
|
|
};
|
|
|
|
return .{ gen_headers, funcs_data };
|
|
}
|
|
|
|
fn gen_header(
|
|
b: *std.Build,
|
|
gen_step: *std.Build.Step.Run,
|
|
name: []const u8,
|
|
gen_headers: *std.Build.Step.WriteFile,
|
|
) std.Build.LazyPath {
|
|
_ = b;
|
|
const header = gen_step.addOutputFileArg(name);
|
|
_ = gen_headers.addCopyFile(header, name);
|
|
return header;
|
|
}
|
|
|
|
fn gen_header_with_header(
|
|
b: *std.Build,
|
|
gen_step: *std.Build.Step.Run,
|
|
name: []const u8,
|
|
nlua0: *std.Build.Step.Compile,
|
|
gen_headers: *std.Build.Step.WriteFile,
|
|
) !std.Build.LazyPath {
|
|
if (name.len < 12 or !std.mem.eql(u8, ".generated.h", name[name.len - 12 ..])) return error.InvalidBaseName;
|
|
const h = gen_header(b, gen_step, name, gen_headers);
|
|
_ = try generate_header_for(b, b.fmt("{s}.h", .{name[0 .. name.len - 12]}), h, null, nlua0, gen_headers, false);
|
|
return h;
|
|
}
|
|
|
|
pub const PreprocessorOptions = struct {
|
|
include_dirs: []const LazyPath = &.{},
|
|
c_macros: []const []const u8 = &.{},
|
|
target: ?std.Build.ResolvedTarget = null,
|
|
};
|
|
|
|
fn generate_header_for(
|
|
b: *std.Build,
|
|
name: []const u8,
|
|
input_file: LazyPath,
|
|
api_export: ?*std.ArrayList(LazyPath),
|
|
nlua0: *std.Build.Step.Compile,
|
|
gen_headers: *std.Build.Step.WriteFile,
|
|
nvim_header: bool,
|
|
) !*std.Build.Step.Run {
|
|
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;
|
|
const basename = name[0 .. name.len - 2];
|
|
const run_step = b.addRunArtifact(nlua0);
|
|
run_step.addFileArg(b.path("src/gen/gen_declarations.lua"));
|
|
run_step.addFileArg(input_file);
|
|
const gen_name = b.fmt("{s}.{s}.generated.h", .{ basename, if (nvim_header) "h.inline" else "c" });
|
|
_ = gen_header(b, run_step, gen_name, gen_headers);
|
|
if (nvim_header) {
|
|
run_step.addArg("SKIP");
|
|
} else {
|
|
const h_file = gen_header(b, run_step, b.fmt("{s}.h.generated.h", .{basename}), gen_headers);
|
|
if (api_export) |api_files| {
|
|
try api_files.append(b.allocator, h_file);
|
|
}
|
|
}
|
|
|
|
run_step.addArg(gen_name);
|
|
return run_step;
|
|
}
|