about things
0
fork

Configure Feed

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

at main 97 lines 3.0 kB view raw view rendered
1# code generation 2 3generating zig source at build time - for help text, unicode tables, bindings, anything derived from data. 4 5## the pattern 6 7build an executable, run it, capture output, import as zig source: 8 9```zig 10// 1. build the generator (always for host, not target) 11const gen_exe = b.addExecutable(.{ 12 .name = "helpgen", 13 .root_module = b.createModule(.{ 14 .root_source_file = b.path("src/helpgen.zig"), 15 .target = b.graph.host, // runs on build machine 16 }), 17}); 18 19// 2. run it and capture stdout 20const gen_run = b.addRunArtifact(gen_exe); 21const gen_output = gen_run.captureStdOut(); 22 23// 3. make it available as an import 24step.root_module.addAnonymousImport("help_strings", .{ 25 .root_source_file = gen_output, 26}); 27``` 28 29now your code can `@import("help_strings")` and get the generated content. 30 31## why `.target = b.graph.host` 32 33the generator runs during the build, on your machine. even if you're cross-compiling to arm64-linux, the generator needs to run on your x86-macos (or whatever you're building from). 34 35`b.graph.host` gives you the host target - the machine running the build. 36 37## writing to files instead 38 39if you need the output as a file (not just an import): 40 41```zig 42const wf = b.addWriteFiles(); 43const output_path = wf.addCopyFile( 44 gen_run.captureStdOut(), 45 "generated.zig", 46); 47// output_path is a LazyPath you can use elsewhere 48``` 49 50## custom build steps for external tools 51 52wrap non-zig tools (metal shader compiler, lipo, etc.) as build steps: 53 54```zig 55pub const MetallibStep = struct { 56 step: std.Build.Step, 57 output: std.Build.LazyPath, 58 59 pub fn create(b: *std.Build, shader_source: []const u8) *MetallibStep { 60 const run = b.addSystemCommand(&.{ 61 "/usr/bin/xcrun", "-sdk", "macosx", "metal", 62 "-c", "-o", 63 }); 64 const ir_output = run.addOutputFileArg("shader.ir"); 65 run.addFileArg(b.path(shader_source)); 66 67 // chain another command for metallib... 68 const self = b.allocator.create(MetallibStep) catch @panic("OOM"); 69 self.* = .{ 70 .step = std.Build.Step.init(.{ ... }), 71 .output = ir_output, 72 }; 73 return self; 74 } 75}; 76``` 77 78key points: 79- `addOutputFileArg()` creates a LazyPath for the output 80- `addFileArg()` adds a dependency on an input file 81- proper dependency tracking means the step reruns when inputs change 82 83## conditional embedding 84 85bun embeds javascript runtime code in release builds but loads from disk in debug: 86 87```zig 88pub fn shouldEmbedCode(opts: *const BuildOptions) bool { 89 return opts.optimize != .Debug or opts.force_embed; 90} 91``` 92 93debug builds iterate faster (no recompile to change js). release builds are self-contained. 94 95sources: 96- [ghostty/src/build/HelpStrings.zig](https://github.com/ghostty-org/ghostty/blob/main/src/build/HelpStrings.zig) 97- [ghostty/src/build/MetallibStep.zig](https://github.com/ghostty-org/ghostty/blob/main/src/build/MetallibStep.zig)