╭ build.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
1 const std = @import("std"); 2 3 pub fn build(b: *std.Build) void { 4 const xit_dep = b.dependency("xit", .{}); 5 const ansi_art = ansiArtModule(b); 6 7 // wasm 8 const wasm_exe = blk: { 9 const wasm_target = b.resolveTargetQuery(.{ 10 .cpu_arch = .wasm32, 11 .os_tag = .freestanding, 12 }); 13 14 const exe = b.addExecutable(.{ 15 .name = "haxy", 16 .root_module = b.createModule(.{ 17 .root_source_file = b.path("src/main_wasm.zig"), 18 .target = wasm_target, 19 .optimize = .ReleaseSmall, 20 }), 21 }); 22 exe.root_module.addImport("xit", xit_dep.module("xit")); 23 24 exe.entry = .disabled; 25 exe.rdynamic = true; 26 exe.import_memory = false; 27 exe.export_memory = true; 28 exe.stack_size = std.wasm.page_size * 8; 29 30 // start small and let the allocator grow on demand up to wasm32's 31 // architectural ceiling (65536 pages = 4 GiB) 32 const initial_pages = 16; 33 const max_pages = 65536; 34 exe.initial_memory = std.wasm.page_size * initial_pages; 35 exe.max_memory = std.wasm.page_size * max_pages; 36 37 const install_exe = b.addInstallArtifact(exe, .{}); 38 39 const wasm_step = b.step("wasm", "Generate the wasm"); 40 wasm_step.dependOn(&install_exe.step); 41 42 break :blk exe; 43 }; 44 45 const target = b.standardTargetOptions(.{}); 46 const optimize = b.standardOptimizeOption(.{}); 47 48 // main 49 { 50 const exe = b.addExecutable(.{ 51 .name = "haxy", 52 .root_module = b.createModule(.{ 53 .root_source_file = b.path("src/main.zig"), 54 .target = target, 55 // default to ReleaseSafe unless an explicit -Doptimize is passed 56 .optimize = if (b.user_input_options.contains("optimize")) optimize else .ReleaseSafe, 57 }), 58 .use_llvm = true, 59 }); 60 exe.root_module.addImport("xit", xit_dep.module("xit")); 61 exe.root_module.addImport("ansi_art", ansi_art); 62 exe.root_module.addAnonymousImport("haxy.wasm", .{ 63 .root_source_file = wasm_exe.getEmittedBin(), 64 }); 65 66 const install_exe = b.addInstallArtifact(exe, .{}); 67 b.getInstallStep().dependOn(&install_exe.step); 68 } 69 70 // test 71 { 72 const unit_tests = b.addTest(.{ 73 .root_module = b.createModule(.{ 74 .root_source_file = b.path("src/test.zig"), 75 .target = target, 76 .optimize = optimize, 77 }), 78 }); 79 unit_tests.root_module.addImport("xit", xit_dep.module("xit")); 80 unit_tests.root_module.addImport("ansi_art", ansi_art); 81 82 const run_unit_tests = b.addRunArtifact(unit_tests); 83 run_unit_tests.has_side_effects = true; 84 const test_step = b.step("test", "Run unit tests"); 85 test_step.dependOn(&run_unit_tests.step); 86 } 87 88 // module for using haxy as a library 89 // (the commands below consume haxy this way) 90 const haxy = b.addModule("haxy", .{ 91 .root_source_file = b.path("src/lib.zig"), 92 }); 93 haxy.addImport("xit", xit_dep.module("xit")); 94 haxy.addImport("ansi_art", ansi_art); 95 haxy.addAnonymousImport("haxy.wasm", .{ 96 .root_source_file = wasm_exe.getEmittedBin(), 97 }); 98 99 // try 100 { 101 const exe = b.addExecutable(.{ 102 .name = "try", 103 .root_module = b.createModule(.{ 104 .root_source_file = b.path("src/try.zig"), 105 .target = target, 106 .optimize = optimize, 107 }), 108 }); 109 exe.root_module.addImport("haxy", haxy); 110 const try_install = b.addInstallArtifact(exe, .{}); 111 112 const run_cmd = b.addRunArtifact(exe); 113 run_cmd.step.dependOn(&try_install.step); 114 if (b.args) |args| { 115 run_cmd.addArgs(args); 116 } 117 118 const run_step = b.step("try", "Try the app"); 119 run_step.dependOn(&run_cmd.step); 120 } 121 122 // testnet 123 { 124 const server_exe = b.addExecutable(.{ 125 .name = "haxy", 126 .root_module = b.createModule(.{ 127 .root_source_file = b.path("src/main.zig"), 128 .target = target, 129 .optimize = .Debug, 130 }), 131 .use_llvm = true, 132 }); 133 server_exe.root_module.addImport("xit", xit_dep.module("xit")); 134 server_exe.root_module.addImport("ansi_art", ansi_art); 135 server_exe.root_module.addAnonymousImport("haxy.wasm", .{ 136 .root_source_file = wasm_exe.getEmittedBin(), 137 }); 138 const install_server_exe = b.addInstallArtifact(server_exe, .{}); 139 140 const unit_tests = b.addTest(.{ 141 .root_module = b.createModule(.{ 142 .root_source_file = b.path("src/testnet.zig"), 143 .target = target, 144 .optimize = optimize, 145 }), 146 }); 147 unit_tests.root_module.addImport("haxy", haxy); 148 149 const run_unit_tests = b.addRunArtifact(unit_tests); 150 run_unit_tests.has_side_effects = true; 151 run_unit_tests.step.dependOn(&install_server_exe.step); 152 const test_step = b.step("testnet", "Run network unit tests"); 153 test_step.dependOn(&run_unit_tests.step); 154 } 155 } 156 157 // reads every ANSI-art text file while configuring the build. sorting keeps 158 // the generated module stable when directory iteration order changes. 159 fn ansiArtModule(b: *std.Build) *std.Build.Module { 160 const io = b.graph.io; 161 var dir = b.build_root.handle.openDir(io, "src/embed/ansi", .{ .iterate = true }) catch |err| { 162 std.debug.panic("unable to open src/embed/ansi: {t}", .{err}); 163 }; 164 defer dir.close(io); 165 166 var names: std.ArrayList([]const u8) = .empty; 167 var iter = dir.iterate(); 168 while (iter.next(io) catch |err| std.debug.panic("unable to read src/embed/ansi: {t}", .{err})) |entry| { 169 if (entry.kind != .file or !std.mem.endsWith(u8, entry.name, ".txt")) continue; 170 names.append(b.allocator, b.dupe(entry.name)) catch @panic("OOM"); 171 } 172 std.mem.sort([]const u8, names.items, {}, struct { 173 fn lessThan(_: void, lhs: []const u8, rhs: []const u8) bool { 174 return std.mem.order(u8, lhs, rhs) == .lt; 175 } 176 }.lessThan); 177 if (names.items.len == 0) @panic("src/embed/ansi must contain at least one .txt file"); 178 179 const contents = b.allocator.alloc([]const u8, names.items.len) catch @panic("OOM"); 180 for (names.items, contents) |name, *content| { 181 content.* = dir.readFileAlloc(io, name, b.allocator, .limited(16 * 1024 * 1024)) catch |err| { 182 std.debug.panic("unable to read src/embed/ansi/{s}: {t}", .{ name, err }); 183 }; 184 } 185 186 const options = b.addOptions(); 187 options.addOption([]const []const u8, "art", contents); 188 return options.createModule(); 189 } 190