repos / zmx

session persistence for terminal processes
git clone https://github.com/neurosnap/zmx.git

Eric Bower  ·  2026-04-26

build.zig

  1const std = @import("std");
  2
  3const linux_targets: []const std.Target.Query = &.{
  4    .{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .musl },
  5    .{ .cpu_arch = .aarch64, .os_tag = .linux, .abi = .musl },
  6};
  7
  8const macos_targets: []const std.Target.Query = &.{
  9    .{ .cpu_arch = .x86_64, .os_tag = .macos },
 10    .{ .cpu_arch = .aarch64, .os_tag = .macos },
 11};
 12
 13pub fn build(b: *std.Build) void {
 14    const target = b.standardTargetOptions(.{});
 15    const optimize = b.standardOptimizeOption(.{});
 16    const version = b.option([]const u8, "version", "Version string for release") orelse
 17        @as([]const u8, @import("build.zig.zon").version);
 18
 19    var code: u8 = 0;
 20    const git_sha = std.mem.trim(u8, b.runAllowFail(
 21        &.{ "git", "rev-parse", "--short", "HEAD" },
 22        &code,
 23        .Inherit,
 24    ) catch "unknown", "\n");
 25
 26    const options = b.addOptions();
 27    options.addOption([]const u8, "version", version);
 28    options.addOption([]const u8, "git_sha", git_sha);
 29    const ghostty_ver = @import("build.zig.zon").dependencies.ghostty.hash;
 30    options.addOption([]const u8, "ghostty_version", ghostty_ver);
 31
 32    const exe_mod = b.createModule(.{
 33        .root_source_file = b.path("src/main.zig"),
 34        .target = target,
 35        .optimize = optimize,
 36    });
 37    exe_mod.addOptions("build_options", options);
 38
 39    const dep = b.dependency("ghostty", .{
 40        .target = target,
 41        .optimize = optimize,
 42    });
 43    exe_mod.addImport(
 44        "ghostty-vt",
 45        dep.module("ghostty-vt"),
 46    );
 47
 48    // Run
 49    {
 50        const run_step = b.step("run", "Run the app");
 51        const exe = b.addExecutable(.{
 52            .name = "zmx",
 53            .root_module = exe_mod,
 54        });
 55        exe.linkLibC();
 56        b.installArtifact(exe);
 57        const run_cmd = b.addRunArtifact(exe);
 58        run_cmd.step.dependOn(b.getInstallStep());
 59        if (b.args) |args| run_cmd.addArgs(args);
 60        run_step.dependOn(&run_cmd.step);
 61    }
 62
 63    // Test
 64    {
 65        const test_step = b.step("test", "Run unit tests");
 66        const test_module = b.addModule("test", .{
 67            .root_source_file = b.path("src/test.zig"),
 68            .target = target,
 69            .optimize = optimize,
 70        });
 71        const test_dep = b.dependency("ghostty", .{
 72            .target = target,
 73            .optimize = optimize,
 74        });
 75        test_module.addImport(
 76            "ghostty-vt",
 77            test_dep.module("ghostty-vt"),
 78        );
 79        const exe_unit_tests = b.addTest(.{
 80            .root_module = test_module,
 81        });
 82        const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
 83        test_step.dependOn(&run_exe_unit_tests.step);
 84    }
 85
 86    // Integration tests (bats)
 87    {
 88        const integration_step = b.step("test-integration", "Run bats integration tests");
 89        const bats = b.addSystemCommand(&.{ "bats", "test/session.bats" });
 90        bats.step.dependOn(b.getInstallStep());
 91        integration_step.dependOn(&bats.step);
 92    }
 93
 94    // Check for LSP integration
 95    {
 96        const check = b.step("check", "Check if zmx compiles");
 97        const exe_check = b.addExecutable(.{
 98            .name = "zmx",
 99            .root_module = exe_mod,
100        });
101        exe_check.linkLibC();
102
103        // Finally we add the "check" step which will be detected
104        // by ZLS and automatically enable Build-On-Save.
105        // If you copy this into your `build.zig`, make sure to rename 'foo'
106        check.dependOn(&exe_check.step);
107    }
108
109    // Release step - cross-compile to all targets from any host
110    {
111        const release_step = b.step(
112            "release",
113            "Build release binaries for all platforms",
114        );
115        const release_targets = linux_targets ++ macos_targets;
116        for (release_targets) |release_target| {
117            const resolved = b.resolveTargetQuery(release_target);
118            const release_mod = b.createModule(.{
119                .root_source_file = b.path("src/main.zig"),
120                .target = resolved,
121                .optimize = .ReleaseSafe,
122            });
123            release_mod.addOptions("build_options", options);
124
125            if (b.lazyDependency("ghostty", .{
126                .target = resolved,
127                .optimize = .ReleaseSafe,
128            })) |release_dep| {
129                release_mod.addImport("ghostty-vt", release_dep.module("ghostty-vt"));
130            }
131
132            const release_exe = b.addExecutable(.{
133                .name = "zmx",
134                .root_module = release_mod,
135            });
136            release_exe.linkLibC();
137
138            const os_name = @tagName(release_target.os_tag orelse .linux);
139            const arch_name = @tagName(release_target.cpu_arch orelse .x86_64);
140            const tarball_name = b.fmt("zmx-{s}-{s}-{s}.tar.gz", .{ version, os_name, arch_name });
141
142            const tar = b.addSystemCommand(&.{ "tar", "--no-xattrs", "-czf" });
143
144            const tarball = tar.addOutputFileArg(tarball_name);
145            tar.addArg("-C");
146            tar.addDirectoryArg(release_exe.getEmittedBinDirectory());
147            tar.addArg("zmx");
148
149            const shasum = b.addSystemCommand(&.{ "shasum", "-a", "256" });
150            shasum.addFileArg(tarball);
151            const shasum_output = shasum.captureStdOut();
152
153            const install_tar = b.addInstallFile(tarball, b.fmt("dist/{s}", .{tarball_name}));
154            const install_sha = b.addInstallFile(
155                shasum_output,
156                b.fmt("dist/{s}.sha256", .{tarball_name}),
157            );
158            release_step.dependOn(&install_tar.step);
159            release_step.dependOn(&install_sha.step);
160        }
161    }
162
163    // Upload artifacts to pgs
164    {
165        const upload_step = b.step("upload", "Upload docs and dist to pgs.sh:/zmx");
166        const gen_doc = b.addSystemCommand(&.{ "sh", "-c", "cat README.md | pdocs -tmpl index.tmpl -toc | ssh pgs.sh /zmx/index.html" });
167        const rsync_docs = b.addSystemCommand(&.{ "rsync", "-v", "./logo.png", "pgs.sh:/zmx/" });
168        const rsync_dist = b.addSystemCommand(&.{ "rsync", "-rv", "zig-out/dist/", "pgs.sh:/zmx/a" });
169
170        upload_step.dependOn(&gen_doc.step);
171        upload_step.dependOn(&rsync_docs.step);
172        upload_step.dependOn(&rsync_dist.step);
173    }
174}