summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-24 12:56:04 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit7fdf5ed9d1dd433e4657b670b7831cec6e3d41ca (patch)
treea0a8f2631e54647cdb88ef876189ff175f4b9a58
parent8de5bf6fecc19cf2be6093b4338691fe4af84815 (diff)
downloadpardes-7fdf5ed9d1dd433e4657b670b7831cec6e3d41ca.tar.gz
pardes-7fdf5ed9d1dd433e4657b670b7831cec6e3d41ca.zip
Build MuPDF against the FreeType the gui links, not the slim one it bundles
MuPDF compiled its own FreeType 2.13.3 (FREETYPE_SRC, trimmed by scripts/freetype's slimftmodules.h and slimftoptions.h) into libmupdf.a, and the gui also links the freetype package, 2.14.3 in its full configuration. The two define the same 312 symbols, and a linker handed both keeps one of each: the gui's MuPDF ran the package's FreeType compiled against the slim headers, while the tty ran the slim one. Now there is one. mupdf.zig takes the build's freetype artifact, links it (its headers come with it) and no longer compiles FREETYPE_SRC or puts the slim headers on the include path. The shared artifact is built at c_optimize, as MuPDF is, so a Debug gui's glyph atlas now uses a ReleaseFast FreeType too; one artifact cannot be both. The tty gains the full FreeType's extra modules, which FT_Add_Default_Modules registers whether or not a PDF needs them. MuPDF asks nothing of FreeType the full configuration lacks: every page of docs/design.pdf, docs/9p.pdf and docs/registry.pdf renders bit for bit as before, at 144 and at 300 dpi. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
-rw-r--r--build.zig19
-rw-r--r--mupdf.zig22
2 files changed, 22 insertions, 19 deletions
diff --git a/build.zig b/build.zig
index 2c8a8858..3b57fff6 100644
--- a/build.zig
+++ b/build.zig
@@ -418,12 +418,22 @@ pub fn build(b: *std.Build) void {
.root_source_file = b.path("src/c_heap.zig"),
});
+ // One FreeType in a binary: the gui's glyph atlas links it and MuPDF is
+ // built against it (see mupdf.zig). At c_optimize with the rest of the
+ // vendored C, since MuPDF rasterizes a PDF's text through it.
+ const freetype: ?*std.Build.Step.Compile = if (freestanding_core) null else b.dependency("freetype", .{
+ .target = target,
+ .optimize = c_optimize,
+ .@"enable-libpng" = false,
+ }).artifact("freetype");
+
if (enable_mupdf) {
if (b.lazyDependency("mupdf", .{})) |mupdf_dep| {
const mupdf = mupdf_build.add(b, io, mupdf_dep, .{
.target = target,
.optimize = c_optimize,
.jpx = enable_jpx,
+ .freetype = freetype.?,
});
const mupdf_mod = b.createModule(.{
.target = target,
@@ -647,12 +657,7 @@ pub fn build(b: *std.Build) void {
gm.linkLibrary(sdl_lib);
gm.addIncludePath(dep.path("include"));
}
- const freetype_dep = b.dependency("freetype", .{
- .target = target,
- .optimize = optimize,
- .@"enable-libpng" = false,
- });
- gm.linkLibrary(freetype_dep.artifact("freetype"));
+ gm.linkLibrary(freetype.?);
// HarfBuzz from source, like FreeType: its FreeType integration
// (HAVE_FREETYPE, hb-ft) links the freetype artifact above, so the two
// share one FreeType. The flags are the ones Ghostty builds it with,
@@ -669,7 +674,7 @@ pub fn build(b: *std.Build) void {
.link_libcpp = true,
}),
});
- harfbuzz.root_module.linkLibrary(freetype_dep.artifact("freetype"));
+ harfbuzz.root_module.linkLibrary(freetype.?);
harfbuzz.root_module.addIncludePath(upstream.path("src"));
harfbuzz.root_module.addCSourceFile(.{
.file = upstream.path("src/harfbuzz.cc"),
diff --git a/mupdf.zig b/mupdf.zig
index 400e5ee3..cda9a38a 100644
--- a/mupdf.zig
+++ b/mupdf.zig
@@ -33,6 +33,14 @@ pub fn add(b: *std.Build, io: std.Io, dependency: *std.Build.Dependency, options
/// Compile openjpeg and let MuPDF decode JPEG 2000. See the OPENJPEG
/// block below for why this is a switch rather than always-on.
jpx: bool = true,
+ /// The FreeType the rest of the build links, which MuPDF is compiled
+ /// against and links instead of the slim one it bundles (FREETYPE_SRC,
+ /// configured by scripts/freetype). Both define the same symbols and a
+ /// linker handed two keeps one of each, so the gui's MuPDF ran the full
+ /// FreeType's code compiled against the slim one's headers, while the tty
+ /// ran the slim one. MuPDF asks nothing of FreeType the full
+ /// configuration lacks.
+ freetype: *std.Build.Step.Compile,
}) Result {
const module = b.createModule(.{
.target = options.target,
@@ -45,6 +53,8 @@ pub fn add(b: *std.Build, io: std.Io, dependency: *std.Build.Dependency, options
// debug-locking/assertion paths. linkTo applies the same public-header
// contract to consumers; keeping it here also covers every archive source.
module.addCMacro("NDEBUG", "1");
+ // The build's own FreeType, headers and all; see `freetype` above.
+ module.linkLibrary(options.freetype);
// MuPDF itself uses wildcards for these two directories. The dependency
// is immutable and content-addressed, so discovering the flat C lists at
@@ -82,16 +92,6 @@ pub fn add(b: *std.Build, io: std.Io, dependency: *std.Build.Dependency, options
const makelists = readMakelists(b, io, dependency);
module.addCSourceFiles(.{
.root = dependency.path(""),
- .files = makeSources(b, makelists, "FREETYPE_SRC"),
- .flags = &.{
- "-std=gnu11",
- "-DFT_CONFIG_MODULES_H=\"slimftmodules.h\"",
- "-DFT_CONFIG_OPTIONS_H=\"slimftoptions.h\"",
- "-DFT2_BUILD_LIBRARY",
- },
- });
- module.addCSourceFiles(.{
- .root = dependency.path(""),
.files = makeSources(b, makelists, "LIBJPEG_SRC"),
.flags = &.{"-std=gnu11"},
});
@@ -250,8 +250,6 @@ fn configureModule(module: *std.Build.Module, dependency: *std.Build.Dependency,
module.addIncludePath(dependency.path("include"));
module.addIncludePath(dependency.path("source/fitz"));
module.addIncludePath(dependency.path("source/pdf"));
- module.addIncludePath(dependency.path("thirdparty/freetype/include"));
- module.addIncludePath(dependency.path("scripts/freetype"));
module.addIncludePath(dependency.path("thirdparty/libjpeg"));
module.addIncludePath(dependency.path("scripts/libjpeg"));
module.addIncludePath(dependency.path("thirdparty/zlib"));