commit 6d9031390cfc06300d60f96f63ba2bd95b4c7b3b
parent dddc359213be522026d60ffd89867a0f52f19256
Author: Chinmay Dalal <dalal.chinmay.0101@gmail.com>
Date: Sat, 20 Dec 2025 00:11:05 -0500
feat(build.zig): add option to use system dependencies
Problem:
build.zig always downloads dependencies and statically links them,
which is frowned upon by distro packagers.
Solution:
Add option to use system libraries.
Diffstat:
7 files changed, 331 insertions(+), 120 deletions(-)
diff --git a/build.zig b/build.zig
@@ -1,5 +1,6 @@
const std = @import("std");
const LazyPath = std.Build.LazyPath;
+const Compile = std.Build.Step.Compile;
const build_lua = @import("src/build_lua.zig");
const gen = @import("src/gen/gen_steps.zig");
const runtime = @import("runtime/gen_runtime.zig");
@@ -16,6 +17,15 @@ const version = struct {
const api_prerelease = true;
};
+pub const SystemIntegrationOptions = packed struct {
+ lpeg: bool,
+ lua: bool,
+ tree_sitter: bool,
+ unibilium: bool,
+ utf8proc: bool,
+ uv: bool,
+};
+
// TODO(bfredl): this is for an upstream issue
pub fn lazyArtifact(d: *std.Build.Dependency, name: []const u8) ?*std.Build.Step.Compile {
var found: ?*std.Build.Step.Compile = null;
@@ -54,51 +64,68 @@ pub fn build(b: *std.Build) !void {
const arch = t.cpu.arch;
const default_luajit = (is_linux and arch == .x86_64) or (is_darwin and arch == .aarch64);
const use_luajit = b.option(bool, "luajit", "use luajit") orelse default_luajit;
+ const lualib_name = if (use_luajit) "luajit" else "lua5.1";
const host_use_luajit = if (cross_compiling) false else use_luajit;
const E = enum { luajit, lua51 };
+ const system_integration_options = SystemIntegrationOptions{
+ .lpeg = b.systemIntegrationOption("lpeg", .{}),
+ .lua = b.systemIntegrationOption("lua", .{}),
+ .tree_sitter = b.systemIntegrationOption("tree-sitter", .{}),
+ .unibilium = b.systemIntegrationOption("unibilium", .{}),
+ .utf8proc = b.systemIntegrationOption("utf8proc", .{}),
+ .uv = b.systemIntegrationOption("uv", .{}),
+ };
+
const ziglua = b.dependency("zlua", .{
.target = target,
.optimize = optimize_lua,
.lang = if (use_luajit) E.luajit else E.lua51,
.shared = false,
+ .system_lua = system_integration_options.lua,
});
-
const ziglua_host = if (cross_compiling) b.dependency("zlua", .{
.target = target_host,
.optimize = .ReleaseSmall,
.lang = if (host_use_luajit) E.luajit else E.lua51,
+ .system_lua = system_integration_options.lua,
.shared = false,
}) else ziglua;
-
- const lpeg = b.dependency("lpeg", .{});
-
- const iconv = if (is_windows or is_darwin) b.lazyDependency("libiconv", .{ .target = target, .optimize = optimize }) else null;
-
- // this is currently not necessary, as ziglua currently doesn't use lazy dependencies
- // to circumvent ziglua.artifact() failing in a bad way.
- const lua = lazyArtifact(ziglua, "lua") orelse return;
- if (cross_compiling) {
- _ = lazyArtifact(ziglua_host, "lua") orelse return;
+ var lua: ?*Compile = null;
+ var libuv: ?*Compile = null;
+ var libluv: ?*Compile = null;
+ var libluv_host: ?*Compile = null;
+ if (!system_integration_options.lua) {
+ // this is currently not necessary, as ziglua currently doesn't use lazy dependencies
+ // to circumvent ziglua.artifact() failing in a bad way.
+ lua = lazyArtifact(ziglua, "lua") orelse return;
+ if (cross_compiling) {
+ _ = lazyArtifact(ziglua_host, "lua") orelse return;
+ }
+ }
+ if (!system_integration_options.uv) {
+ if (b.lazyDependency("libuv", .{ .target = target, .optimize = optimize })) |dep| {
+ libuv = dep.artifact("uv");
+ libluv = try build_lua.build_libluv(b, target, optimize, lua, libuv.?, use_luajit);
+
+ libluv_host = if (cross_compiling) libluv_host: {
+ const libuv_dep_host = b.lazyDependency("libuv", .{ .target = target_host, .optimize = optimize_host });
+ const libuv_host = libuv_dep_host.?.artifact("uv");
+ break :libluv_host try build_lua.build_libluv(b, target_host, optimize_host, ziglua_host.artifact("lua"), libuv_host, host_use_luajit);
+ } else libluv;
+ }
}
- // const lua = ziglua.artifact("lua");
- const libuv_dep = b.dependency("libuv", .{ .target = target, .optimize = optimize });
- const libuv = libuv_dep.artifact("uv");
- const libluv = try build_lua.build_libluv(b, target, optimize, lua, libuv);
+ const lpeg = if (system_integration_options.lpeg) null else b.lazyDependency("lpeg", .{});
- const libluv_host = if (cross_compiling) libluv_host: {
- const libuv_dep_host = b.dependency("libuv", .{ .target = target_host, .optimize = optimize_host });
- const libuv_host = libuv_dep_host.artifact("uv");
- break :libluv_host try build_lua.build_libluv(b, target_host, optimize_host, ziglua_host.artifact("lua"), libuv_host);
- } else libluv;
+ const iconv = if (is_windows or is_darwin) b.lazyDependency("libiconv", .{ .target = target, .optimize = optimize }) else null;
- const utf8proc = b.dependency("utf8proc", .{ .target = target, .optimize = optimize });
- const unibilium = if (use_unibilium) b.lazyDependency("unibilium", .{ .target = target, .optimize = optimize }) else null;
+ const utf8proc = if (system_integration_options.utf8proc) null else b.lazyDependency("utf8proc", .{ .target = target, .optimize = optimize });
+ const unibilium = if (use_unibilium and !system_integration_options.unibilium) b.lazyDependency("unibilium", .{ .target = target, .optimize = optimize }) else null;
// TODO(bfredl): fix upstream bugs with UBSAN
- const treesitter = b.dependency("treesitter", .{ .target = target, .optimize = .ReleaseFast });
+ const treesitter = if (system_integration_options.tree_sitter) null else b.lazyDependency("treesitter", .{ .target = target, .optimize = .ReleaseFast });
- const nlua0 = build_lua.build_nlua0(b, target_host, optimize_host, host_use_luajit, ziglua_host, lpeg, libluv_host);
+ const nlua0 = try build_lua.build_nlua0(b, target_host, optimize_host, host_use_luajit, ziglua_host, lpeg, libluv_host, system_integration_options);
// usual caveat emptor: might need to force a rebuild if the only change is
// addition of new .c files, as those are not seen by any hash
@@ -228,6 +255,9 @@ pub fn build(b: *std.Build) !void {
.VTERM_TEST_FILE = "test/vterm_test_output", // TODO(bfredl): revisit when porting libvterm tests
});
+ const system_install_path = b.option([]const u8, "install-path", "Install path (for packagers)");
+ const install_path = system_install_path orelse b.install_path;
+ const lib_dir = if (system_install_path) |path| b.fmt("{s}/lib", .{path}) else b.lib_dir;
_ = gen_config.addCopyFile(sysconfig_step.getOutput(), "auto/config.h"); // run_preprocessor() workaronnd
_ = gen_config.add("auto/pathdef.h", b.fmt(
@@ -235,7 +265,7 @@ pub fn build(b: *std.Build) !void {
\\char *default_vimruntime_dir = "";
\\char *default_lib_dir = "{s}/nvim";
// b.lib_dir is typically b.install_path + "/lib" but may be overridden
- , .{ try replace_backslashes(b, b.install_path), try replace_backslashes(b, b.lib_dir) }));
+ , .{ try replace_backslashes(b, install_path), try replace_backslashes(b, lib_dir) }));
const opt_version_string = b.option([]const u8, "version-string", "Override Neovim version string. Default is to find out with git.");
const version_medium = if (opt_version_string) |version_string| version_string else v: {
@@ -282,17 +312,45 @@ pub fn build(b: *std.Build) !void {
// TODO(zig): using getEmittedIncludeTree() is ugly af. we want unittests
// to reuse the std.build.Module include_path thing
- const unittest_include_path = [_]LazyPath{
- b.path("src/"),
- gen_config.getDirectory(),
- lua.getEmittedIncludeTree(),
- libuv.getEmittedIncludeTree(),
- libluv.getEmittedIncludeTree(),
- utf8proc.artifact("utf8proc").getEmittedIncludeTree(),
- if (unibilium) |u| u.artifact("unibilium").getEmittedIncludeTree() else b.path("UNUSED_PATH/"), // :p
- treesitter.artifact("tree-sitter").getEmittedIncludeTree(),
- if (iconv) |dep| dep.artifact("iconv").getEmittedIncludeTree() else b.path("UNUSED_PATH/"),
- };
+ var unittest_include_path: std.ArrayList(LazyPath) = try .initCapacity(b.allocator, 2);
+ try unittest_include_path.append(b.allocator, b.path("src/"));
+ try unittest_include_path.append(b.allocator, gen_config.getDirectory());
+ if (system_integration_options.lua) {
+ try appendSystemIncludePath(b, &unittest_include_path, lualib_name);
+ } else if (lua) |compile| {
+ try unittest_include_path.append(b.allocator, compile.getEmittedIncludeTree());
+ }
+ if (system_integration_options.uv) {
+ try appendSystemIncludePath(b, &unittest_include_path, "libuv");
+ try appendSystemIncludePath(b, &unittest_include_path, "libluv");
+ } else {
+ if (libuv) |compile| {
+ try unittest_include_path.append(b.allocator, compile.getEmittedIncludeTree());
+ }
+ if (libluv) |compile| {
+ try unittest_include_path.append(b.allocator, compile.getEmittedIncludeTree());
+ }
+ }
+ if (system_integration_options.utf8proc) {
+ try appendSystemIncludePath(b, &unittest_include_path, "libutf8proc");
+ } else if (utf8proc) |dep| {
+ try unittest_include_path.append(b.allocator, dep.artifact("utf8proc").getEmittedIncludeTree());
+ }
+ if (use_unibilium) {
+ if (system_integration_options.unibilium) {
+ try appendSystemIncludePath(b, &unittest_include_path, "unibilium");
+ } else if (unibilium) |dep| {
+ try unittest_include_path.append(b.allocator, dep.artifact("unibilium").getEmittedIncludeTree());
+ }
+ }
+ if (system_integration_options.tree_sitter) {
+ try appendSystemIncludePath(b, &unittest_include_path, "tree-sitter");
+ } else if (treesitter) |dep| {
+ try unittest_include_path.append(b.allocator, dep.artifact("tree-sitter").getEmittedIncludeTree());
+ }
+ if (iconv) |dep| {
+ try unittest_include_path.append(b.allocator, dep.artifact("iconv").getEmittedIncludeTree());
+ }
const gen_headers, const funcs_data = try gen.nvim_gen_sources(b, nlua0, &nvim_sources, &nvim_headers, &api_headers, versiondef_git, version_lua);
@@ -309,24 +367,50 @@ pub fn build(b: *std.Build) !void {
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
+ .link_libc = true,
}),
});
nvim_exe.rdynamic = true; // -E
- nvim_exe.linkLibrary(lua);
- nvim_exe.linkLibrary(libuv);
- nvim_exe.linkLibrary(libluv);
+ if (system_integration_options.lua) {
+ nvim_exe.root_module.linkSystemLibrary(lualib_name, .{});
+ } else if (lua) |compile| {
+ nvim_exe.root_module.linkLibrary(compile);
+ }
+ if (system_integration_options.uv) {
+ nvim_exe.root_module.linkSystemLibrary("libuv", .{});
+ nvim_exe.root_module.linkSystemLibrary("libluv", .{});
+ } else {
+ if (libuv) |compile|
+ nvim_exe.root_module.linkLibrary(compile);
+ if (libluv) |compile|
+ nvim_exe.root_module.linkLibrary(compile);
+ }
if (iconv) |dep| nvim_exe.linkLibrary(dep.artifact("iconv"));
- nvim_exe.linkLibrary(utf8proc.artifact("utf8proc"));
- if (unibilium) |u| nvim_exe.linkLibrary(u.artifact("unibilium"));
- nvim_exe.linkLibrary(treesitter.artifact("tree-sitter"));
+ if (system_integration_options.utf8proc) {
+ nvim_exe.root_module.linkSystemLibrary("utf8proc", .{});
+ } else if (utf8proc) |dep| {
+ nvim_exe.root_module.linkLibrary(dep.artifact("utf8proc"));
+ }
+ if (use_unibilium) {
+ if (system_integration_options.unibilium) {
+ nvim_exe.root_module.linkSystemLibrary("unibilium", .{});
+ } else if (unibilium) |dep| {
+ nvim_exe.root_module.linkLibrary(dep.artifact("unibilium"));
+ }
+ }
+ if (system_integration_options.tree_sitter) {
+ nvim_exe.root_module.linkSystemLibrary("tree-sitter", .{});
+ } else if (treesitter) |dep| {
+ nvim_exe.root_module.linkLibrary(dep.artifact("tree-sitter"));
+ }
if (is_windows) {
nvim_exe.linkSystemLibrary("netapi32");
}
nvim_exe.addIncludePath(b.path("src"));
nvim_exe.addIncludePath(gen_config.getDirectory());
nvim_exe.addIncludePath(gen_headers.getDirectory());
- build_lua.add_lua_modules(nvim_exe.root_module, lpeg, use_luajit, false);
+ try build_lua.add_lua_modules(b, t, nvim_exe.root_module, lpeg, use_luajit, false, system_integration_options);
var unit_test_sources = try std.ArrayList([]u8).initCapacity(b.allocator, 10);
if (support_unittests) {
@@ -415,12 +499,12 @@ pub fn build(b: *std.Build) !void {
b.installDirectory(.{ .source_dir = b.path("runtime/"), .install_dir = .prefix, .install_subdir = "share/nvim/runtime/" });
b.installDirectory(.{ .source_dir = gen_runtime.getDirectory(), .install_dir = .prefix, .install_subdir = "share/nvim/runtime/" });
- test_deps.dependOn(test_fixture(b, "shell-test", null, target, optimize, &flags));
- test_deps.dependOn(test_fixture(b, "tty-test", libuv, target, optimize, &flags));
- test_deps.dependOn(test_fixture(b, "pwsh-test", null, target, optimize, &flags));
- test_deps.dependOn(test_fixture(b, "printargs-test", null, target, optimize, &flags));
- test_deps.dependOn(test_fixture(b, "printenv-test", null, target, optimize, &flags));
- test_deps.dependOn(test_fixture(b, "streams-test", libuv, target, optimize, &flags));
+ test_deps.dependOn(test_fixture(b, "shell-test", false, false, null, target, optimize, &flags));
+ test_deps.dependOn(test_fixture(b, "tty-test", true, system_integration_options.uv, libuv, target, optimize, &flags));
+ test_deps.dependOn(test_fixture(b, "pwsh-test", false, false, null, target, optimize, &flags));
+ test_deps.dependOn(test_fixture(b, "printargs-test", false, false, null, target, optimize, &flags));
+ test_deps.dependOn(test_fixture(b, "printenv-test", false, false, null, target, optimize, &flags));
+ test_deps.dependOn(test_fixture(b, "streams-test", true, system_integration_options.uv, libuv, target, optimize, &flags));
// xxd - hex dump utility (vendored from Vim)
const xxd_exe = b.addExecutable(.{
@@ -434,28 +518,39 @@ pub fn build(b: *std.Build) !void {
xxd_exe.linkLibC();
test_deps.dependOn(&b.addInstallArtifact(xxd_exe, .{}).step);
- const parser_c = b.dependency("treesitter_c", .{ .target = target, .optimize = optimize });
- test_deps.dependOn(add_ts_parser(b, "c", parser_c.path("."), false, target, optimize));
- const parser_markdown = b.dependency("treesitter_markdown", .{ .target = target, .optimize = optimize });
- test_deps.dependOn(add_ts_parser(b, "markdown", parser_markdown.path("tree-sitter-markdown/"), true, target, optimize));
- test_deps.dependOn(add_ts_parser(b, "markdown_inline", parser_markdown.path("tree-sitter-markdown-inline/"), true, target, optimize));
- const parser_vim = b.dependency("treesitter_vim", .{ .target = target, .optimize = optimize });
- test_deps.dependOn(add_ts_parser(b, "vim", parser_vim.path("."), true, target, optimize));
- const parser_vimdoc = b.dependency("treesitter_vimdoc", .{ .target = target, .optimize = optimize });
- test_deps.dependOn(add_ts_parser(b, "vimdoc", parser_vimdoc.path("."), false, target, optimize));
- const parser_lua = b.dependency("treesitter_lua", .{ .target = target, .optimize = optimize });
- test_deps.dependOn(add_ts_parser(b, "lua", parser_lua.path("."), true, target, optimize));
- const parser_query = b.dependency("treesitter_query", .{ .target = target, .optimize = optimize });
- test_deps.dependOn(add_ts_parser(b, "query", parser_query.path("."), false, target, optimize));
-
- const unit_headers: ?[]const LazyPath = if (support_unittests) &(unittest_include_path ++ .{gen_headers.getDirectory()}) else null;
+ if (b.lazyDependency("treesitter_c", .{ .target = target, .optimize = optimize })) |parser| {
+ test_deps.dependOn(add_ts_parser(b, "c", parser.path("."), false, target, optimize));
+ }
+ if (b.lazyDependency("treesitter_markdown", .{ .target = target, .optimize = optimize })) |parser| {
+ test_deps.dependOn(add_ts_parser(b, "markdown", parser.path("tree-sitter-markdown/"), true, target, optimize));
+ test_deps.dependOn(add_ts_parser(b, "markdown_inline", parser.path("tree-sitter-markdown-inline/"), true, target, optimize));
+ }
+ if (b.lazyDependency("treesitter_vim", .{ .target = target, .optimize = optimize })) |parser| {
+ test_deps.dependOn(add_ts_parser(b, "vim", parser.path("."), true, target, optimize));
+ }
+ if (b.lazyDependency("treesitter_vimdoc", .{ .target = target, .optimize = optimize })) |parser| {
+ test_deps.dependOn(add_ts_parser(b, "vimdoc", parser.path("."), false, target, optimize));
+ }
+ if (b.lazyDependency("treesitter_lua", .{ .target = target, .optimize = optimize })) |parser| {
+ test_deps.dependOn(add_ts_parser(b, "lua", parser.path("."), true, target, optimize));
+ }
+ if (b.lazyDependency("treesitter_query", .{ .target = target, .optimize = optimize })) |parser| {
+ test_deps.dependOn(add_ts_parser(b, "query", parser.path("."), false, target, optimize));
+ }
+ var unit_headers: ?[]const LazyPath = null;
+ if (support_unittests) {
+ try unittest_include_path.append(b.allocator, gen_headers.getDirectory());
+ unit_headers = unittest_include_path.items;
+ }
try tests.test_steps(b, nvim_exe, test_deps, lua_dev_deps.path("."), test_config_step.getDirectory(), unit_headers);
}
pub fn test_fixture(
b: *std.Build,
name: []const u8,
+ use_libuv: bool,
+ use_system_libuv: bool,
libuv: ?*std.Build.Step.Compile,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
@@ -475,7 +570,13 @@ pub fn test_fixture(
fixture.addCSourceFile(.{ .file = b.path(b.fmt("./test/functional/fixtures/{s}.c", .{source})), .flags = flags });
fixture.linkLibC();
- if (libuv) |uv| fixture.linkLibrary(uv);
+ if (use_libuv) {
+ if (use_system_libuv) {
+ fixture.root_module.linkSystemLibrary("libuv", .{});
+ } else if (libuv) |uv| {
+ fixture.linkLibrary(uv);
+ }
+ }
return &b.addInstallArtifact(fixture, .{}).step;
}
@@ -551,3 +652,29 @@ pub fn test_config(b: *std.Build) ![]u8 {
\\return M
, .{ .bin_dir = try replace_backslashes(b, b.install_path), .src_path = try replace_backslashes(b, src_path) });
}
+
+fn appendSystemIncludePath(
+ b: *std.Build,
+ path: *std.ArrayList(LazyPath),
+ system_name: []const u8,
+) !void {
+ var code: u8 = 0;
+ const stdout = try b.runAllowFail(
+ &[_][]const u8{ "pkg-config", system_name, "--cflags-only-I", "--keep-system-cflags" },
+ &code,
+ .Ignore,
+ );
+ if (code != 0) return std.Build.PkgConfigError.PkgConfigFailed;
+ var arg_it = std.mem.tokenizeAny(u8, stdout, " \r\n\t");
+ while (arg_it.next()) |arg| {
+ if (std.mem.eql(u8, arg, "-I")) {
+ // -I /foo/bar
+ const dir = arg_it.next() orelse return std.Build.PkgConfigError.PkgConfigInvalidOutput;
+ try path.append(b.allocator, .{ .cwd_relative = dir });
+ } else if (std.mem.startsWith(u8, arg, "-I")) {
+ // -I/foo/bar
+ const dir = arg[("-I".len)..];
+ try path.append(b.allocator, .{ .cwd_relative = dir });
+ }
+ }
+}
diff --git a/build.zig.zon b/build.zig.zon
@@ -6,30 +6,35 @@
.dependencies = .{
.zlua = .{
- .url = "git+https://github.com/natecraddock/ziglua#a4d08d97795c312e63a0f09d456f7c6d280610b4",
- .hash = "zlua-0.1.0-hGRpC5c9BQAfU5bkkFfLV9B4a7Prw8N7JPIFAZBbRCkq",
+ .url = "git+https://github.com/natecraddock/ziglua#dca1800ea46f5a19fc9abf88b2f8c1617f86ac23",
+ .hash = "zlua-0.1.0-hGRpC1dCBQDf-IqqUifYvyr8B9-4FlYXqY8cl7HIetrC",
},
.lpeg = .{
.url = "https://github.com/neovim/deps/raw/d495ee6f79e7962a53ad79670cb92488abe0b9b4/opt/lpeg-1.1.0.tar.gz",
.hash = "N-V-__8AAMnaAwCEutreuREG3QayBVEZqUTDQFY1Nsrv2OIt",
+ .lazy = true,
},
.luv = .{
.url = "git+https://github.com/luvit/luv?ref=1.51.0-1#4c9fbc6cf6f3338bb0e0426710cf885ee557b540",
.hash = "N-V-__8AAMlNDwCY07jUoMiq3iORXdZy0uFWKiHsy8MaDBJA",
+ .lazy = true,
},
.lua_compat53 = .{
.url = "https://github.com/lunarmodules/lua-compat-5.3/archive/v0.13.tar.gz",
.hash = "N-V-__8AADi-AwDnVoXwDCQvv2wcYOmN0bJLqZ44J3lwoQY2",
+ .lazy = true,
},
.treesitter = .{
.url = "git+https://github.com/tree-sitter/tree-sitter?ref=v0.26.3#cd4b6e2ef996d4baca12caadb78dffc8b55bc869",
.hash = "tree_sitter-0.26.3-Tw2sRwKWCwB6DronNIXBd7Aq5TY4WlnmS4d8PB_M7TIU",
+ .lazy = true,
},
.libuv = .{
.url = "git+https://github.com/allyourcodebase/libuv#a2dfd385bd2a00d6d290fda85a40a55a9d6cffc5",
.hash = "libuv-1.51.0-htqqv6liAADxBLIBCZT-qUh_3nRRwtNYsOFQOUmrd_sx",
+ .lazy = true,
},
- .utf8proc = .{ .path = "./deps/utf8proc/" },
+ .utf8proc = .{ .path = "./deps/utf8proc/", .lazy = true },
.unibilium = .{ .path = "./deps/unibilium/", .lazy = true },
.libiconv = .{
.url = "git+https://github.com/allyourcodebase/libiconv#9def4c8a1743380e85bcedb80f2c15b455e236f3",
@@ -43,26 +48,32 @@
.treesitter_c = .{
.url = "git+https://github.com/tree-sitter/tree-sitter-c?ref=v0.24.1#7fa1be1b694b6e763686793d97da01f36a0e5c12",
.hash = "N-V-__8AANxPSABzw3WBTSH_YkwaGAfrK6PBqAMqQedkDDim",
+ .lazy = true,
},
.treesitter_markdown = .{
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-markdown?ref=v0.5.1#2dfd57f547f06ca5631a80f601e129d73fc8e9f0",
.hash = "N-V-__8AABcZUwBZelO8MiLRwuLD1Wk34qHHbXtS4UW3Khys",
+ .lazy = true,
},
.treesitter_lua = .{
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-lua?ref=v0.4.1#816840c592ab973500ae9750763c707b447e7fef",
.hash = "N-V-__8AAHCmCAAf-5sa_C1N5Ts8B7V-vTKqUEMJZVnNkq_y",
+ .lazy = true,
},
.treesitter_vim = .{
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-vim?ref=v0.7.0#3dd4747082d1b717b8978211c06ef7b6cd16125b",
.hash = "N-V-__8AAMArVAB4uo2wg2XRs8HBviQ4Pq366cC_iRolX4Vc",
+ .lazy = true,
},
.treesitter_vimdoc = .{
.url = "git+https://github.com/neovim/tree-sitter-vimdoc?ref=v4.1.0#f061895a0eff1d5b90e4fb60d21d87be3267031a",
.hash = "N-V-__8AAI7VCgBqRcQ-vIxB8DJJFhmLG42p6rfwCWIdypSJ",
+ .lazy = true,
},
.treesitter_query = .{
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-query?ref=v0.8.0#a225e21d81201be77da58de614e2b7851735677a",
.hash = "N-V-__8AAMR5AwAzZ5_8S2p2COTEf5usBeeT4ORzh-lBGkWy",
+ .lazy = true,
},
},
.paths = .{
diff --git a/deps/unibilium/build.zig b/deps/unibilium/build.zig
@@ -4,7 +4,6 @@ pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
- const upstream = b.dependency("unibilium", .{});
const lib = b.addLibrary(.{
.name = "unibilium",
.linkage = .static,
@@ -14,17 +13,19 @@ pub fn build(b: *std.Build) !void {
}),
});
- lib.addIncludePath(upstream.path(""));
+ if (b.lazyDependency("unibilium", .{})) |upstream| {
+ lib.addIncludePath(upstream.path(""));
- lib.installHeader(upstream.path("unibilium.h"), "unibilium.h");
+ lib.installHeader(upstream.path("unibilium.h"), "unibilium.h");
- lib.linkLibC();
+ lib.linkLibC();
- lib.addCSourceFiles(.{ .root = upstream.path(""), .files = &.{
- "unibilium.c",
- "uninames.c",
- "uniutil.c",
- }, .flags = &.{"-DTERMINFO_DIRS=\"/etc/terminfo:/usr/share/terminfo\""} });
+ lib.addCSourceFiles(.{ .root = upstream.path(""), .files = &.{
+ "unibilium.c",
+ "uninames.c",
+ "uniutil.c",
+ }, .flags = &.{"-DTERMINFO_DIRS=\"/etc/terminfo:/usr/share/terminfo\""} });
+ }
b.installArtifact(lib);
}
diff --git a/deps/unibilium/build.zig.zon b/deps/unibilium/build.zig.zon
@@ -7,6 +7,7 @@
.unibilium = .{
.url = "git+https://github.com/neovim/unibilium?ref=v2.1.2#bfcb0350129dd76893bc90399cf37c45812268a2",
.hash = "N-V-__8AADO1CgCggvx73yptnBlXbEm7TjOSO6VGIqc0CvYR",
+ .lazy = true,
},
},
}
diff --git a/deps/utf8proc/build.zig b/deps/utf8proc/build.zig
@@ -4,7 +4,6 @@ pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
- const upstream = b.dependency("utf8proc", .{});
const lib = b.addLibrary(.{
.name = "utf8proc",
.linkage = .static,
@@ -14,14 +13,16 @@ pub fn build(b: *std.Build) !void {
}),
});
- lib.addIncludePath(upstream.path(""));
- lib.installHeader(upstream.path("utf8proc.h"), "utf8proc.h");
+ if (b.lazyDependency("utf8proc", .{})) |upstream| {
+ lib.addIncludePath(upstream.path(""));
+ lib.installHeader(upstream.path("utf8proc.h"), "utf8proc.h");
- lib.linkLibC();
+ lib.linkLibC();
- lib.addCSourceFiles(.{ .root = upstream.path(""), .files = &.{
- "utf8proc.c",
- }, .flags = &.{"-DUTF8PROC_STATIC"} });
+ lib.addCSourceFiles(.{ .root = upstream.path(""), .files = &.{
+ "utf8proc.c",
+ }, .flags = &.{"-DUTF8PROC_STATIC"} });
+ }
b.installArtifact(lib);
}
diff --git a/deps/utf8proc/build.zig.zon b/deps/utf8proc/build.zig.zon
@@ -7,6 +7,7 @@
.utf8proc = .{
.url = "git+https://github.com/juliastrings/utf8proc?ref=v2.11.3#e5e799221b45bbb90f5fdc5c69b6b8dfbf017e78",
.hash = "N-V-__8AACywKABFCj0r_Y-jIWsk9ahy10zlk78hjn6S-39g",
+ .lazy = true,
},
},
}
diff --git a/src/build_lua.zig b/src/build_lua.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const build = @import("../build.zig");
const LazyPath = std.Build.LazyPath;
pub fn build_nlua0(
@@ -7,9 +8,10 @@ pub fn build_nlua0(
optimize: std.builtin.OptimizeMode,
use_luajit: bool,
ziglua: *std.Build.Dependency,
- lpeg: *std.Build.Dependency,
- libluv: *std.Build.Step.Compile,
-) *std.Build.Step.Compile {
+ lpeg: ?*std.Build.Dependency,
+ libluv: ?*std.Build.Step.Compile,
+ system_integration_options: build.SystemIntegrationOptions,
+) !*std.Build.Step.Compile {
const options = b.addOptions();
options.addOption(bool, "use_luajit", use_luajit);
@@ -19,6 +21,7 @@ pub fn build_nlua0(
.root_source_file = b.path("src/nlua0.zig"),
.target = target,
.optimize = optimize,
+ .link_libc = true,
}),
});
const nlua0_mod = nlua0_exe.root_module;
@@ -28,6 +31,7 @@ pub fn build_nlua0(
.root_source_file = b.path("src/nlua0.zig"),
.target = target,
.optimize = optimize,
+ .link_libc = true,
}),
});
@@ -39,14 +43,23 @@ pub fn build_nlua0(
mod.addImport("ziglua", ziglua.module("zlua"));
mod.addImport("embedded_data", embedded_data);
// addImport already links by itself. but we need headers as well..
- mod.linkLibrary(ziglua.artifact("lua"));
- mod.linkLibrary(libluv);
+ if (system_integration_options.lua) {
+ const system_lua_lib = if (use_luajit) "luajit" else "lua5.1";
+ mod.linkSystemLibrary(system_lua_lib, .{});
+ } else {
+ mod.linkLibrary(ziglua.artifact("lua"));
+ }
+ if (libluv) |luv| {
+ mod.linkLibrary(luv);
+ } else {
+ mod.linkSystemLibrary("luv", .{});
+ }
mod.addOptions("options", options);
mod.addIncludePath(b.path("src"));
mod.addIncludePath(b.path("src/includes_fixmelater"));
- add_lua_modules(mod, lpeg, use_luajit, true);
+ try add_lua_modules(b, target.result, mod, lpeg, use_luajit, true, system_integration_options);
}
// for debugging the nlua0 environment
@@ -68,14 +81,24 @@ pub fn build_nlua0(
return nlua0_exe;
}
-pub fn add_lua_modules(mod: *std.Build.Module, lpeg: *std.Build.Dependency, use_luajit: bool, is_nlua0: bool) void {
+pub fn add_lua_modules(
+ b: *std.Build,
+ target: std.Target,
+ mod: *std.Build.Module,
+ lpeg_dep: ?*std.Build.Dependency,
+ use_luajit: bool,
+ is_nlua0: bool,
+ system_integration_options: build.SystemIntegrationOptions,
+) !void {
const flags = [_][]const u8{
// Standard version used in Lua Makefile
"-std=gnu99",
if (is_nlua0) "-DNVIM_NLUA0" else "",
};
- mod.addIncludePath(lpeg.path(""));
+ if (lpeg_dep) |lpeg| {
+ mod.addIncludePath(lpeg.path(""));
+ }
mod.addCSourceFiles(.{
.files = &.{
"src/mpack/lmpack.c",
@@ -86,18 +109,25 @@ pub fn add_lua_modules(mod: *std.Build.Module, lpeg: *std.Build.Dependency, use_
},
.flags = &flags,
});
- mod.addCSourceFiles(.{
- .root = .{ .dependency = .{ .dependency = lpeg, .sub_path = "" } },
- .files = &.{
- "lpcap.c",
- "lpcode.c",
- "lpcset.c",
- "lpprint.c",
- "lptree.c",
- "lpvm.c",
- },
- .flags = &flags,
- });
+ if (system_integration_options.lpeg) {
+ if (try findLpeg(b, target)) |lpeg_lib| {
+ mod.addLibraryPath(.{ .cwd_relative = std.fs.path.dirname(lpeg_lib).? });
+ mod.addObjectFile(.{ .cwd_relative = lpeg_lib });
+ }
+ } else if (lpeg_dep) |lpeg| {
+ mod.addCSourceFiles(.{
+ .root = .{ .dependency = .{ .dependency = lpeg, .sub_path = "" } },
+ .files = &.{
+ "lpcap.c",
+ "lpcode.c",
+ "lpcset.c",
+ "lpprint.c",
+ "lptree.c",
+ "lpvm.c",
+ },
+ .flags = &flags,
+ });
+ }
if (!use_luajit) {
mod.addCSourceFiles(.{
@@ -113,11 +143,12 @@ pub fn build_libluv(
b: *std.Build,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
- lua: *std.Build.Step.Compile,
+ lua: ?*std.Build.Step.Compile,
libuv: *std.Build.Step.Compile,
+ use_luajit: bool,
) !*std.Build.Step.Compile {
- const upstream = b.dependency("luv", .{});
- const compat53 = b.dependency("lua_compat53", .{});
+ const upstream = b.lazyDependency("luv", .{});
+ const compat53 = b.lazyDependency("lua_compat53", .{});
const lib = b.addLibrary(.{
.name = "luv",
.linkage = .static,
@@ -127,21 +158,59 @@ pub fn build_libluv(
}),
});
- lib.linkLibrary(lua);
+ if (lua) |lua_lib| {
+ lib.root_module.linkLibrary(lua_lib);
+ } else {
+ const system_lua_lib = if (use_luajit) "luajit" else "lua5.1";
+ lib.root_module.linkSystemLibrary(system_lua_lib, .{});
+ }
lib.linkLibrary(libuv);
- lib.addIncludePath(upstream.path("src"));
- lib.addIncludePath(compat53.path("c-api"));
-
- lib.installHeader(upstream.path("src/luv.h"), "luv/luv.h");
-
- lib.addCSourceFiles(.{ .root = upstream.path("src/"), .files = &.{
- "luv.c",
- } });
-
- lib.addCSourceFiles(.{ .root = compat53.path("c-api"), .files = &.{
- "compat-5.3.c",
- } });
+ if (upstream) |dep| {
+ lib.addIncludePath(dep.path("src"));
+ lib.installHeader(dep.path("src/luv.h"), "luv/luv.h");
+ lib.addCSourceFiles(.{ .root = dep.path("src/"), .files = &.{
+ "luv.c",
+ } });
+ }
+ if (compat53) |dep| {
+ lib.addIncludePath(dep.path("c-api"));
+ lib.addCSourceFiles(.{ .root = dep.path("c-api"), .files = &.{
+ "compat-5.3.c",
+ } });
+ }
return lib;
}
+
+fn findLpeg(b: *std.Build, target: std.Target) !?[]const u8 {
+ const filenames = [_][]const u8{
+ "lpeg_a",
+ "lpeg",
+ "liblpeg_a",
+ "lpeg.so",
+ b.fmt("lpeg{s}", .{target.dynamicLibSuffix()}),
+ };
+ var code: u8 = 0;
+ const dirs_stdout = std.mem.trimEnd(u8, try b.runAllowFail(&[_][]const u8{
+ "pkg-config",
+ "--variable=pc_system_libdirs",
+ "--keep-system-cflags",
+ "pkg-config",
+ }, &code, .Ignore), "\r\n");
+ var paths: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 0);
+ var path_it = std.mem.tokenizeAny(u8, dirs_stdout, " ,");
+ while (path_it.next()) |dir| {
+ try paths.append(b.allocator, dir);
+ try paths.append(b.allocator, b.fmt("{s}/lua/5.1", .{dir}));
+ }
+ for (paths.items) |path| {
+ var dir = std.fs.openDirAbsolute(path, .{}) catch continue;
+ defer dir.close();
+ for (filenames) |filename| {
+ dir.access(filename, .{}) catch continue;
+ return b.fmt("{s}/{s}", .{ path, filename });
+ }
+ }
+ return null;
+}