const std = @import("std"); pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const strip = b.option(bool, "strip", "strip debug symbols from the relay") orelse false; const offline_replay = b.option(bool, "offline-replay", "enable bounded offline corpus replay") orelse false; const zat = b.dependency("zat", .{ .target = target, .optimize = optimize, }); const websocket = b.dependency("websocket", .{ .target = target, .optimize = optimize, }); const pg = b.dependency("pg", .{ .target = target, .optimize = optimize, }); const zkv = b.dependency("zkv", .{ .target = target, .optimize = optimize, }); if (b.option(bool, "migration-tools", "build the offline index migration rehearsal") orelse false) { const rocks = b.lazyDependency("migration_rocksdb", .{ .target = target, .optimize = optimize }) orelse return; const archive = b.option([]const u8, "migration-rocksdb-library", "reuse an archive built from the pinned RocksDB source"); const raw, const bindings = if (archive) |path| blk: { const headers = rocks.builder.dependency("rocksdb", .{}); const translated = b.addTranslateC(.{ .root_source_file = headers.path("include/rocksdb/c.h"), .target = target, .optimize = optimize }); const raw = b.createModule(.{ .root_source_file = translated.getOutput(), .target = target, .optimize = optimize, .link_libc = true, .link_libcpp = true }); raw.addObjectFile(.{ .cwd_relative = path }); const bindings = b.createModule(.{ .root_source_file = rocks.path("src/lib.zig"), .target = target, .optimize = optimize }); bindings.addImport("rocksdb", raw); break :blk .{ raw, bindings }; } else .{ rocks.module("rocksdb"), rocks.module("bindings") }; const module = b.createModule(.{ .root_source_file = b.path("src/index_migration.zig"), .target = target, .optimize = optimize, .link_libc = true, .link_libcpp = true, .imports = &.{ .{ .name = "zkv", .module = zkv.module("zkv") }, .{ .name = "zat", .module = zat.module("zat") }, .{ .name = "rocksdb", .module = bindings }, .{ .name = "rocksdb_c", .module = raw } }, }); const checks = b.addTest(.{ .root_module = module }); b.step("test-index-migration", "test exact conversion and mismatch detection").dependOn(&b.addRunArtifact(checks).step); const tool = b.addExecutable(.{ .name = "index-migration", .root_module = module }); b.step("index-migration", "install the isolated forward/reverse migration rehearsal").dependOn(&b.addInstallArtifact(tool, .{}).step); } const zio = b.dependency("zio", .{ .target = target, .optimize = optimize, }); // -Dbackend=zio swaps the std.Io implementation under the whole relay. // Both variants must compile from the same source; see docs/design.md. const backend = b.option(enum { threaded, zio }, "backend", "std.Io backend (default: threaded)") orelse .threaded; const backend_opts = b.addOptions(); backend_opts.addOption(bool, "use_zio", backend == .zio); const imports: []const std.Build.Module.Import = &.{ .{ .name = "zat", .module = zat.module("zat") }, .{ .name = "websocket", .module = websocket.module("websocket") }, .{ .name = "pg", .module = pg.module("pg") }, .{ .name = "zkv", .module = zkv.module("zkv") }, .{ .name = "zio", .module = zio.module("zio") }, .{ .name = "backend_config", .module = backend_opts.createModule() }, }; // embed build info (git SHA + optimize mode) for canary metric const build_options = b.addOptions(); build_options.addOption([]const u8, "git_sha", git_sha: { var code: u8 = 0; const result = b.runAllowFail(&.{ "git", "rev-parse", "--short", "HEAD" }, &code, .ignore); if (result) |output| { break :git_sha std.mem.trimEnd(u8, output, "\n \t"); } else |_| { break :git_sha "unknown"; } }); build_options.addOption([]const u8, "optimize", @tagName(optimize)); const use_gpa = b.option(bool, "use_gpa", "use GeneralPurposeAllocator for leak detection (slow)") orelse false; build_options.addOption(bool, "use_gpa", use_gpa); build_options.addOption(bool, "offline_replay", offline_replay); build_options.addOption(bool, "profile_stages", b.option(bool, "profile-stages", "measure live frame processing stages") orelse false); // relay executable const relay_mod = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .imports = imports, }); relay_mod.addImport("build_options", build_options.createModule()); if (offline_replay) { relay_mod.addImport("relay_corpus", b.createModule(.{ .root_source_file = b.path("src/internal/testing/relay_corpus.zig"), .target = target, .optimize = optimize, })); } relay_mod.link_libc = true; relay_mod.strip = strip; const relay = b.addExecutable(.{ .name = "zlay", .root_module = relay_mod, }); b.installArtifact(relay); b.step("relay", "install only the relay executable").dependOn(&b.addInstallArtifact(relay, .{}).step); const run_relay = b.addRunArtifact(relay); run_relay.addPassthruArgs(); const run_step = b.step("run", "run the relay"); run_step.dependOn(&run_relay.step); const proof_mod = b.createModule(.{ .root_source_file = b.path("src/proof_replay.zig"), .target = target, .optimize = optimize, .imports = imports, .link_libc = true, }); proof_mod.addImport("build_options", build_options.createModule()); const proof = b.addExecutable(.{ .name = "proof-replay", .root_module = proof_mod }); b.step("proof-replay", "install the offline captured-proof verifier").dependOn(&b.addInstallArtifact(proof, .{}).step); // conformance harness — runs the atmoq relay-conformance corpora through // the real decode + validation path (see src/conformance_main.zig) const conformance_mod = b.createModule(.{ .root_source_file = b.path("src/conformance_main.zig"), .target = target, .optimize = optimize, .imports = imports, }); conformance_mod.addImport("build_options", build_options.createModule()); conformance_mod.link_libc = true; const conformance = b.addExecutable(.{ .name = "conformance", .root_module = conformance_mod, }); b.installArtifact(conformance); const run_conformance = b.addRunArtifact(conformance); run_conformance.addPassthruArgs(); const conformance_step = b.step("conformance", "run the relay conformance harness"); conformance_step.dependOn(&run_conformance.step); const space_mod = b.createModule(.{ .root_source_file = b.path("src/index_space.zig"), .target = target, .optimize = optimize, .imports = imports, .link_libc = true, }); const space = b.addExecutable(.{ .name = "index-space", .root_module = space_mod }); b.step("index-space", "install the offline index space comparison").dependOn( &b.addInstallArtifact(space, .{}).step, ); const index_bench_mod = b.createModule(.{ .root_source_file = b.path("src/index_bench.zig"), .target = target, .optimize = optimize, .imports = imports, .link_libc = true, .link_libcpp = false, }); const index_bench = b.addExecutable(.{ .name = "index-bench", .root_module = index_bench_mod }); b.step("index-bench", "install the offline collection index benchmark").dependOn( &b.addInstallArtifact(index_bench, .{}).step, ); const corpus_mod = b.createModule(.{ .root_source_file = b.path("src/index_corpus.zig"), .target = target, .optimize = optimize, .imports = imports, .link_libc = true, .link_libcpp = false, }); const corpus = b.addExecutable(.{ .name = "index-corpus", .root_module = corpus_mod }); b.step("index-corpus", "install the offline captured-frame index replay").dependOn( &b.addInstallArtifact(corpus, .{}).step, ); const strip_load = b.option(bool, "strip-load", "strip debug information from the load harness") orelse false; const read_cost = b.addExecutable(.{ .name = "index-read-cost", .root_module = b.createModule(.{ .root_source_file = b.path("src/index_read_cost.zig"), .target = target, .optimize = optimize, .imports = imports, .link_libc = true, }), }); b.step("index-read-cost", "install the reader refresh and dispatch microcosm").dependOn(&b.addInstallArtifact(read_cost, .{}).step); const owner_cost = b.addExecutable(.{ .name = "index-owner-cost", .root_module = b.createModule(.{ .root_source_file = b.path("src/index_owner_cost.zig"), .target = target, .optimize = optimize, .imports = imports, .link_libc = true, }), }); b.step("index-owner-cost", "install the scheduled owner-handoff control").dependOn(&b.addInstallArtifact(owner_cost, .{}).step); const load_mod = b.createModule(.{ .strip = strip_load, .root_source_file = b.path("src/index_load.zig"), .target = target, .optimize = optimize, .imports = imports, .link_libc = true, .link_libcpp = false, }); const load = b.addExecutable(.{ .name = "index-load", .root_module = load_mod }); b.step("index-load", "install the fixed-arrival-rate collection index load test").dependOn( &b.addInstallArtifact(load, .{}).step, ); const recovery_mod = b.createModule(.{ .root_source_file = b.path("src/index_recovery.zig"), .target = target, .optimize = optimize, .imports = imports, .link_libc = true, .strip = strip_load, }); const recovery = b.addExecutable(.{ .name = "index-recovery", .root_module = recovery_mod }); b.step("index-recovery", "install the process-crash collection index recovery test").dependOn( &b.addInstallArtifact(recovery, .{}).step, ); const runtime_mod = b.createModule(.{ .strip = strip_load, .root_source_file = b.path("src/index_runtime.zig"), .target = target, .optimize = optimize, .imports = imports, .link_libc = true, }); const runtime_probe = b.addExecutable(.{ .name = "index-runtime", .root_module = runtime_mod }); b.step("index-runtime", "install the one-executor reader scheduling probe").dependOn( &b.addInstallArtifact(runtime_probe, .{}).step, ); // tests // tests — a single module rooted at src/ so every internal/ import resolves const test_step = b.step("test", "run unit tests"); const test_mod = b.createModule(.{ .root_source_file = b.path("src/tests.zig"), .target = target, .optimize = optimize, .imports = imports, }); test_mod.addImport("build_options", build_options.createModule()); test_mod.link_libc = true; const t = b.addTest(.{ .root_module = test_mod, }); test_step.dependOn(&b.addRunArtifact(t).step); const index_test_mod = b.createModule(.{ .root_source_file = b.path("src/index_tests.zig"), .target = target, .optimize = optimize, .imports = imports, .link_libc = true, }); const index_tests = b.addTest(.{ .root_module = index_test_mod }); b.step("test-index", "test collection index ownership, readers, maintenance, backfill and resync").dependOn(&b.addRunArtifact(index_tests).step); }