summaryrefslogtreecommitdiff
path: root/build.zig
blob: 2e54c7f7cd5f7822b7574e40999e2d22c171168e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
const std = @import("std");

pub fn build(b: *std.Build) void {
    const optimize = b.standardOptimizeOption(.{});
    const target = b.standardTargetOptions(.{});
    var threaded: std.Io.Threaded = .init(b.allocator, .{});
    defer threaded.deinit();
    const io = threaded.io();

    const exe = b.addExecutable(.{
        .name = "pardes",
        .root_module = b.createModule(.{
            .target = target,
            .optimize = optimize,
            .root_source_file = b.path("main.zig"),
            .link_libc = true,
        }),
    });
    const tests = b.addExecutable(.{
        .name = "pardes-e2e",
        .root_module = b.createModule(.{
            .target = target,
            .optimize = optimize,
            .root_source_file = b.path("tests.zig"),
            .link_libc = true,
        }),
    });

    // ghostty-vt and vaxis both depend on uucode, but Zig 0.16 forbids the
    // same source file from belonging to two modules, so they can't each have
    // their own uucode instance. We build a single uucode module here (with our
    // own uucode_config.zig) and hand it to both.
    //
    // Our config matches ghostty's exactly except the tables are `.unpacked`;
    // see uucode_config.zig for why that's required on Zig 0.16.
    const uucode_config = b.path("uucode_config.zig");
    const uucode_tables = b.dependency("uucode", .{
        .target = target,
        .optimize = optimize,
        .build_config_path = uucode_config,
    }).namedLazyPath("tables.zig");
    const uucode_mod = b.dependency("uucode", .{
        .target = target,
        .optimize = optimize,
        .build_config_path = uucode_config,
        .tables_path = uucode_tables,
    }).module("uucode");

    // vaxis is built with `external_uucode = true` so it skips its built-in
    // uucode dependency and lets us wire one in.
    const vaxis_dep = b.dependency("vaxis", .{
        .target = target,
        .optimize = optimize,
        .external_uucode = true,
    });
    const vaxis_mod = vaxis_dep.module("vaxis");

    // You'll want to use a lazy dependency here so that ghostty is only
    // downloaded if you actually need it.
    if (b.lazyDependency("ghostty", .{
        // Setting simd to false will force a pure static build that
        // doesn't even require libc, but it has a significant performance
        // penalty. If your embedding app requires libc anyway, you should
        // always keep simd enabled.
        // .simd = false,
    })) |dep| {
        // Accessing ghostty's modules runs its build(), which (because vaxis is
        // a shared dependency, deduplicated to the same module) wires ghostty's
        // own uucode into vaxis. We undo that below by overriding both imports
        // with ours — order matters, so this must happen after this point.
        const ghostty_vt = dep.module("ghostty-vt");
        ghostty_vt.addImport("uucode", uucode_mod);
        exe.root_module.addImport("ghostty-vt", ghostty_vt);
    }

    // Override uucode on vaxis last, so it wins over ghostty's build() above.
    vaxis_mod.addImport("uucode", uucode_mod);
    exe.root_module.addImport("vaxis", vaxis_mod);

    const tree_sitter = b.dependency("tree_sitter", .{
        .target = target,
        .optimize = optimize,
    });
    exe.root_module.addImport("tree-sitter", tree_sitter.module("tree_sitter"));

    const ts_rust_dep = b.dependency("ts_rust", .{});
    const ts_c_dep = b.dependency("ts_c", .{});
    const ts_zig_dep = b.dependency("ts_zig", .{});
    const c_query_path = ts_c_dep.path("queries/highlights.scm").getPath(b);
    const rust_query_path = ts_rust_dep.path("queries/highlights.scm").getPath(b);
    const zig_query_path = ts_zig_dep.path("queries/highlights.scm").getPath(b);
    const c_query = std.Io.Dir.cwd().readFileAlloc(io, c_query_path, b.allocator, .limited(0x100000)) catch @panic("read c highlights");
    const rust_query = std.Io.Dir.cwd().readFileAlloc(io, rust_query_path, b.allocator, .limited(0x100000)) catch @panic("read rust highlights");
    const zig_query = std.Io.Dir.cwd().readFileAlloc(io, zig_query_path, b.allocator, .limited(0x100000)) catch @panic("read zig highlights");
    const ts_queries = b.addOptions();
    ts_queries.addOption([]const u8, "c_highlights", c_query);
    ts_queries.addOption([]const u8, "rust_highlights", rust_query);
    ts_queries.addOption([]const u8, "zig_highlights", zig_query);
    exe.root_module.addOptions("ts_queries", ts_queries);

    const rust_parser_lib = b.addLibrary(.{
        .name = "tree-sitter-rust",
        .root_module = b.createModule(.{
            .target = target,
            .optimize = optimize,
            .link_libc = true,
        }),
        .linkage = .static,
    });
    rust_parser_lib.root_module.addCSourceFile(.{ .file = ts_rust_dep.path("src/parser.c") });
    rust_parser_lib.root_module.addCSourceFile(.{ .file = ts_rust_dep.path("src/scanner.c") });
    rust_parser_lib.root_module.addIncludePath(ts_rust_dep.path("src"));
    exe.root_module.linkLibrary(rust_parser_lib);

    const c_parser_lib = b.addLibrary(.{
        .name = "tree-sitter-c",
        .root_module = b.createModule(.{
            .target = target,
            .optimize = optimize,
            .link_libc = true,
        }),
        .linkage = .static,
    });
    c_parser_lib.root_module.addCSourceFile(.{ .file = ts_c_dep.path("src/parser.c") });
    c_parser_lib.root_module.addIncludePath(ts_c_dep.path("src"));
    exe.root_module.linkLibrary(c_parser_lib);

    const zig_parser_lib = b.addLibrary(.{
        .name = "tree-sitter-zig",
        .root_module = b.createModule(.{
            .target = target,
            .optimize = optimize,
            .link_libc = true,
        }),
        .linkage = .static,
    });
    zig_parser_lib.root_module.addCSourceFile(.{ .file = ts_zig_dep.path("src/parser.c") });
    zig_parser_lib.root_module.addIncludePath(ts_zig_dep.path("src"));
    exe.root_module.linkLibrary(zig_parser_lib);

    const run_exe = b.addRunArtifact(exe);

    const run = b.step("run", "descend to the pardes");
    run.dependOn(&run_exe.step);

    const run_tests = b.addRunArtifact(tests);
    run_tests.addArtifactArg(exe);
    const test_step = b.step("test", "run deterministic tests");
    test_step.dependOn(&run_tests.step);
}