// Build recipe // SPDX-FileCopyrightText: 2025 Nguyễn Gia Phong // SPDX-License-Identifier: GPL-3.0-or-later const Build = std.Build; const Module = Build.Module; const NativePaths = std.zig.system.NativePaths; const getStdOut = std.io.getStdOut; const openDirAbsolute = std.fs.openDirAbsolute; const std = @import("std"); const tokenize = std.mem.tokenizeScalar; const supported_languages = @embedFile("src/supported-languages"); /// Generates the "language" module. pub fn main() !void { const stdout = getStdOut().writer(); try stdout.writeAll( \\const Language = @import("tree-sitter").Language; \\pub const Create = *const fn () callconv(.c) *const Language; ); var language_names = tokenize(u8, supported_languages, '\n'); while (language_names.next()) |name| try stdout.print( \\pub const {s} = @extern(Create, .{{ .name = "tree_sitter_{s}" }}); , .{ name, name }); } fn linkTreeSitterGrammars(b: *Build, module: *Module) !void { const target = module.resolved_target.?; const native_paths = try NativePaths.detect(b.allocator, target.result); for (native_paths.lib_dirs.items) |lib_dir| { // Guix somehow puts the shared objects in $output/lib/tree-sitter/. const tree_sitter_dir = b.pathJoin(&.{ lib_dir, "tree-sitter" }); var dir = openDirAbsolute(tree_sitter_dir, .{}) catch continue; dir.close(); module.addLibraryPath(.{ .cwd_relative = tree_sitter_dir }); } var language_names = tokenize(u8, supported_languages, '\n'); while (language_names.next()) |name| module.linkSystemLibrary(b.fmt("tree-sitter-{s}", .{ name }), .{}); const languages = b.createModule(.{ .root_source_file = b.addRunArtifact(b.addExecutable(.{ .name = "extern-tree-sitter-grammars", .root_source_file = b.path(@src().file), // main function above .target = b.graph.host, })).captureStdOut(), .target = target, .optimize = module.optimize.?, }); const lib = "tree-sitter"; languages.addImport(lib, b.dependency(lib, .{}).module(lib)); module.addImport("languages", languages); } pub fn build(b: *Build) !void { const mod = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = b.standardTargetOptions(.{}), .optimize = b.standardOptimizeOption(.{}), }); inline for (.{ "known-folders", "tree-sitter", "vaxis", "zsanett" }) |lib| mod.addImport(lib, b.dependency(lib, .{}).module(lib)); try linkTreeSitterGrammars(b, mod); const unit_tests = b.addTest(.{ .root_module = mod }); const test_step = b.step("test", "Run unit tests"); test_step.dependOn(&b.addRunArtifact(unit_tests).step); const exe = b.addExecutable(.{ .name = "kay", .root_module = mod }); b.installArtifact(exe); const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(b.getInstallStep()); if (b.args) |args| run_cmd.addArgs(args); const run_step = b.step("run", "Run the app"); run_step.dependOn(&run_cmd.step); }