Skip to content

Commit cfea2ea

Browse files
committed
build: mark most dependencies as lazy
Lazy dependencies are only fetched if the build script would actually reach a usage of that dependency at runtime (when the `lazyDependency` function is called). This can save a lot of network traffic, disk uage, and time because we don't have to fetch and build dependencies that we don't actually need. Prior to this commit, Ghostty fetched almost everything for all platforms and configurations all the time. This commit reverses that to fetching almost nothing until it's actually needed. There are very little downsides to doing this[1]. One downside is `zig build --fetch` doesn't fetch lazy dependencies, but we don't rely on this command for packaging and suggest using our custom shell script that downloads a cached list of URLs (`build.zig.zon.txt`). This commit doesn't cover 100% of dependencies, since some provide no benefit to make lazy while the complexity to make them lazy is higher (in code style typically). Conversely, some simple dependencies are marked lazy even if they're almost always needed if they don't introduce any real complexity to the code, because there is very little downside to do so. [1]: https://ziggit.dev/t/lazy-dependencies-best-dependencies/5509/5
1 parent 234b804 commit cfea2ea

29 files changed

+974
-778
lines changed

build.zig.zon

+31-19
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,36 @@
1010
// mitchellh/libxev
1111
.url = "https://github.com/mitchellh/libxev/archive/3df9337a9e84450a58a2c4af434ec1a036f7b494.tar.gz",
1212
.hash = "libxev-0.0.0-86vtc-ziEgDbLP0vihUn1MhsxNKY4GJEga6BEr7oyHpz",
13+
.lazy = true,
1314
},
1415
.vaxis = .{
1516
// rockorager/libvaxis
1617
.url = "git+https://github.com/rockorager/libvaxis#1e24e0dfb509e974e1c8713bcd119d0ae032a8c7",
1718
.hash = "vaxis-0.1.0-BWNV_MHyCAARemSCSwwc3sA1etNgv7ge0BCIXspX6CZv",
19+
.lazy = true,
1820
},
1921
.z2d = .{
2022
// vancluever/z2d
2123
.url = "https://github.com/vancluever/z2d/archive/1e89605a624940c310c7a1d81b46a7c5c05919e3.tar.gz",
2224
.hash = "z2d-0.6.0-j5P_HvLdCABu-dXpCeRM7Uk4m16vULg1980lMNCQj4_C",
25+
.lazy = true,
2326
},
2427
.zig_objc = .{
2528
// mitchellh/zig-objc
2629
.url = "https://github.com/mitchellh/zig-objc/archive/3ab0d37c7d6b933d6ded1b3a35b6b60f05590a98.tar.gz",
2730
.hash = "zig_objc-0.0.0-Ir_Sp3TyAADEVRTxXlScq3t_uKAM91MYNerZkHfbD0yt",
31+
.lazy = true,
2832
},
2933
.zig_js = .{
3034
// mitchellh/zig-js
3135
.url = "https://deps.files.ghostty.org/zig_js-12205a66d423259567764fa0fc60c82be35365c21aeb76c5a7dc99698401f4f6fefc.tar.gz",
3236
.hash = "N-V-__8AAB9YCQBaZtQjJZVndk-g_GDIK-NTZcIa63bFp9yZ",
37+
.lazy = true,
3338
},
3439
.ziglyph = .{
3540
.url = "https://deps.files.ghostty.org/ziglyph-b89d43d1e3fb01b6074bc1f7fc980324b04d26a5.tar.gz",
3641
.hash = "ziglyph-0.11.2-AAAAAHPtHwB4Mbzn1KvOV7Wpjo82NYEc_v0WC8oCLrkf",
42+
.lazy = true,
3743
},
3844
.zig_wayland = .{
3945
// codeberg ifreund/zig-wayland
@@ -44,56 +50,62 @@
4450
// natecraddock/zf
4551
.url = "https://github.com/natecraddock/zf/archive/03176fcf23fda543cc02a8675e92c1fe3b1ee2eb.tar.gz",
4652
.hash = "zf-0.10.3-OIRy8bKIAACV6JaNNncXA68Nw2BUAD9JVfQdzjyoZQ-J",
53+
.lazy = true,
4754
},
4855
.gobject = .{
4956
// https://github.com/jcollie/ghostty-gobject based on zig_gobject
5057
// Temporary until we generate them at build time automatically.
5158
.url = "https://github.com/jcollie/ghostty-gobject/releases/download/0.14.0-2025-03-11-16-1/ghostty-gobject-0.14.0-2025-03-11-16-1.tar.gz",
5259
.hash = "gobject-0.2.0-Skun7H6DlQDWCiNQtdE5TXYcCvx7MyjW01OQe5M_n_jV",
60+
.lazy = true,
5361
},
5462

