diff options
Diffstat (limited to 'build.zig')
| -rw-r--r-- | build.zig | 306 |
1 files changed, 103 insertions, 203 deletions
@@ -9,7 +9,6 @@ pub const Platform = enum { tty, gui, web }; /// which fails on a fetched package that has no .git) and to `SPC l i`. const zls_version = "0.16.1-dev+3e0d0820"; pub const TreeSitterGrammars = enum { disabled, zig, minimal, full }; -const GhosttyArtifact = enum { ghostty, lib }; pub fn build(b: *std.Build) void { // Default target is the Steam Deck (deckcap's trick): x86_64 linux-gnu @@ -27,10 +26,10 @@ pub fn build(b: *std.Build) void { const platform = b.option(Platform, "platform", "which shell to build (tty, gui, web)") orelse .tty; const static = b.option(bool, "static", "statically link") orelse false; const dump_path = b.option([]const u8, "dump", "dump .zon embedded into the web shell (-Dplatform=web)"); - const emcc_path = b.option([]const u8, "emcc", "emcc for the web shell's final link") orelse "/usr/lib/emscripten/emcc"; - const is_emscripten = target.result.os.tag == .emscripten; + const is_web = platform == .web; + const is_web_target = target.result.cpu.arch == .wasm32 and target.result.os.tag == .freestanding; // wasm: size is the budget - const optimize = if (is_emscripten) .ReleaseSmall else requested_optimize; + const optimize = if (is_web) .ReleaseSmall else requested_optimize; // The vendored C is never what we are debugging, and at -O0 it dominates // the app: 90% of a Debug startup is tree-sitter's query analyser // (perf: ts_query__perform_analysis + ts_lookahead_iterator__next), and @@ -38,12 +37,16 @@ pub fn build(b: *std.Build) void { // mode takes a Debug boot from ~710ms to ~210ms — the same treatment // ghostty's simdutf/highway already get here. Zig code keeps its mode. const c_optimize: std.builtin.OptimizeMode = if (optimize == .Debug) .ReleaseFast else optimize; - const default_grammars: TreeSitterGrammars = if (is_emscripten) .zig else .full; + // The browser keeps its useful default grammar without acquiring a host + // libc contract: Tree-sitter and the generated Zig parser are linked into + // the freestanding module against src/web/libc's tiny in-module shim. + const default_grammars: TreeSitterGrammars = if (is_web) .zig else .full; const tree_sitter_grammars = b.option(TreeSitterGrammars, "tree-sitter", "tree-sitter grammar set: disabled, zig, minimal (c/c++/zig), full") orelse default_grammars; const tracy = b.option([]const u8, "tracy", "enable Tracy profiling; supply the path to a Tracy source checkout"); - // the browser shell: zig object + emcc link + html, installed to zig-out/web - const web_step = b.step("web", "build the browser shell into zig-out/web (-Dplatform=web -Dtarget=wasm32-emscripten -Ddump=<dump.zon>)"); + // The browser shell is a freestanding wasm core plus ordinary web files. + // JavaScript owns the loop and IO; HTML/CSS own rendering. + const web_step = b.step("web", "build the DOM browser shell into zig-out/web (-Dplatform=web -Dtarget=wasm32-freestanding -Ddump=<dump.zon>)"); // Web LOOK has a tiny read-only source filesystem. Generate one Zig module // on the host from every tracked .zig path + its current working-tree @@ -68,30 +71,9 @@ pub fn build(b: *std.Build) void { snap_build.addWeb(b); - const emscripten_sysroot = if (is_emscripten) detectEmscriptenSysroot(b) else null; - if (platform == .web and !is_emscripten) return failBuild(b, web_step, "-Dplatform=web requires -Dtarget=wasm32-emscripten"); - if (platform != .web and is_emscripten) return failBuild(b, web_step, "-Dtarget=wasm32-emscripten requires -Dplatform=web"); + if (is_web and !is_web_target) return failBuild(b, web_step, "-Dplatform=web requires -Dtarget=wasm32-freestanding"); + if (!is_web and (is_web_target or target.result.os.tag == .emscripten)) return failBuild(b, web_step, "wasm browser targets require -Dplatform=web"); if (platform == .web and dump_path == null) return failBuild(b, web_step, "-Dplatform=web requires -Ddump=<dump.zon> (the browser has no ptys; state replays from an embedded dump)"); - if (platform == .web and emscripten_sysroot == null) return failBuild(b, web_step, "no emscripten sysroot found; pass --sysroot <emscripten-cache>/sysroot or set EM_CACHE/EMSDK"); - - // emscripten "libc": point zig at the sysroot headers/crt via a libc.txt - // (the prototype's WriteFiles trick) — applied to EVERY compile step. - const libc_file: ?std.Build.LazyPath = if (emscripten_sysroot) |sysroot| blk: { - const files = b.addWriteFiles(); - break :blk files.add("emscripten-libc.txt", b.fmt( - \\include_dir={s}/include - \\sys_include_dir={s}/include - \\crt_dir={s}/lib/wasm32-emscripten - \\msvc_lib_dir= - \\kernel32_lib_dir= - \\gcc_dir= - \\ - , .{ sysroot, sysroot, sysroot })); - } else null; - const emscripten_include: ?std.Build.LazyPath = if (emscripten_sysroot) |sysroot| - .{ .cwd_relative = b.pathJoin(&.{ sysroot, "include" }) } - else - null; // build-time IO: slurps the grammars' highlights.scm queries, and reads // vendor/themes to find the theme sources @@ -102,8 +84,8 @@ pub fn build(b: *std.Build) void { const root_mod = b.createModule(.{ .target = target, .optimize = optimize, - .root_source_file = b.path("src/main.zig"), - .link_libc = true, + .root_source_file = b.path(if (is_web) "src/web.zig" else "src/main.zig"), + .link_libc = !is_web, }); // helix differential harness (test/hxdiff.zig): a second compilation of // the sans-IO core, driven headlessly. Mirrors root_mod's wiring for @@ -150,19 +132,16 @@ pub fn build(b: *std.Build) void { root_mod.addImport("generated_themes", themes_mod); hx_core_mod.addImport("generated_themes", themes_mod); - // static archives the emcc link needs beyond the zig object (grammars, SDL) - var wasm_libs: std.ArrayList(std.Build.LazyPath) = .empty; - // forkpty: in libc proper on glibc>=2.34 and darwin; the BSDs keep it in libutil if (target.result.os.tag == .freebsd or target.result.os.tag == .netbsd or target.result.os.tag == .openbsd) root_mod.linkSystemLibrary("util", .{}); // The language backend (src/lsp/lsp_zls.zig) links ZLS as a MODULE — no zls // binary, no JSON-RPC, no protocol. Everything except the browser gets it; - // emscripten does not, because the web shell has no threads and no-ops the + // the web shell does not, because it has no threads and no-ops the // lsp effect anyway, so paying to compile an analyser it can never call // would be pure wasm. - const zls_backend = !is_emscripten; + const zls_backend = !is_web; const opts = b.addOptions(); opts.addOption(Platform, "platform", platform); @@ -236,16 +215,26 @@ pub fn build(b: *std.Build) void { // ts_queries options module (codegen consumed by comptime in syntax.zig). if (tree_sitter_grammars != .disabled) { const tree_sitter_mod = b.dependency("tree_sitter", .{ .target = target, .optimize = c_optimize }).module("tree_sitter"); - // the C runtime rides the module as a static lib; give it the wasm - // libc and hand its archive to the emcc link - if (is_emscripten) { + if (is_web) { + // zig-tree-sitter carries its C runtime as a linked static library. + // Retarget that library away from libc and put the compatibility + // headers before any unavailable freestanding system headers. + const web_libc_include: std.Build.LazyPath = .{ + .cwd_relative = b.path("src/web/libc/include").getPath(b), + }; for (tree_sitter_mod.link_objects.items) |link_object| switch (link_object) { .other_step => |lib| { - lib.setLibCFile(libc_file.?); - wasm_libs.append(b.allocator, lib.getEmittedBin()) catch @panic("OOM"); + lib.root_module.link_libc = false; + lib.root_module.addIncludePath(web_libc_include); + lib.root_module.addCMacro("NDEBUG", "1"); }, else => {}, }; + root_mod.addIncludePath(b.path("src/web/libc/include")); + root_mod.addCSourceFile(.{ + .file = b.path("src/web/libc.c"), + .flags = &.{ "-std=c11", "-DNDEBUG=1" }, + }); } root_mod.addImport("tree-sitter", tree_sitter_mod); hx_core_mod.addImport("tree-sitter", tree_sitter_mod); @@ -299,10 +288,9 @@ pub fn build(b: *std.Build) void { const lib = b.addLibrary(.{ .name = "tree-sitter-" ++ g.name, - .root_module = b.createModule(.{ .target = target, .optimize = c_optimize, .link_libc = true }), + .root_module = b.createModule(.{ .target = target, .optimize = c_optimize, .link_libc = !is_web }), .linkage = .static, }); - if (libc_file) |f| lib.setLibCFile(f); // grammars declare external_scanner_create() with EMPTY PARENS // (a K&R non-prototype, not (void)): under clang's // -fsanitize=function the callee's type hash differs from the @@ -315,19 +303,26 @@ pub fn build(b: *std.Build) void { lib.root_module.addCSourceFile(.{ .file = dep.path(g.src ++ "/parser.c"), .flags = &ts_cflags }); if (g.scanner) lib.root_module.addCSourceFile(.{ .file = dep.path(g.src ++ "/scanner.c"), .flags = &ts_cflags }); lib.root_module.addIncludePath(dep.path(g.src)); + if (is_web) lib.root_module.addIncludePath(b.path("src/web/libc/include")); root_mod.linkLibrary(lib); hx_core_mod.linkLibrary(lib); - if (is_emscripten) wasm_libs.append(b.allocator, lib.getEmittedBin()) catch @panic("OOM"); } } root_mod.addOptions("ts_queries", ts_queries); hx_core_mod.addOptions("ts_queries", ts_queries); } - // zstbi (C stb_image): image pane decode. zigimg crashes the 0.16 compiler. - const zstbi_dep = b.dependency("zstbi", .{ .target = target, .optimize = c_optimize }); - root_mod.addImport("zstbi", zstbi_dep.module("root")); - hx_core_mod.addImport("zstbi", zstbi_dep.module("root")); + // zstbi (C stb_image): image pane decode. The freestanding core has no C + // allocator ABI, so its module is a compatible no-decode shim; browser IO + // can grow native image decoding independently of the core. + const zstbi_dep = if (!is_web) b.dependency("zstbi", .{ .target = target, .optimize = c_optimize }) else null; + const zstbi_mod = if (zstbi_dep) |dep| dep.module("root") else b.createModule(.{ + .target = target, + .optimize = optimize, + .root_source_file = b.path("src/web/zstbi.zig"), + }); + root_mod.addImport("zstbi", zstbi_mod); + hx_core_mod.addImport("zstbi", zstbi_mod); // mvzr: the regex engine behind `s` / `S` (helix select/split on a regex). // A bytecode VM that compiles a RUNTIME pattern into a fixed-size struct @@ -353,11 +348,11 @@ pub fn build(b: *std.Build) void { .tables_path = uucode_tables, }).module("uucode"); - const vaxis_mod = b.dependency("vaxis", .{ + const vaxis_mod: ?*std.Build.Module = if (!is_web) b.dependency("vaxis", .{ .target = target, .optimize = optimize, .external_uucode = true, - }).module("vaxis"); + }).module("vaxis") else null; var ghostty_vt_for_snap: ?*std.Build.Module = null; // ghostty's simd libs (simdutf/highway, C++) locate the Apple SDK via @@ -379,7 +374,7 @@ pub fn build(b: *std.Build) void { // without it); gate that block on `b.graph.host.result.os.tag == .linux`. // Ghostty's pinned translate-c tarball also 404s now (codeberg dropped // the archive endpoint) — seed zig-pkg/ from a machine that has it. - const ghostty_simd = !target.result.os.tag.isDarwin() or b.graph.host.result.os.tag.isDarwin(); + const ghostty_simd = !is_web and (!target.result.os.tag.isDarwin() or b.graph.host.result.os.tag.isDarwin()); // app-runtime none + emit-xcframework off: only the ghostty-vt module is // consumed, and the defaults otherwise drag ghostty's app graph into the // build — gtk4 header translation via host pkg-config for linux targets, @@ -394,39 +389,19 @@ pub fn build(b: *std.Build) void { // own safety checks come from OUR optimize mode and are unaffected, since // ghostty-vt is a module compiled into this binary. See reflow.snap. const ghostty_optimize: std.builtin.OptimizeMode = if (optimize == .Debug) .ReleaseSafe else optimize; - const ghostty_dep = if (is_emscripten) - b.lazyDependency("ghostty", .{ .simd = false }) - else - b.lazyDependency("ghostty", .{ .target = target, .optimize = ghostty_optimize, .simd = ghostty_simd, .@"app-runtime" = .none, .@"emit-xcframework" = false }); + const ghostty_dep = b.lazyDependency("ghostty", .{ .target = target, .optimize = ghostty_optimize, .simd = ghostty_simd, .@"app-runtime" = .none, .@"emit-xcframework" = false }); if (ghostty_dep) |dep| { const ghostty_vt = dep.module("ghostty-vt"); ghostty_vt_for_snap = ghostty_vt; ghostty_vt.addImport("uucode", uucode_mod); - // emscripten: hand ghostty-vt the terminal_options module its build() - // would otherwise provide (copied verbatim from the prototype build) - if (is_emscripten) { - const term_opts = b.addOptions(); - term_opts.addOption(GhosttyArtifact, "artifact", .lib); - term_opts.addOption(bool, "c_abi", false); - term_opts.addOption(bool, "oniguruma", false); - term_opts.addOption(bool, "simd", false); - term_opts.addOption(bool, "slow_runtime_safety", false); - term_opts.addOption(bool, "kitty_graphics", false); - term_opts.addOption(bool, "tmux_control_mode", false); - term_opts.addOption([]const u8, "version_string", "0.0.0"); - term_opts.addOption(usize, "version_major", 0); - term_opts.addOption(usize, "version_minor", 0); - term_opts.addOption(usize, "version_patch", 0); - term_opts.addOption(?[]const u8, "version_pre", null); - term_opts.addOption(?[]const u8, "version_build", null); - ghostty_vt.addOptions("terminal_options", term_opts); - } root_mod.addImport("ghostty-vt", ghostty_vt); hx_core_mod.addImport("ghostty-vt", ghostty_vt); } // override uucode on vaxis LAST so it wins over ghostty's build() wiring. - vaxis_mod.addImport("uucode", uucode_mod); - root_mod.addImport("vaxis", vaxis_mod); + if (vaxis_mod) |vaxis| { + vaxis.addImport("uucode", uucode_mod); + root_mod.addImport("vaxis", vaxis); + } root_mod.addImport("uucode", uucode_mod); hx_core_mod.addImport("uucode", uucode_mod); @@ -467,29 +442,22 @@ pub fn build(b: *std.Build) void { root_mod.addOptions("pardes_config", opts); hx_core_mod.addOptions("pardes_config", opts); - // SDL3 shell wiring (-Dplatform=gui and web). The sdl package builds SDL3 + // SDL3 shell wiring (-Dplatform=gui). The sdl package builds SDL3 // from source as a static lib + emits the SDL3/ headers; gui.zig @cImports // those, plus a small stb_truetype C shim for the glyph atlas, and embeds - // the SPIR-V compiled at build time from shaders/*.glsl — or, on web, the - // GL ES shader sources compiled at runtime by WebGL. - if (platform == .gui or platform == .web) { + // the SPIR-V compiled at build time from shaders/*.glsl. + if (platform == .gui) { // sanitize_c MUST stay off: zig cc's UBSan (on for C in Debug AND // ReleaseSafe) traps hidapi's mismatched fn-pointer calls the moment // a HID gamepad is enumerated — SDL_Init SIGILLs on the deck itself // (ud2 in SDL_hid_set_nonblocking_REAL); headless boxes never see it. // SDL3 always statically linked (like deckcap): the gui binary must // only need system libc/libm — never a shared libSDL3. - const sdl_dep = if (emscripten_include) |include| - b.lazyDependency("sdl", .{ .target = target, .optimize = optimize, .sanitize_c = .off, .preferred_linkage = .static, .system_include_path = include }) - else - b.lazyDependency("sdl", .{ .target = target, .optimize = optimize, .sanitize_c = .off, .preferred_linkage = .static }); + const sdl_dep = b.lazyDependency("sdl", .{ .target = target, .optimize = optimize, .sanitize_c = .off, .preferred_linkage = .static }); if (sdl_dep) |dep| { const sdl_lib = dep.artifact("SDL3"); - if (libc_file) |f| sdl_lib.setLibCFile(f); root_mod.linkLibrary(sdl_lib); root_mod.addIncludePath(dep.path("include")); - if (emscripten_include) |include| root_mod.addSystemIncludePath(include); - if (is_emscripten) wasm_libs.append(b.allocator, sdl_lib.getEmittedBin()) catch @panic("OOM"); } // darwin: SDL_GPU only speaks SPIRV here (shaders/*.glsl -> glslc), so // it must pick its vulkan backend via the Vulkan SDK's loader + @@ -505,71 +473,56 @@ pub fn build(b: *std.Build) void { root_mod.addAnonymousImport("AdwaitaMono-Regular.ttf", .{ .root_source_file = b.path("assets/AdwaitaMono-Regular.ttf"), }); - if (platform == .web) { - root_mod.addAnonymousImport("ui.vert.es.glsl", .{ .root_source_file = b.path("shaders/ui.vert.es.glsl") }); - root_mod.addAnonymousImport("ui.frag.es.glsl", .{ .root_source_file = b.path("shaders/ui.frag.es.glsl") }); - root_mod.addAnonymousImport("overlay.vert.es.glsl", .{ .root_source_file = b.path("shaders/overlay.vert.es.glsl") }); - root_mod.addAnonymousImport("overlay.frag.es.glsl", .{ .root_source_file = b.path("shaders/overlay.frag.es.glsl") }); - const dp = dump_path.?; - root_mod.addAnonymousImport("embedded.dump.zon", .{ - .root_source_file = if (std.fs.path.isAbsolute(dp)) .{ .cwd_relative = dp } else b.path(dp), - }); - root_mod.addAnonymousImport("embedded_sources", .{ .root_source_file = embedded_sources }); - } else { - root_mod.addAnonymousImport("ui.vert.spv", .{ - .root_source_file = compileGlsl(b, "shaders/ui.vert.glsl", "vertex", "ui.vert.spv"), - }); - root_mod.addAnonymousImport("ui.frag.spv", .{ - .root_source_file = compileGlsl(b, "shaders/ui.frag.glsl", "fragment", "ui.frag.spv"), - }); - root_mod.addAnonymousImport("overlay.vert.spv", .{ - .root_source_file = compileGlsl(b, "shaders/overlay.vert.glsl", "vertex", "overlay.vert.spv"), - }); - root_mod.addAnonymousImport("overlay.frag.spv", .{ - .root_source_file = compileGlsl(b, "shaders/overlay.frag.glsl", "fragment", "overlay.frag.spv"), - }); - root_mod.addAnonymousImport("crt.vert.spv", .{ - .root_source_file = compileGlsl(b, "shaders/crt.vert.glsl", "vertex", "crt.vert.spv"), - }); - root_mod.addAnonymousImport("crt.frag.spv", .{ - .root_source_file = compileGlsl(b, "shaders/crt.frag.glsl", "fragment", "crt.frag.spv"), - }); - } + root_mod.addAnonymousImport("ui.vert.spv", .{ + .root_source_file = compileGlsl(b, "shaders/ui.vert.glsl", "vertex", "ui.vert.spv"), + }); + root_mod.addAnonymousImport("ui.frag.spv", .{ + .root_source_file = compileGlsl(b, "shaders/ui.frag.glsl", "fragment", "ui.frag.spv"), + }); + root_mod.addAnonymousImport("overlay.vert.spv", .{ + .root_source_file = compileGlsl(b, "shaders/overlay.vert.glsl", "vertex", "overlay.vert.spv"), + }); + root_mod.addAnonymousImport("overlay.frag.spv", .{ + .root_source_file = compileGlsl(b, "shaders/overlay.frag.glsl", "fragment", "overlay.frag.spv"), + }); + root_mod.addAnonymousImport("crt.vert.spv", .{ + .root_source_file = compileGlsl(b, "shaders/crt.vert.glsl", "vertex", "crt.vert.spv"), + }); + root_mod.addAnonymousImport("crt.frag.spv", .{ + .root_source_file = compileGlsl(b, "shaders/crt.frag.glsl", "fragment", "crt.frag.spv"), + }); + } + + if (is_web) { + const dp = dump_path.?; + root_mod.addAnonymousImport("embedded.dump.zon", .{ + .root_source_file = if (std.fs.path.isAbsolute(dp)) .{ .cwd_relative = dp } else b.path(dp), + }); + root_mod.addAnonymousImport("embedded_sources", .{ .root_source_file = embedded_sources }); } if (platform == .web) { - // zig emits an object; emcc does the final link (wasm + js glue), - // compiling the C shims itself and pulling in every static archive. - const obj = b.addObject(.{ .name = "pardes", .root_module = root_mod }); - obj.setLibCFile(libc_file.?); + const wasm = b.addExecutable(.{ .name = "pardes", .root_module = root_mod }); + wasm.entry = .disabled; + wasm.rdynamic = true; + wasm.export_memory = true; + // The full grammar tier carries ~48 MiB of generated parse tables. + // Keep the compact default at 32 MiB, but leave enough static address + // space for an explicitly requested all-language build to link. + wasm.initial_memory = @as(u64, if (tree_sitter_grammars == .full) 64 else 32) * 1024 * 1024; + wasm.max_memory = 512 * 1024 * 1024; + web_step.dependOn(&b.addInstallFileWithDir(wasm.getEmittedBin(), .{ .custom = "web" }, "pardes.wasm").step); + inline for (.{ + .{ "src/web/index.html", "index.html" }, + .{ "src/web/app.mjs", "app.mjs" }, + .{ "src/web/pardes.css", "pardes.css" }, + .{ "assets/AdwaitaMono-Regular.ttf", "AdwaitaMono-Regular.ttf" }, + }) |file| web_step.dependOn(&b.addInstallFileWithDir(b.path(file[0]), .{ .custom = "web" }, file[1]).step); - const emcc = b.addSystemCommand(&.{emcc_path}); - emcc.addFileArg(obj.getEmittedBinDirectory().path(b, "pardes_zcu.o")); - emcc.addFileArg(obj.getEmittedBin()); - emcc.addFileArg(b.path("vendor/stb/stb_truetype_impl.c")); - emcc.addFileArg(b.path("vendor/stb/font.c")); - emcc.addFileArg(zstbi_dep.path("src/zstbi.c")); - for (wasm_libs.items) |lib| emcc.addFileArg(lib); - emcc.addPrefixedDirectoryArg("-I", b.path("vendor/stb")); - emcc.addPrefixedDirectoryArg("-I", zstbi_dep.path("libs/stbi")); - emcc.addArgs(&.{ - "-std=c99", - "-fno-sanitize=undefined", - "-Oz", - "-sINITIAL_MEMORY=1073741824", // the 512 MiB web heap + code/stack - "-sEXIT_RUNTIME=0", // run() returns; the rAF loop keeps living - "-sFULL_ES3=1", - "-sMIN_WEBGL_VERSION=2", - "-sMAX_WEBGL_VERSION=2", - "-sINCOMING_MODULE_JS_API=canvas", - "-sEXPORTED_FUNCTIONS=['_main','_pardes_web_test_cols','_pardes_web_test_rows','_pardes_web_test_cursor_x','_pardes_web_test_cursor_y','_pardes_web_test_cell','_pardes_web_test_cell_fg','_pardes_web_test_cell_bg','_pardes_web_test_cell_attrs','_pardes_web_test_cell_x','_pardes_web_test_cell_y']", - "-o", - }); - const js = emcc.addOutputFileArg("pardes.js"); - web_step.dependOn(&b.addInstallFileWithDir(js, .{ .custom = "web" }, "pardes.js").step); - web_step.dependOn(&b.addInstallFileWithDir(js.dirname().path(b, "pardes.wasm"), .{ .custom = "web" }, "pardes.wasm").step); - const html = b.addWriteFiles().add("index.html", html_shell); - web_step.dependOn(&b.addInstallFileWithDir(html, .{ .custom = "web" }, "index.html").step); + const run_web_harness = b.addSystemCommand(&.{ "node", "test/web_harness.mjs" }); + run_web_harness.addArg(b.getInstallPath(.{ .custom = "web" }, "")); + run_web_harness.step.dependOn(web_step); + b.step("web-harness", "run the dependency-free JS/WASM DOM harness").dependOn(&run_web_harness.step); b.getInstallStep().dependOn(web_step); } else { // binary name: the native-shaped linux-x86_64 tty build stays `pardes` @@ -587,7 +540,7 @@ pub fn build(b: *std.Build) void { b.installArtifact(exe); const run = b.addRunArtifact(exe); b.step("run", "descend to the pardes").dependOn(&run.step); - web_step.dependOn(&b.addFail("web needs -Dplatform=web -Dtarget=wasm32-emscripten -Ddump=<dump.zon>").step); + web_step.dependOn(&b.addFail("web needs -Dplatform=web -Dtarget=wasm32-freestanding -Ddump=<dump.zon>").step); // snapshot parity suite: scripted input traces in a pty, captured grids // diffed against the goldens in snapshots/ — the frozen record of parity @@ -736,45 +689,6 @@ pub fn build(b: *std.Build) void { } } -// the html shell: a full-viewport canvas wired into Module (from the prototype) -const html_shell = - \\<!doctype html> - \\<html> - \\<head> - \\ <meta charset="utf-8"> - \\ <meta name="viewport" content="width=device-width, initial-scale=1"> - \\ <title>pardes</title> - \\ <style> - \\ html, body { margin: 0; width: 100%; height: 100%; background: #121212; } - \\ body { overflow: hidden; } - \\ canvas { display: block; width: 100vw; height: 100vh; outline: none; - \\ image-rendering: crisp-edges; image-rendering: pixelated; - \\ -ms-interpolation-mode: nearest-neighbor; - \\ transform: translateZ(0); backface-visibility: hidden; - \\ touch-action: none; } - \\ </style> - \\</head> - \\<body> - \\ <canvas id="canvas" tabindex="0"></canvas> - \\ <script> - \\ const canvas = document.getElementById('canvas'); - \\ canvas.addEventListener('contextmenu', (event) => event.preventDefault()); - \\ canvas.addEventListener('pointerdown', (event) => { - \\ canvas.focus({ preventScroll: true }); - \\ canvas.setPointerCapture?.(event.pointerId); - \\ }); - \\ const releasePointer = (event) => { - \\ if (canvas.hasPointerCapture?.(event.pointerId)) canvas.releasePointerCapture(event.pointerId); - \\ }; - \\ canvas.addEventListener('pointerup', releasePointer); - \\ canvas.addEventListener('pointercancel', releasePointer); - \\ window.Module = { canvas }; - \\ </script> - \\ <script src="pardes.js"></script> - \\</body> - \\</html> -; - // a bad -D combination: fail both `zig build` and `zig build web` with the why fn failBuild(b: *std.Build, web_step: *std.Build.Step, msg: []const u8) void { const fail = &b.addFail(msg).step; @@ -812,17 +726,3 @@ fn vendoredThemes(b: *std.Build, io: std.Io) []const []const u8 { }.lt); return names.items; } - -fn detectEmscriptenSysroot(b: *std.Build) ?[]const u8 { - if (b.option([]const u8, "emscripten-sysroot", "path to the Emscripten sysroot")) |path| return path; - if (b.sysroot) |path| return path; - if (envPath(b, "EMSCRIPTEN_SYSROOT")) |path| return path; - if (envPath(b, "EM_CACHE")) |cache| return b.pathJoin(&.{ cache, "sysroot" }); - if (envPath(b, "EMSDK")) |emsdk| return b.pathJoin(&.{ emsdk, "upstream", "emscripten", "cache", "sysroot" }); - if (envPath(b, "HOME")) |home| return b.pathJoin(&.{ home, ".cache", "emscripten", "sysroot" }); - return null; -} - -fn envPath(b: *std.Build, name: []const u8) ?[]const u8 { - return b.graph.environ_map.get(name); -} |
