summaryrefslogtreecommitdiff
path: root/build.zig
diff options
context:
space:
mode:
Diffstat (limited to 'build.zig')
-rw-r--r--build.zig61
1 files changed, 61 insertions, 0 deletions
diff --git a/build.zig b/build.zig
index c7a42872..40058407 100644
--- a/build.zig
+++ b/build.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const mupdf_build = @import("mupdf.zig");
const snap_build = @import("build/snap.zig");
pub const Platform = enum { tty, gui, web };
@@ -27,6 +28,7 @@ pub fn build(b: *std.Build) void {
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 is_web = platform == .web;
+ const enable_mupdf = b.option(bool, "mupdf", "native PDF rendering with MuPDF (AGPL/commercial; native default on, web off; -Dmupdf=false disables)") orelse !is_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_web) .ReleaseSmall else requested_optimize;
@@ -47,6 +49,9 @@ pub fn build(b: *std.Build) void {
// 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>)");
+ const mupdf_check = b.step("mupdf-check", "compile, link, render, and search docs/design.pdf with MuPDF");
+ if (!enable_mupdf)
+ mupdf_check.dependOn(&b.addFail("mupdf-check is unavailable with -Dmupdf=false").step);
// 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
@@ -74,6 +79,7 @@ pub fn build(b: *std.Build) void {
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 (enable_mupdf and is_web) return failBuild(b, web_step, "-Dmupdf=true is supported only by the native tty/Kitty and gui/SDL backends");
// build-time IO: slurps the grammars' highlights.scm queries, and reads
// vendor/themes to find the theme sources
@@ -151,6 +157,7 @@ pub fn build(b: *std.Build) void {
opts.addOption(bool, "syntax_full_grammars", tree_sitter_grammars == .full);
opts.addOption(bool, "enable_tracy", tracy != null);
opts.addOption(bool, "zls_backend", zls_backend);
+ opts.addOption(bool, "mupdf", enable_mupdf);
// Which ZLS is compiled in, for `SPC l i`. Kept next to the dependency it
// names: the .zon pins a commit, and a status screen that cannot say WHICH
// analyser answered is not worth opening.
@@ -332,6 +339,44 @@ pub fn build(b: *std.Build) void {
root_mod.addImport("mvzr", mvzr_mod);
hx_core_mod.addImport("mvzr", mvzr_mod);
+ // MuPDF is the default native PDF engine, but remains a genuinely optional
+ // dependency: with -Dmupdf=false (and by default on web), the lazy source
+ // archive is not fetched, compiled, linked, or exposed to runtime code.
+ // mupdf.zig mirrors the 1.27.0 Makefile source graph with Zig's C compiler
+ // and deliberately enables only the PDF document handler for this first
+ // integration.
+ if (enable_mupdf) {
+ if (b.lazyDependency("mupdf", .{})) |mupdf_dep| {
+ const mupdf = mupdf_build.add(b, io, mupdf_dep, .{
+ .target = target,
+ .optimize = c_optimize,
+ });
+ const mupdf_mod = b.createModule(.{
+ .target = target,
+ .optimize = optimize,
+ .root_source_file = b.path("src/pdf.zig"),
+ .link_libc = true,
+ });
+ mupdf.linkTo(mupdf_mod);
+ mupdf_mod.addIncludePath(b.path("src"));
+ mupdf_mod.addCSourceFile(.{
+ .file = b.path("src/pdf_bridge.c"),
+ .flags = &.{"-std=gnu11"},
+ });
+ root_mod.addImport("mupdf", mupdf_mod);
+ hx_core_mod.addImport("mupdf", mupdf_mod);
+ // Compile the @cImport + exception bridge and exercise the Zig
+ // wrapper's stride-aware RGB-to-RGBA boundary alongside the C
+ // end-to-end document probe below.
+ const mupdf_test = b.addTest(.{ .root_module = mupdf_mod });
+ mupdf_check.dependOn(&b.addRunArtifact(mupdf_test).step);
+ mupdf_check.dependOn(mupdf_build.addProbe(b, mupdf, .{
+ .target = target,
+ .pdf = b.path("docs/design.pdf"),
+ }));
+ }
+ }
+
// ghostty-vt and vaxis both depend on uucode, but Zig forbids one source
// file in two modules — build a single uucode (our config, unpacked tables)
// and hand it to both. Same trick as the prototype; see uucode_config.zig.
@@ -583,6 +628,22 @@ pub fn build(b: *std.Build) void {
run_image_harness.has_side_effects = true;
b.step("image-harness", "exercise native Kitty/SDL image rendering end to end").dependOn(&run_image_harness.step);
+ // The PDF arm uses the same native-pixel observer but a generated,
+ // searchable two-page document. Keep it a distinct opt-in step: the
+ // ordinary image harness stays identical when MuPDF is disabled, and
+ // asking for PDF coverage without the feature gets an explicit error.
+ const pdf_harness_step = b.step("pdf-harness", "exercise PDF rendering, page replacement, and search Look end to end");
+ if (enable_mupdf) {
+ const run_pdf_harness = b.addRunArtifact(image_harness);
+ run_pdf_harness.addArtifactArg(exe);
+ run_pdf_harness.addArg(if (platform == .gui) "gui" else "tty");
+ run_pdf_harness.addArg("pdf");
+ run_pdf_harness.has_side_effects = true;
+ pdf_harness_step.dependOn(&run_pdf_harness.step);
+ } else {
+ pdf_harness_step.dependOn(&b.addFail("pdf-harness is unavailable with -Dmupdf=false").step);
+ }
+
// helix differential harness: drive the sans-IO core headlessly over
// JSON-Lines cases, one contract result line per case on stdout —
// the pardes half of the pardes-vs-helix diff (helix's hx-harness on