From d87921bb9c39b0b06c811f2082f9a9991cdca027 Mon Sep 17 00:00:00 2001 From: "Ronald T. Casili" Date: Sat, 9 Aug 2025 15:18:07 +0800 Subject: [PATCH] fix(bindings): update zig template files (#4637) --- crates/cli/src/init.rs | 39 +++++++++++--- crates/cli/src/templates/build.zig | 71 +++++++++++++++----------- crates/cli/src/templates/build.zig.zon | 13 +++-- crates/cli/src/templates/root.zig | 18 +------ crates/cli/src/templates/test.zig | 17 ++++++ 5 files changed, 99 insertions(+), 59 deletions(-) create mode 100644 crates/cli/src/templates/test.zig diff --git a/crates/cli/src/init.rs b/crates/cli/src/init.rs index 5fceafa9..18f0a22a 100644 --- a/crates/cli/src/init.rs +++ b/crates/cli/src/init.rs @@ -98,6 +98,7 @@ const TESTS_SWIFT_TEMPLATE: &str = include_str!("./templates/tests.swift"); const BUILD_ZIG_TEMPLATE: &str = include_str!("./templates/build.zig"); const BUILD_ZIG_ZON_TEMPLATE: &str = include_str!("./templates/build.zig.zon"); const ROOT_ZIG_TEMPLATE: &str = include_str!("./templates/root.zig"); +const TEST_ZIG_TEMPLATE: &str = include_str!("./templates/test.zig"); const TREE_SITTER_JSON_SCHEMA: &str = "https://tree-sitter.github.io/tree-sitter/assets/schemas/config.schema.json"; @@ -749,17 +750,39 @@ pub fn generate_grammar_files( // Generate Zig bindings if tree_sitter_config.bindings.zig { - missing_path(repo_path.join("build.zig"), |path| { - generate_file(path, BUILD_ZIG_TEMPLATE, language_name, &generate_opts) - })?; + missing_path_else( + repo_path.join("build.zig"), + allow_update, + |path| generate_file(path, BUILD_ZIG_TEMPLATE, language_name, &generate_opts), + |path| { + eprintln!("Replacing build.zig"); + generate_file(path, BUILD_ZIG_TEMPLATE, language_name, &generate_opts) + }, + )?; - missing_path(repo_path.join("build.zig.zon"), |path| { - generate_file(path, BUILD_ZIG_ZON_TEMPLATE, language_name, &generate_opts) - })?; + missing_path_else( + repo_path.join("build.zig.zon"), + allow_update, + |path| generate_file(path, BUILD_ZIG_ZON_TEMPLATE, language_name, &generate_opts), + |path| { + eprintln!("Replacing build.zig.zon"); + generate_file(path, BUILD_ZIG_ZON_TEMPLATE, language_name, &generate_opts) + }, + )?; missing_path(bindings_dir.join("zig"), create_dir)?.apply(|path| { - missing_path(path.join("root.zig"), |path| { - generate_file(path, ROOT_ZIG_TEMPLATE, language_name, &generate_opts) + missing_path_else( + path.join("root.zig"), + allow_update, + |path| generate_file(path, ROOT_ZIG_TEMPLATE, language_name, &generate_opts), + |path| { + eprintln!("Replacing root.zig"); + generate_file(path, ROOT_ZIG_TEMPLATE, language_name, &generate_opts) + }, + )?; + + missing_path(path.join("test.zig"), |path| { + generate_file(path, TEST_ZIG_TEMPLATE, language_name, &generate_opts) })?; Ok(()) diff --git a/crates/cli/src/templates/build.zig b/crates/cli/src/templates/build.zig index 65c3b837..6b9540c2 100644 --- a/crates/cli/src/templates/build.zig +++ b/crates/cli/src/templates/build.zig @@ -7,24 +7,24 @@ pub fn build(b: *std.Build) !void { const shared = b.option(bool, "build-shared", "Build a shared library") orelse true; const reuse_alloc = b.option(bool, "reuse-allocator", "Reuse the library allocator") orelse false; - const lib: *std.Build.Step.Compile = if (shared) b.addSharedLibrary(.{ - .name = "tree-sitter-PARSER_NAME", - .pic = true, - .target = target, - .optimize = optimize, - .link_libc = true, - }) else b.addStaticLibrary(.{ - .name = "tree-sitter-PARSER_NAME", - .target = target, - .optimize = optimize, - .link_libc = true, + const library_name = "tree-sitter-PARSER_NAME"; + + const lib: *std.Build.Step.Compile = b.addLibrary(.{ + .name = library_name, + .linkage = if (shared) .dynamic else .static, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + .link_libc = true, + .pic = if (shared) true else null, + }), }); lib.addCSourceFile(.{ .file = b.path("src/parser.c"), .flags = &.{"-std=c11"}, }); - if (hasScanner(b.build_root.handle)) { + if (fileExists(b, "src/scanner.c")) { lib.addCSourceFile(.{ .file = b.path("src/scanner.c"), .flags = &.{"-std=c11"}, @@ -42,38 +42,49 @@ pub fn build(b: *std.Build) !void { b.installArtifact(lib); b.installFile("src/node-types.json", "node-types.json"); - b.installDirectory(.{ .source_dir = b.path("queries"), .install_dir = .prefix, .install_subdir = "queries", .include_extensions = &.{"scm"} }); - const module = b.addModule("tree-sitter-PARSER_NAME", .{ + if (fileExists(b, "queries")) { + b.installDirectory(.{ + .source_dir = b.path("queries"), + .install_dir = .prefix, + .install_subdir = "queries", + .include_extensions = &.{"scm"}, + }); + } + + const module = b.addModule(library_name, .{ .root_source_file = b.path("bindings/zig/root.zig"), .target = target, .optimize = optimize, }); module.linkLibrary(lib); - const ts_dep = b.dependency("tree-sitter", .{}); - const ts_mod = ts_dep.module("tree-sitter"); - module.addImport("tree-sitter", ts_mod); - - // ╭─────────────────╮ - // │ Tests │ - // ╰─────────────────╯ - const tests = b.addTest(.{ - .root_source_file = b.path("bindings/zig/root.zig"), - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .root_source_file = b.path("bindings/zig/test.zig"), + .target = target, + .optimize = optimize, + }), }); - tests.linkLibrary(lib); - tests.root_module.addImport("tree-sitter", ts_mod); + tests.root_module.addImport(library_name, module); + + var args = try std.process.argsWithAllocator(b.allocator); + defer args.deinit(); + while (args.next()) |a| { + if (std.mem.eql(u8, a, "test")) { + const ts_dep = b.lazyDependency("tree_sitter", .{}) orelse continue; + tests.root_module.addImport("tree-sitter", ts_dep.module("tree-sitter")); + break; + } + } const run_tests = b.addRunArtifact(tests); - const test_step = b.step("test", "Run unit tests"); test_step.dependOn(&run_tests.step); } -inline fn hasScanner(dir: std.fs.Dir) bool { - dir.access("src/scanner.c", .{}) catch return false; +inline fn fileExists(b: *std.Build, filename: []const u8) bool { + const dir = b.build_root.handle; + dir.access(filename, .{}) catch return false; return true; } diff --git a/crates/cli/src/templates/build.zig.zon b/crates/cli/src/templates/build.zig.zon index 1f4b3907..ef084d23 100644 --- a/crates/cli/src/templates/build.zig.zon +++ b/crates/cli/src/templates/build.zig.zon @@ -1,10 +1,13 @@ .{ - .name = "tree-sitter-PARSER_NAME", + .name = .tree_sitter_PARSER_NAME, .version = "PARSER_VERSION", - .dependencies = .{ .@"tree-sitter" = .{ - .url = "https://github.com/tree-sitter/zig-tree-sitter/archive/refs/tags/v0.25.0.tar.gz", - .hash = "12201a8d5e840678bbbf5128e605519c4024af422295d68e2ba2090e675328e5811d", - } }, + .dependencies = .{ + .tree_sitter = .{ + .url = "git+https://github.com/tree-sitter/zig-tree-sitter#b4b72c903e69998fc88e27e154a5e3cc9166551b", + .hash = "tree_sitter-0.25.0-8heIf51vAQConvVIgvm-9mVIbqh7yabZYqPXfOpS3YoG", + .lazy = true, + }, + }, .paths = .{ "build.zig", "build.zig.zon", diff --git a/crates/cli/src/templates/root.zig b/crates/cli/src/templates/root.zig index 26a6cbef..0e8f24bd 100644 --- a/crates/cli/src/templates/root.zig +++ b/crates/cli/src/templates/root.zig @@ -1,19 +1,5 @@ -const testing = @import("std").testing; +extern fn tree_sitter_PARSER_NAME() callconv(.c) *const anyopaque; -const ts = @import("tree-sitter"); -const Language = ts.Language; -const Parser = ts.Parser; - -pub extern fn tree_sitter_PARSER_NAME() callconv(.C) *const Language; - -pub export fn language() *const Language { +pub fn language() *const anyopaque { return tree_sitter_PARSER_NAME(); } - -test "can load grammar" { - const parser = Parser.create(); - defer parser.destroy(); - try testing.expectEqual(parser.setLanguage(language()), void{}); - try testing.expectEqual(parser.getLanguage(), tree_sitter_PARSER_NAME()); -} - diff --git a/crates/cli/src/templates/test.zig b/crates/cli/src/templates/test.zig new file mode 100644 index 00000000..7baec557 --- /dev/null +++ b/crates/cli/src/templates/test.zig @@ -0,0 +1,17 @@ +const testing = @import("std").testing; + +const ts = @import("tree-sitter"); +const root = @import("tree-sitter-PARSER_NAME"); +const Language = ts.Language; +const Parser = ts.Parser; + +test "can load grammar" { + const parser = Parser.create(); + defer parser.destroy(); + + const lang: *const ts.Language = @ptrCast(root.language()); + defer lang.destroy(); + + try testing.expectEqual(void{}, parser.setLanguage(lang)); + try testing.expectEqual(lang, parser.getLanguage()); +}