Something went wrong. Try again.
My version of https://github.com/vercel-labs/fx
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429const std = @import("std");
const UpdateChannel = enum { stable, dev };
const WasmSurface = enum { none, core, term,};
const PgsoArtifact = enum { fx, file_index, ui_activity, approval_review,};
const NapiSurface = enum { none, core,};
pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const pgso_artifact = b.option( PgsoArtifact, "pgso-artifact", "Emit ReleaseSafe LLVM bitcode for one PGO/PGSO artifact", ); const wasm_surface = b.option( WasmSurface, "wasm-surface", "Build a WASI WebAssembly surface for JavaScript hosts (core or term)", ) orelse .none; const napi_surface = b.option( NapiSurface, "napi-surface", "Build a Node-API addon surface (core)", ) orelse .none;
const git_commit = readGitCommit(b); const app_version = readAppVersion(b); const update_channel = b.option(UpdateChannel, "update-channel", "Build update channel (stable or dev)") orelse .stable;
const build_options = b.addOptions(); build_options.addOption([]const u8, "git_commit", git_commit); build_options.addOption([]const u8, "app_version", app_version); build_options.addOption([]const u8, "update_channel", @tagName(update_channel)); build_options.addOption(WasmSurface, "wasm_surface", .none);
const exe = b.addExecutable(.{ .name = "fx", .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .link_libc = true, .stack_check = false, .stack_protector = false, .omit_frame_pointer = true, .unwind_tables = .none, .error_tracing = false, .strip = optimize != .Debug, }), }); exe.root_module.addImport("build_options", build_options.createModule());
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(b.getInstallStep()); if (b.args) |args| { run_cmd.addArgs(args); }
const run_step = b.step("run", "Run fx"); run_step.dependOn(&run_cmd.step);
const exe_tests = b.addTest(.{ .root_module = exe.root_module, }); const run_exe_tests = b.addRunArtifact(exe_tests); run_exe_tests.step.dependOn(b.getInstallStep()); run_exe_tests.setEnvironmentVariable( "FX_TEST_PRODUCT_EXE", b.getInstallPath(.bin, "fx"), );
const test_step = b.step("test", "Run tests"); test_step.dependOn(&run_exe_tests.step);
if (wasm_surface != .none) { addWasmArtifact(b, wasm_surface, git_commit, app_version, update_channel); } if (napi_surface != .none) { addNapiArtifact(b, napi_surface, target, git_commit, app_version, update_channel); }
const mcp_test_exports = b.createModule(.{ .root_source_file = b.path("src/mcp_test_exports.zig"), .target = target, .optimize = optimize, .link_libc = true, }); mcp_test_exports.addImport("build_options", build_options.createModule()); const mcp_dispatcher_e2e = b.addExecutable(.{ .name = "mcp-stdio-dispatcher-driver", .root_module = b.createModule(.{ .root_source_file = b.path( "tests/e2e/fixtures/mcp-stdio-dispatcher-driver.zig", ), .target = target, .optimize = optimize, .link_libc = true, }), }); mcp_dispatcher_e2e.root_module.addImport( "mcp_test_exports", mcp_test_exports, ); const run_mcp_dispatcher_e2e = b.addRunArtifact(mcp_dispatcher_e2e); if (b.args) |args| run_mcp_dispatcher_e2e.addArgs(args); const mcp_dispatcher_e2e_step = b.step( "run-mcp-stdio-dispatcher-e2e", "Run the MCP stdio dispatcher E2E driver", ); mcp_dispatcher_e2e_step.dependOn(&run_mcp_dispatcher_e2e.step);
// --- file_index search benchmark --- const benchmark_exports_mod = b.createModule(.{ .root_source_file = b.path("src/benchmark_exports.zig"), .target = target, .optimize = optimize, .link_libc = true, }); const file_index_bench = b.addExecutable(.{ .name = "file-index-bench", .root_module = b.createModule(.{ .root_source_file = b.path("benchmarks/file_index_bench.zig"), .target = target, .optimize = optimize, .link_libc = true, }), }); file_index_bench.root_module.addImport("file_index", benchmark_exports_mod); const install_bench = b.addInstallArtifact(file_index_bench, .{}); const bench_step = b.step("bench-file-index", "Build file_index search benchmark"); bench_step.dependOn(&install_bench.step);
const run_bench = b.addRunArtifact(file_index_bench); run_bench.step.dependOn(&install_bench.step); if (b.args) |args| run_bench.addArgs(args); const run_bench_step = b.step("run-bench-file-index", "Build and run file_index search benchmark"); run_bench_step.dependOn(&run_bench.step);
// --- UI activity progress benchmark --- const ui_activity_bench = b.addExecutable(.{ .name = "ui-activity-progress-bench", .root_module = b.createModule(.{ .root_source_file = b.path("benchmarks/activity_progress.zig"), .target = target, .optimize = optimize, .link_libc = true, }), }); ui_activity_bench.root_module.addImport( "benchmark_exports", benchmark_exports_mod, ); const install_ui_activity_bench = b.addInstallArtifact(ui_activity_bench, .{}); const ui_activity_bench_step = b.step( "bench-ui-activity", "Build the UI activity progress benchmark", ); ui_activity_bench_step.dependOn(&install_ui_activity_bench.step);
const run_ui_activity_bench = b.addRunArtifact(ui_activity_bench); run_ui_activity_bench.step.dependOn(&install_ui_activity_bench.step); const run_ui_activity_bench_step = b.step( "run-bench-ui-activity", "Build and run the UI activity progress benchmark", ); run_ui_activity_bench_step.dependOn(&run_ui_activity_bench.step);
const ui_activity_bench_tests = b.addTest(.{ .root_module = b.createModule(.{ .root_source_file = b.path("benchmarks/activity_progress.zig"), .target = target, .optimize = optimize, }), }); ui_activity_bench_tests.root_module.addImport( "benchmark_exports", benchmark_exports_mod, ); const run_ui_activity_bench_tests = b.addRunArtifact(ui_activity_bench_tests); test_step.dependOn(&run_ui_activity_bench_tests.step); const test_ui_activity_bench_step = b.step( "test-ui-activity-benchmark", "Run UI activity benchmark policy tests", ); test_ui_activity_bench_step.dependOn(&run_ui_activity_bench_tests.step);
// --- file-diff approval review benchmark --- const approval_review_bench = b.addExecutable(.{ .name = "approval-review-bench", .root_module = b.createModule(.{ .root_source_file = b.path("benchmarks/approval_review.zig"), .target = target, .optimize = optimize, .link_libc = true, }), }); approval_review_bench.root_module.addImport( "benchmark_exports", benchmark_exports_mod, ); const install_approval_review_bench = b.addInstallArtifact( approval_review_bench, .{}, ); const approval_review_bench_step = b.step( "bench-approval-review", "Build the file-diff approval review benchmark", ); approval_review_bench_step.dependOn(&install_approval_review_bench.step);
const run_approval_review_bench = b.addRunArtifact(approval_review_bench); run_approval_review_bench.step.dependOn(&install_approval_review_bench.step); if (b.args) |args| run_approval_review_bench.addArgs(args); const run_approval_review_bench_step = b.step( "run-bench-approval-review", "Build and run the file-diff approval review benchmark", ); run_approval_review_bench_step.dependOn(&run_approval_review_bench.step);
const approval_review_bench_tests = b.addTest(.{ .root_module = b.createModule(.{ .root_source_file = b.path("benchmarks/approval_review.zig"), .target = target, .optimize = optimize, }), }); approval_review_bench_tests.root_module.addImport( "benchmark_exports", benchmark_exports_mod, ); const run_approval_review_bench_tests = b.addRunArtifact( approval_review_bench_tests, ); const test_approval_review_bench_step = b.step( "test-approval-review-benchmark", "Run file-diff approval review benchmark qualification tests", ); test_approval_review_bench_step.dependOn( &run_approval_review_bench_tests.step, );
const pgso_ir_step = b.step( "pgso-ir", "Emit selected ReleaseSafe LLVM bitcode for PGO/PGSO qualification", ); if (pgso_artifact) |artifact| { const selected: *std.Build.Step.Compile = switch (artifact) { .fx => exe, .file_index => file_index_bench, .ui_activity => ui_activity_bench, .approval_review => approval_review_bench, }; const output_name = switch (artifact) { .fx => "pgso/fx.bc", .file_index => "pgso/file-index.bc", .ui_activity => "pgso/ui-activity.bc", .approval_review => "pgso/approval-review.bc", }; const install_ir = b.addInstallFile( selected.getEmittedLlvmBc(), output_name, ); pgso_ir_step.dependOn(&install_ir.step); } else { const missing_artifact = b.addFail( "pgso-ir requires -Dpgso-artifact", ); pgso_ir_step.dependOn(&missing_artifact.step); }}
fn addWasmArtifact( b: *std.Build, surface: WasmSurface, git_commit: []const u8, app_version: []const u8, update_channel: UpdateChannel,) void { const wasm_target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .wasi, }); const name = switch (surface) { .core => "fx-core", .term => "fx-term", .none => unreachable, }; const description = switch (surface) { .core => "Build the headless fx WebAssembly artifact", .term => "Build the terminal fx WebAssembly artifact", .none => unreachable, };
const wasm_options = b.addOptions(); wasm_options.addOption([]const u8, "git_commit", git_commit); wasm_options.addOption([]const u8, "app_version", app_version); wasm_options.addOption([]const u8, "update_channel", @tagName(update_channel)); wasm_options.addOption(WasmSurface, "wasm_surface", surface);
const wasm_root = switch (surface) { .core => "src/wasm_core_main.zig", .term => "src/wasm_term_main.zig", .none => unreachable, }; const wasm_exe = b.addExecutable(.{ .name = name, .root_module = b.createModule(.{ .root_source_file = b.path(wasm_root), .target = wasm_target, .optimize = .ReleaseSmall, .single_threaded = true, .link_libc = true, .stack_check = false, .stack_protector = false, .omit_frame_pointer = true, .unwind_tables = .none, .error_tracing = false, .strip = true, }), }); if (surface == .core) wasm_exe.stack_size = 1024 * 1024; wasm_exe.root_module.addImport("build_options", wasm_options.createModule());
const install_wasm = b.addInstallArtifact(wasm_exe, .{}); const wasm_step = b.step(name ++ "-wasm", description); wasm_step.dependOn(&install_wasm.step); b.getInstallStep().dependOn(&install_wasm.step);}
fn addNapiArtifact( b: *std.Build, surface: NapiSurface, target: std.Build.ResolvedTarget, git_commit: []const u8, app_version: []const u8, update_channel: UpdateChannel,) void { const napi_options = b.addOptions(); napi_options.addOption([]const u8, "git_commit", git_commit); napi_options.addOption([]const u8, "app_version", app_version); napi_options.addOption([]const u8, "update_channel", @tagName(update_channel)); napi_options.addOption(NapiSurface, "napi_surface", surface);
const root = switch (surface) { .core => "src/napi_core_main.zig", .none => unreachable, }; const lib = b.addLibrary(.{ .name = "libfx", .linkage = .dynamic, .root_module = b.createModule(.{ .root_source_file = b.path(root), .target = target, .optimize = .ReleaseSafe, .link_libc = true, .strip = true, }), }); lib.root_module.addImport("build_options", napi_options.createModule()); const node_include = b.option( []const u8, "node-include-dir", "Directory containing node_api.h for the N-API addon", ) orelse discoverNodeIncludeDir(b); lib.root_module.addSystemIncludePath(.{ .cwd_relative = node_include }); lib.linker_allow_shlib_undefined = true;
const install = b.addInstallArtifact(lib, .{ .dest_sub_path = "libfx.node" }); const step = b.step("libfx-napi", "Build the libfx Node-API core addon"); step.dependOn(&install.step); b.getInstallStep().dependOn(&install.step);}
fn discoverNodeIncludeDir(b: *std.Build) []const u8 { var code: u8 = 0; const out = b.runAllowFail( &.{ "node", "-p", "require('node:path').join(require('node:path').dirname(process.execPath), '..', 'include', 'node')" }, &code, .ignore, ) catch std.process.fatal("Node.js is required to locate node_api.h; pass -Dnode-include-dir=<path>", .{}); if (code != 0) std.process.fatal("could not locate node_api.h; pass -Dnode-include-dir=<path>", .{}); const trimmed = std.mem.trim(u8, out, " \t\r\n"); return b.allocator.dupe(u8, trimmed) catch std.process.fatal("could not allocate Node include path", .{});}
fn readGitCommit(b: *std.Build) []const u8 { var code: u8 = 0; const out = b.runAllowFail( &.{ "git", "rev-parse", "--short=12", "HEAD" }, &code, .ignore, ) catch return "unknown"; if (code != 0) return "unknown"; const trimmed = std.mem.trim(u8, out, " \t\r\n"); return b.allocator.dupe(u8, trimmed) catch "unknown";}
fn readAppVersion(b: *std.Build) []const u8 { const bytes = std.Io.Dir.cwd().readFileAlloc(b.graph.io, "src/main.zig", b.allocator, .limited(1024 * 1024)) catch @panic("could not read src/main.zig to resolve app version"); defer b.allocator.free(bytes);
const prefix = "pub const version = \""; const start = (std.mem.find(u8, bytes, prefix) orelse @panic("could not find pub const version in src/main.zig")) + prefix.len; const end_rel = std.mem.findScalar(u8, bytes[start..], '"') orelse @panic("could not parse pub const version in src/main.zig"); return b.allocator.dupe(u8, bytes[start .. start + end_rel]) catch @panic("could not allocate app version");}