5563
// C libs
56-
.cimgui = .{ .path = "./pkg/cimgui" },
57-
.fontconfig = .{ .path = "./pkg/fontconfig" },
58-
.freetype = .{ .path = "./pkg/freetype" },
59-
.glfw = .{ .path = "./pkg/glfw" },
60-
.gtk4_layer_shell = .{ .path = "./pkg/gtk4-layer-shell" },
61-
.harfbuzz = .{ .path = "./pkg/harfbuzz" },
62-
.highway = .{ .path = "./pkg/highway" },
63-
.libintl = .{ .path = "./pkg/libintl" },
64-
.libpng = .{ .path = "./pkg/libpng" },
65-
.macos = .{ .path = "./pkg/macos" },
66-
.oniguruma = .{ .path = "./pkg/oniguruma" },
67-
.opengl = .{ .path = "./pkg/opengl" },
68-
.sentry = .{ .path = "./pkg/sentry" },
69-
.simdutf = .{ .path = "./pkg/simdutf" },
70-
.utfcpp = .{ .path = "./pkg/utfcpp" },
71-
.wuffs = .{ .path = "./pkg/wuffs" },
72-
.zlib = .{ .path = "./pkg/zlib" },
64+
.cimgui = .{ .path = "./pkg/cimgui", .lazy = true },
65+
.fontconfig = .{ .path = "./pkg/fontconfig", .lazy = true },
66+
.freetype = .{ .path = "./pkg/freetype", .lazy = true },
67+
.glfw = .{ .path = "./pkg/glfw", .lazy = true },
68+
.gtk4_layer_shell = .{ .path = "./pkg/gtk4-layer-shell", .lazy = true },
69+
.harfbuzz = .{ .path = "./pkg/harfbuzz", .lazy = true },
70+
.highway = .{ .path = "./pkg/highway", .lazy = true },
71+
.libintl = .{ .path = "./pkg/libintl", .lazy = true },
72+
.libpng = .{ .path = "./pkg/libpng", .lazy = true },
73+
.macos = .{ .path = "./pkg/macos", .lazy = true },
74+
.oniguruma = .{ .path = "./pkg/oniguruma", .lazy = true },
75+
.opengl = .{ .path = "./pkg/opengl", .lazy = true },
76+
.sentry = .{ .path = "./pkg/sentry", .lazy = true },
77+
.simdutf = .{ .path = "./pkg/simdutf", .lazy = true },
78+
.utfcpp = .{ .path = "./pkg/utfcpp", .lazy = true },
79+
.wuffs = .{ .path = "./pkg/wuffs", .lazy = true },
80+
.zlib = .{ .path = "./pkg/zlib", .lazy = true },
7381

7482
// Shader translation
75-
.glslang = .{ .path = "./pkg/glslang" },
76-
.spirv_cross = .{ .path = "./pkg/spirv-cross" },
83+
.glslang = .{ .path = "./pkg/glslang", .lazy = true },
84+
.spirv_cross = .{ .path = "./pkg/spirv-cross", .lazy = true },
7785

7886
// Wayland
7987
.wayland = .{
8088
.url = "https://deps.files.ghostty.org/wayland-9cb3d7aa9dc995ffafdbdef7ab86a949d0fb0e7d.tar.gz",
8189
.hash = "N-V-__8AAKrHGAAs2shYq8UkE6bGcR1QJtLTyOE_lcosMn6t",
90+
.lazy = true,
8291
},
8392
.wayland_protocols = .{
8493
.url = "https://deps.files.ghostty.org/wayland-protocols-258d8f88f2c8c25a830c6316f87d23ce1a0f12d9.tar.gz",
8594
.hash = "N-V-__8AAKw-DAAaV8bOAAGqA0-oD7o-HNIlPFYKRXSPT03S",
95+
.lazy = true,
8696
},
8797
.plasma_wayland_protocols = .{
8898
.url = "https://deps.files.ghostty.org/plasma_wayland_protocols-12207e0851c12acdeee0991e893e0132fc87bb763969a585dc16ecca33e88334c566.tar.gz",
8999
.hash = "N-V-__8AAKYZBAB-CFHBKs3u4JkeiT4BMvyHu3Y5aaWF3Bbs",
100+
.lazy = true,
90101
},
91102

92103
// Other
93104
.apple_sdk = .{ .path = "./pkg/apple-sdk" },
94105
.iterm2_themes = .{
95106
.url = "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/e21d5ffd19605741d0e3e19d7c5a8c6c25648673.tar.gz",
96107
.hash = "N-V-__8AAABBKARxrVb9mEr7T5TUQbbqPiHxdBoOAmsChg2a",
108+
.lazy = true,
97109
},
98110
},
99111
}

