main build.zig
Eric Bower  ·  2026-07-27
  1const std = @import("std");
  2const build_zig_zon = @import("build.zig.zon");
  3
  4const linux_targets: []const std.Target.Query = &.{
  5    .{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .musl },
  6    .{ .cpu_arch = .aarch64, .os_tag = .linux, .abi = .musl },
  7};
  8
  9const macos_targets: []const std.Target.Query = &.{
 10    .{ .cpu_arch = .x86_64, .os_tag = .macos },
 11    .{ .cpu_arch = .aarch64, .os_tag = .macos },
 12};
 13
 14pub fn build(b: *std.Build) void {
 15    const target = b.standardTargetOptions(.{});
 16    // const is_macos = target.result.os.tag == .macos;
 17    const optimize = b.standardOptimizeOption(.{});
 18    const version = b.option([]const u8, "version", "Version string for release") orelse
 19        @as([]const u8, build_zig_zon.version);
 20
 21    const options = b.addOptions();
 22    options.addOption([]const u8, "version", version);
 23    const ghostty_ver = build_zig_zon.dependencies.ghostty.hash;
 24    options.addOption([]const u8, "ghostty_version", ghostty_ver);
 25
 26    const exe_mod = b.createModule(.{
 27        .root_source_file = b.path("src/main.zig"),
 28        .target = target,
 29        .optimize = optimize,
 30        .link_libc = true,
 31    });
 32    exe_mod.addOptions("build_options", options);
 33
 34    const dep = b.dependency("ghostty", .{
 35        .target = target,
 36        .optimize = optimize,
 37        .@"emit-lib-vt" = true,
 38        // Not redundant: in lib-vt mode emit-xcframework defaults to "xcodebuild
 39        // on PATH" (true even via the CLT stub), which pulls in the iOS SDK at
 40        // configure time and breaks builds without full Xcode.
 41        .@"emit-xcframework" = false,
 42        .@"emit-macos-app" = false,
 43    });
 44    exe_mod.addImport(
 45        "ghostty-vt",
 46        dep.module("ghostty-vt"),
 47    );
 48
 49    // Run
 50    {
 51        const run_step = b.step("run", "Run the app");
 52        const exe = b.addExecutable(.{
 53            .name = "zmx",
 54            // .use_llvm = true,
 55            // .use_lld = !is_macos,
 56            .root_module = exe_mod,
 57        });
 58
 59        b.installArtifact(exe);
 60        const run_cmd = b.addRunArtifact(exe);
 61        run_cmd.step.dependOn(b.getInstallStep());
 62        if (b.args) |args| run_cmd.addArgs(args);
 63        run_step.dependOn(&run_cmd.step);
 64    }
 65
 66    // Test
 67    {
 68        const test_step = b.step("test", "Run unit tests");
 69        const test_module = b.addModule("test", .{
 70            .root_source_file = b.path("src/test.zig"),
 71            .target = target,
 72            .optimize = optimize,
 73            .link_libc = true,
 74        });
 75        const test_dep = b.dependency("ghostty", .{
 76            .target = target,
 77            .optimize = optimize,
 78            .@"emit-lib-vt" = true,
 79            .@"emit-xcframework" = false,
 80            .@"emit-macos-app" = false,
 81        });
 82        test_module.addImport(
 83            "ghostty-vt",
 84            test_dep.module("ghostty-vt"),
 85        );
 86        const exe_unit_tests = b.addTest(.{
 87            .root_module = test_module,
 88            // .use_llvm = true,
 89            // .use_lld = !is_macos,
 90        });
 91
 92        const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
 93        test_step.dependOn(&run_exe_unit_tests.step);
 94    }
 95
 96    // Check for LSP integration
 97    {
 98        const check = b.step("check", "Check if zmx compiles");
 99        const exe_check = b.addExecutable(.{
100            .name = "zmx",
101            // .use_llvm = true,
102            // .use_lld = !is_macos,
103            .root_module = exe_mod,
104        });
105
106        // Finally we add the "check" step which will be detected
107        // by ZLS and automatically enable Build-On-Save.
108        // If you copy this into your `build.zig`, make sure to rename 'foo'
109        check.dependOn(&exe_check.step);
110    }
111
112    // Release step - cross-compile to all targets from any host
113    {
114        const release_step = b.step(
115            "release",
116            "Build release binaries for all platforms",
117        );
118        const release_targets = linux_targets ++ macos_targets;
119        for (release_targets) |release_target| {
120            const resolved = b.resolveTargetQuery(release_target);
121            const release_mod = b.createModule(.{
122                .root_source_file = b.path("src/main.zig"),
123                .target = resolved,
124                .optimize = .ReleaseSafe,
125                .link_libc = true,
126            });
127            release_mod.addOptions("build_options", options);
128
129            if (b.lazyDependency("ghostty", .{
130                .target = resolved,
131                .optimize = .ReleaseSafe,
132                .@"emit-lib-vt" = true,
133                .@"emit-xcframework" = false,
134                .@"emit-macos-app" = false,
135            })) |release_dep| {
136                release_mod.addImport("ghostty-vt", release_dep.module("ghostty-vt"));
137            }
138
139            // const is_local_macos = resolved.result.os.tag == .macos;
140            const release_exe = b.addExecutable(.{
141                .name = "zmx",
142                // .use_llvm = true,
143                // .use_lld = !is_local_macos,
144                .root_module = release_mod,
145            });
146
147            const os_name = @tagName(release_target.os_tag orelse .linux);
148            const arch_name = @tagName(release_target.cpu_arch orelse .x86_64);
149            const tarball_name = b.fmt("zmx-{s}-{s}-{s}.tar.gz", .{ version, os_name, arch_name });
150
151            const tar = b.addSystemCommand(&.{ "tar", "-czf" });
152
153            const tarball = tar.addOutputFileArg(tarball_name);
154            tar.addArg("-C");
155            tar.addDirectoryArg(release_exe.getEmittedBinDirectory());
156            tar.addArg("zmx");
157
158            const shasum = b.addSystemCommand(&.{"sha256sum"});
159            shasum.addFileArg(tarball);
160            const shasum_output = shasum.captureStdOut(.{});
161
162            const install_tar = b.addInstallFile(tarball, b.fmt("dist/{s}", .{tarball_name}));
163            const install_sha = b.addInstallFile(
164                shasum_output,
165                b.fmt("dist/{s}.sha256", .{tarball_name}),
166            );
167            release_step.dependOn(&install_tar.step);
168            release_step.dependOn(&install_sha.step);
169        }
170    }
171}