about things
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 101 lines 2.7 kB view raw view rendered
1# build organization 2 3as projects grow, a single `build.zig` becomes unwieldy. ghostty's solution: treat build logic as a package. 4 5## the pattern 6 7instead of one giant build.zig, create `src/build/` as a zig package: 8 9``` 10src/build/ 11├── main.zig # exports everything 12├── Config.zig # all -D options in one struct 13├── SharedDeps.zig # dependency wiring 14├── GhosttyExe.zig # executable-specific logic 15├── GhosttyLib.zig # library-specific logic 16└── steps/ # custom build steps 17``` 18 19the root `build.zig` becomes a thin shell: 20 21```zig 22const buildpkg = @import("src/build/main.zig"); 23 24pub fn build(b: *std.Build) !void { 25 const config = buildpkg.Config.fromOptions(b); 26 const deps = try buildpkg.SharedDeps.init(b, &config); 27 28 if (config.emit_exe) { 29 _ = try buildpkg.GhosttyExe.init(b, &deps); 30 } 31 if (config.emit_lib) { 32 _ = try buildpkg.GhosttyLib.init(b, &deps); 33 } 34} 35``` 36 37## centralized configuration 38 39all `-D` options live in one struct. this makes them discoverable and passable: 40 41```zig 42// Config.zig 43pub const Config = @This(); 44 45// features 46x11: bool = false, 47wayland: bool = false, 48sentry: bool = true, 49 50// artifacts to emit 51emit_exe: bool = false, 52emit_lib: bool = false, 53emit_docs: bool = false, 54 55pub fn fromOptions(b: *std.Build) Config { 56 return .{ 57 .x11 = b.option(bool, "x11", "Enable X11") orelse false, 58 .wayland = b.option(bool, "wayland", "Enable Wayland") orelse false, 59 // ... 60 }; 61} 62 63// export to comptime for runtime introspection 64pub fn addOptions(self: *const Config, step: *std.Build.Step.Compile) void { 65 const opts = step.root_module.addOptions(); 66 opts.addOption(bool, "x11", self.x11); 67 opts.addOption(bool, "wayland", self.wayland); 68 // now @import("build_options").x11 works in source 69} 70``` 71 72## shared dependencies 73 74avoid duplicating dependency wiring across artifacts: 75 76```zig 77// SharedDeps.zig 78pub const SharedDeps = @This(); 79 80config: *const Config, 81freetype: *std.Build.Dependency, 82harfbuzz: *std.Build.Dependency, 83 84pub fn add(self: *const SharedDeps, step: *std.Build.Step.Compile) void { 85 step.linkLibrary(self.freetype.artifact("freetype")); 86 step.linkLibrary(self.harfbuzz.artifact("harfbuzz")); 87 // add all the deps once, use everywhere 88} 89``` 90 91now both `GhosttyExe` and `GhosttyLib` just call `deps.add(step)`. 92 93## when to split 94 95small projects don't need this. consider splitting when: 96- build.zig exceeds ~500 lines 97- you have multiple artifacts (exe, lib, tests) sharing deps 98- platform-specific logic is getting tangled 99- you want to test build logic itself 100 101source: [ghostty/src/build/](https://github.com/ghostty-org/ghostty/tree/main/src/build)