pkg/breakpad/build.zig

+50-50
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@ pub fn build(b: *std.Build) !void {
44
const target = b.standardTargetOptions(.{});
55
const optimize = b.standardOptimizeOption(.{});
66

7-
const upstream = b.dependency("breakpad", .{});
8-
97
const lib = b.addStaticLibrary(.{
108
.name = "breakpad",
119
.target = target,
1210
.optimize = optimize,
1311
});
1412
lib.linkLibCpp();
15-
lib.addIncludePath(upstream.path("src"));
1613
lib.addIncludePath(b.path("vendor"));
1714
if (target.result.os.tag.isDarwin()) {
1815
const apple_sdk = @import("apple_sdk");
@@ -23,67 +20,70 @@ pub fn build(b: *std.Build) !void {
2320
defer flags.deinit();
2421
try flags.appendSlice(&.{});
2522

26-
lib.addCSourceFiles(.{
27-
.root = upstream.path(""),
28-
.files = common,
29-
.flags = flags.items,
30-
});
31-
32-
if (target.result.os.tag.isDarwin()) {
33-
lib.addCSourceFiles(.{
34-
.root = upstream.path(""),
35-
.files = common_apple,
36-
.flags = flags.items,
37-
});
23+
if (b.lazyDependency("breakpad", .{})) |upstream| {
24+
lib.addIncludePath(upstream.path("src"));
3825
lib.addCSourceFiles(.{
3926
.root = upstream.path(""),
40-
.files = client_apple,
27+
.files = common,
4128
.flags = flags.items,
4229
});
4330

44-
switch (target.result.os.tag) {
45-
.macos => {
46-
lib.addCSourceFiles(.{
47-
.root = upstream.path(""),
48-
.files = common_mac,
49-
.flags = flags.items,
50-
});
51-
lib.addCSourceFiles(.{
31+
if (target.result.os.tag.isDarwin()) {
32+
lib.addCSourceFiles(.{
33+
.root = upstream.path(""),
34+
.files = common_apple,
35+
.flags = flags.items,
36+
});
37+
lib.addCSourceFiles(.{
38+
.root = upstream.path(""),
39+
.files = client_apple,
40+
.flags = flags.items,
41+
});
42+
43+
switch (target.result.os.tag) {
44+
.macos => {
45+
lib.addCSourceFiles(.{
46+
.root = upstream.path(""),
47+
.files = common_mac,
48+
.flags = flags.items,
49+
});
50+
lib.addCSourceFiles(.{
51+
.root = upstream.path(""),
52+
.files = client_mac,
53+
.flags = flags.items,
54+
});
55+
},
56+
57+
.ios => lib.addCSourceFiles(.{
5258
.root = upstream.path(""),
53-
.files = client_mac,
59+
.files = client_ios,
5460
.flags = flags.items,
55-
});
56-
},
61+
}),
5762

58-
.ios => lib.addCSourceFiles(.{
63+
else => {},
64+
}
65+
}
66+
67+
if (target.result.os.tag == .linux) {
68+
lib.addCSourceFiles(.{
5969
.root = upstream.path(""),
60-
.files = client_ios,
70+
.files = common_linux,
6171
.flags = flags.items,
62-
}),
63-
64-
else => {},
72+
});
73+
lib.addCSourceFiles(.{
74+
.root = upstream.path(""),
75+
.files = client_linux,
76+
.flags = flags.items,
77+
});
6578
}
66-
}
6779

68-
if (target.result.os.tag == .linux) {
69-
lib.addCSourceFiles(.{
70-
.root = upstream.path(""),
71-
.files = common_linux,
72-
.flags = flags.items,
73-
});
74-
lib.addCSourceFiles(.{
75-
.root = upstream.path(""),
76-
.files = client_linux,
77-
.flags = flags.items,
78-
});
80+
lib.installHeadersDirectory(
81+
upstream.path("src"),
82+
"",
83+
.{ .include_extensions = &.{".h"} },
84+
);
7985
}
8086

81-
lib.installHeadersDirectory(
82-
upstream.path("src"),
83-
"",
84-
.{ .include_extensions = &.{".h"} },
85-
);
86-
8787
b.installArtifact(lib);
8888
}
8989

pkg/breakpad/build.zig.zon

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
.breakpad = .{
88
.url = "https://deps.files.ghostty.org/breakpad-b99f444ba5f6b98cac261cbb391d8766b34a5918.tar.gz",
99
.hash = "N-V-__8AALw2uwF_03u4JRkZwRLc3Y9hakkYV7NKRR9-RIZJ",
10+
.lazy = true,
1011
},
1112

1213
.apple_sdk = .{ .path = "../apple-sdk" },

pkg/cimgui/build.zig

+7-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@ pub fn build(b: *std.Build) !void {
4040
.@"enable-libpng" = true,
4141
});
4242
lib.linkLibrary(freetype.artifact("freetype"));
43-
module.addIncludePath(freetype.builder.dependency("freetype", .{}).path("include"));
43+
44+
if (freetype.builder.lazyDependency(
45+
"freetype",
46+
.{},
47+
)) |freetype_dep| {
48+
module.addIncludePath(freetype_dep.path("include"));
49+
}
4450
}
4551

4652
lib.addIncludePath(imgui.path(""));

pkg/fontconfig/build.zig

+22-19
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Bu
6464
const libxml2_iconv_enabled = options.libxml2_iconv_enabled;
6565
const freetype_enabled = options.freetype_enabled;
6666

67-
const upstream = b.dependency("fontconfig", .{});
6867
const lib = b.addStaticLibrary(.{
6968
.name = "fontconfig",
7069
.target = target,
@@ -75,9 +74,7 @@ fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Bu
7574
lib.linkSystemLibrary("pthread");
7675
}
7776

78-
lib.addIncludePath(upstream.path(""));
7977
lib.addIncludePath(b.path("override/include"));
80-
module.addIncludePath(upstream.path(""));
8178
module.addIncludePath(b.path("override/include"));
8279

8380
var flags = std.ArrayList([]const u8).init(b.allocator);
@@ -188,11 +185,12 @@ fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Bu
188185
if (b.systemIntegrationOption("freetype", .{})) {
189186
lib.linkSystemLibrary2("freetype2", dynamic_link_opts);
190187
} else {
191-
const freetype_dep = b.dependency(
188+
if (b.lazyDependency(
192189
"freetype",
193190
.{ .target = target, .optimize = optimize },
194-
);
195-
lib.linkLibrary(freetype_dep.artifact("freetype"));
191+
)) |freetype_dep| {
192+
lib.linkLibrary(freetype_dep.artifact("freetype"));
193+
}
196194
}
197195
}
198196

@@ -214,26 +212,31 @@ fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Bu
214212
if (b.systemIntegrationOption("libxml2", .{})) {
215213
lib.linkSystemLibrary2("libxml-2.0", dynamic_link_opts);
216214
} else {
217-
const libxml2_dep = b.dependency("libxml2", .{
215+
if (b.lazyDependency("libxml2", .{
218216
.target = target,
219217
.optimize = optimize,
220218
.iconv = libxml2_iconv_enabled,
221-
});
222-
lib.linkLibrary(libxml2_dep.artifact("xml2"));
219+
})) |libxml2_dep| {
220+
lib.linkLibrary(libxml2_dep.artifact("xml2"));
221+
}
223222
}
224223
}
225224

226-
lib.addCSourceFiles(.{
227-
.root = upstream.path(""),
228-
.files = srcs,
229-
.flags = flags.items,
230-
});
225+
if (b.lazyDependency("fontconfig", .{})) |upstream| {
226+
lib.addIncludePath(upstream.path(""));
227+
module.addIncludePath(upstream.path(""));
228+
lib.addCSourceFiles(.{
229+
.root = upstream.path(""),
230+
.files = srcs,
231+
.flags = flags.items,
232+
});
231233

232-
lib.installHeadersDirectory(
233-
upstream.path("fontconfig"),
234-
"fontconfig",
235-
.{ .include_extensions = &.{".h"} },
236-
);
234+
lib.installHeadersDirectory(
235+
upstream.path("fontconfig"),
236+
"fontconfig",
237+
.{ .include_extensions = &.{".h"} },
238+
);
239+
}
237240

238241
b.installArtifact(lib);
239242

pkg/fontconfig/build.zig.zon

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
.fontconfig = .{
88
.url = "https://deps.files.ghostty.org/fontconfig-2.14.2.tar.gz",
99
.hash = "N-V-__8AAIrfdwARSa-zMmxWwFuwpXf1T3asIN7s5jqi9c1v",
10+
.lazy = true,
1011
},
1112

12-
.freetype = .{ .path = "../freetype" },
13-
.libxml2 = .{ .path = "../libxml2" },
13+
.freetype = .{ .path = "../freetype", .lazy = true },
14+
.libxml2 = .{ .path = "../libxml2", .lazy = true },
1415
},
1516
}

0 commit comments

Comments
 (0)