authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-15 21:32:33-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:33-07:00
log6b040d631fd5090d85c56b39006162f2aa4991b1
treee28f6767a4747d8cf03d757a86859c157e11777a
parent83a34758874dbe98d3566e297b56cd3be0e66900

configure runner: add Step.Run serialization


5 files changed, 178 insertions(+), 41 deletions(-)

lib/compiler/configure_runner.zig+56-6
......@@ -206,6 +206,7 @@ pub fn main(init: process.Init.Minimal) !void {
206206
207207 var wc: Configuration.Wip = .init(gpa);
208208 defer wc.deinit();
209 assert(try wc.addString("") == .empty);
209210
210211 var stdout_buffer: [1024]u8 = undefined;
211212 var file_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer);
......@@ -259,7 +260,6 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
259260 try wc.steps.ensureTotalCapacity(gpa, step_map.entries.capacity);
260261 wc.steps.appendAssumeCapacity(.{
261262 .name = try wc.addString(step.name),
262 .flags = .{ .tag = step.tag },
263263 .deps = deps,
264264 .max_rss = .fromBytes(step.max_rss),
265265 .extra_index = switch (step.tag) {
......@@ -273,6 +273,9 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
273273 .install_artifact => e: {
274274 const ia: *Step.InstallArtifact = @fieldParentPtr("step", step);
275275 break :e try wc.addExtra(@as(Configuration.Step.InstallArtifact, .{
276 .flags = .{
277 .dylib_symlinks = ia.dylib_symlinks != null,
278 },
276279 .dest_dir = try addInstallDir(wc, ia.dest_dir),
277280 .dest_sub_path = try wc.addString(ia.dest_sub_path),
278281 .emitted_bin = try addOptionalLazyPath(wc, ia.emitted_bin),
......@@ -293,7 +296,54 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
293296 .translate_c => @panic("TODO"),
294297 .write_file => @panic("TODO"),
295298 .update_source_files => @panic("TODO"),
296 .run => @panic("TODO"),
299 .run => e: {
300 const run: *Step.Run = @fieldParentPtr("step", step);
301
302 const captured_stdout: Configuration.OptionalString = if (run.captured_stdout) |cs|
303 .init(try wc.addString(cs.output.basename))
304 else
305 .none;
306
307 const captured_stderr: Configuration.OptionalString = if (run.captured_stderr) |cs|
308 .init(try wc.addString(cs.output.basename))
309 else
310 .none;
311
312 const extra_index = try wc.addExtra(@as(Configuration.Step.Run, .{
313 .flags = .{
314 .disable_zig_progress = run.disable_zig_progress,
315 .skip_foreign_checks = run.skip_foreign_checks,
316 .failing_to_execute_foreign_is_an_error = run.failing_to_execute_foreign_is_an_error,
317 .has_side_effects = run.has_side_effects,
318 .test_runner_mode = run.test_runner_mode,
319 .color = run.color,
320 .stdio = switch (run.stdio) {
321 .infer_from_args => .infer_from_args,
322 .inherit => .inherit,
323 .check => .check,
324 .zig_test => .zig_test,
325 },
326 .stdin = switch (run.stdin) {
327 .none => .none,
328 .bytes => .bytes,
329 .lazy_path => .lazy_path,
330 },
331 .stdout_trim_whitespace = if (run.captured_stdout) |cs| cs.trim_whitespace else .none,
332 .stderr_trim_whitespace = if (run.captured_stderr) |cs| cs.trim_whitespace else .none,
333 .stdio_limit = run.stdio_limit != .unlimited,
334 .producer = run.producer != null,
335 },
336 .file_inputs_len = @intCast(run.file_inputs.items.len),
337 .args_len = @intCast(run.argv.items.len),
338 .cwd = try addOptionalLazyPath(wc, run.cwd),
339 .captured_stdout = captured_stdout,
340 .captured_stderr = captured_stderr,
341 }));
342
343 std.log.err("TODO serialize the trailing Run step data", .{});
344
345 break :e extra_index;
346 },
297347 .check_file => @panic("TODO"),
298348 .check_object => @panic("TODO"),
299349 .config_header => @panic("TODO"),
......@@ -319,7 +369,7 @@ fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configu
319369 .src_path => |src_path| i: {
320370 const owner = builderToPackage(src_path.owner);
321371 const sub_path = try wc.addString(src_path.sub_path);
322 break :i try wc.addExtra(@as(Configuration.OptionalLazyPath.SourcePath, .{
372 break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{
323373 .flags = .{},
324374 .owner = owner,
325375 .sub_path = sub_path,
......@@ -327,14 +377,14 @@ fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configu
327377 },
328378 .generated => |generated| i: {
329379 const sub_path = try wc.addString(generated.sub_path);
330 break :i try wc.addExtra(@as(Configuration.OptionalLazyPath.Generated, .{
380 break :i try wc.addExtra(@as(Configuration.LazyPath.Generated, .{
331381 .flags = .{ .up = @intCast(generated.up) },
332382 .sub_path = sub_path,
333383 }));
334384 },
335385 .cwd_relative => |cwd_relative_sub_path| i: {
336386 const sub_path = try wc.addString(cwd_relative_sub_path);
337 break :i try wc.addExtra(@as(Configuration.OptionalLazyPath.Relative, .{
387 break :i try wc.addExtra(@as(Configuration.LazyPath.Relative, .{
338388 .flags = .{ .base = .cwd },
339389 .sub_path = sub_path,
340390 }));
......@@ -342,7 +392,7 @@ fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configu
342392 .dependency => |dependency| i: {
343393 const owner = builderToPackage(dependency.dependency.builder);
344394 const sub_path = try wc.addString(dependency.sub_path);
345 break :i try wc.addExtra(@as(Configuration.OptionalLazyPath.SourcePath, .{
395 break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{
346396 .flags = .{},
347397 .owner = owner,
348398 .sub_path = sub_path,
lib/compiler/maker/Step/Run.zig+3
......@@ -20,6 +20,9 @@ const Step = @import("../Step.zig");
2020fuzz_tests: std.ArrayList([]const u8),
2121cached_test_metadata: ?CachedTestMetadata = null,
2222
23/// Populated during the fuzz phase if this run step corresponds to a unit test
24/// executable that contains fuzz tests.
25rebuilt_executable: ?Path,
2326
2427fn make(step: *Step, options: Step.MakeOptions) !void {
2528 const b = step.owner;
lib/compiler/maker/Watch.zig+2-2
......@@ -1,12 +1,12 @@
1const Watch = @This();
12const builtin = @import("builtin");
23
3const std = @import("../std.zig");
4const std = @import("std");
45const Io = std.Io;
56const Step = std.Build.Step;
67const Allocator = std.mem.Allocator;
78const assert = std.debug.assert;
89const fatal = std.process.fatal;
9const Watch = @This();
1010const FsEvents = @import("Watch/FsEvents.zig");
1111
1212os: Os,
lib/std/Build/Step/Run.zig+2-24
......@@ -89,26 +89,10 @@ dep_output_file: ?*Output,
8989has_side_effects: bool,
9090test_runner_mode: bool = false,
9191
92/// Populated during the fuzz phase if this run step corresponds to a unit test
93/// executable that contains fuzz tests.
94rebuilt_executable: ?Path,
95
9692/// If this Run step was produced by a Compile step, it is tracked here.
9793producer: ?*Step.Compile,
9894
99pub const Color = enum {
100 /// `CLICOLOR_FORCE` is set, and `NO_COLOR` is unset.
101 enable,
102 /// `NO_COLOR` is set, and `CLICOLOR_FORCE` is unset.
103 disable,
104 /// If the build runner is using color, equivalent to `.enable`. Otherwise, equivalent to `.disable`.
105 inherit,
106 /// If stderr is captured or checked, equivalent to `.disable`. Otherwise, equivalent to `.inherit`.
107 auto,
108 /// The build runner does not modify the `CLICOLOR_FORCE` or `NO_COLOR` environment variables.
109 /// They are treated like normal variables, so can be controlled through `setEnvironmentVariable`.
110 manual,
111};
95pub const Color = std.Build.Configuration.Step.Run.Color;
11296
11397pub const StdIn = union(enum) {
11498 none,
......@@ -192,12 +176,7 @@ pub const CapturedStdIo = struct {
192176 trim_whitespace: TrimWhitespace = .none,
193177 };
194178
195 pub const TrimWhitespace = enum {
196 none,
197 all,
198 leading,
199 trailing,
200 };
179 pub const TrimWhitespace = std.Build.Configuration.Step.Run.TrimWhitespace;
201180};
202181
203182pub fn create(owner: *std.Build, name: []const u8) *Run {
......@@ -223,7 +202,6 @@ pub fn create(owner: *std.Build, name: []const u8) *Run {
223202 .captured_stderr = null,
224203 .dep_output_file = null,
225204 .has_side_effects = false,
226 .rebuilt_executable = null,
227205 .producer = null,
228206 };
229207 return run;
lib/std/zig/Configuration.zig+115-9
......@@ -196,17 +196,12 @@ pub const Wip = struct {
196196
197197pub const Step = extern struct {
198198 name: String,
199 flags: Flags,
200199 deps: Deps,
201200 max_rss: MaxRss,
202 /// Points into `extra` for step-specific data.
201 /// Points into `extra` for step-specific data. First element has flags
202 /// with `Tag`.
203203 extra_index: u32,
204204
205 pub const Flags = packed struct(u32) {
206 tag: Tag,
207 _: u24 = 0,
208 };
209
210205 pub const Index = enum(u32) {
211206 _,
212207 };
......@@ -232,10 +227,18 @@ pub const Step = extern struct {
232227 };
233228
234229 pub const TopLevel = struct {
230 flags: Flags = .{},
235231 description: String,
232
233 pub const Flags = packed struct(u32) {
234 tag: Tag = .top_level,
235 _: u24 = 0,
236 };
236237 };
237238
238239 pub const InstallArtifact = struct {
240 flags: Flags,
241
239242 dest_dir: InstallDir,
240243 dest_sub_path: String,
241244 emitted_bin: OptionalLazyPath,
......@@ -252,12 +255,96 @@ pub const Step = extern struct {
252255 /// Always a compile step.
253256 artifact: Step.Index,
254257
255 const Flags = packed struct(u32) {
258 pub const Flags = packed struct(u32) {
256259 tag: Tag = .install_artifact,
257260 dylib_symlinks: bool,
258261 _: u23 = 0,
259262 };
260263 };
264
265 /// Trailing:
266 /// * LazyPath for each file_inputs_len
267 /// * Arg for each args_len
268 /// * environ_map if corresponding flag is set
269 /// * stdin: Bytes, // if StdIn.bytes is chosen
270 /// * stdin: LazyPath, // if StdIn.lazy_path is chosen
271 /// * checks: Checks, // if StdIo.check is chosen
272 /// * stdio_limit: u64, // if stdio_limit is set
273 /// * producer: Step.Index, // if producer is set. always compile step
274 pub const Run = struct {
275 flags: Flags,
276 file_inputs_len: u32,
277 args_len: u32,
278 cwd: OptionalLazyPath,
279 captured_stdout: OptionalString, // basename
280 captured_stderr: OptionalString, // basename
281
282 /// Trailing:
283 /// * String if prefix set
284 /// * String if suffix set
285 /// * String if basename set
286 /// * Step.Index which is always a compile step if tag is artifact
287 /// * LazyPath if tag is path_file, path_directory, or file_content
288 pub const Arg = struct {
289 flags: Arg.Flags,
290
291 pub const Flags = packed struct(u32) {
292 tag: Arg.Tag,
293 prefix: bool,
294 suffix: bool,
295 basename: bool,
296 /// Implies Tag is output_file
297 dep_file: bool,
298 _: u20 = 0,
299 };
300
301 pub const Tag = enum(u8) {
302 artifact,
303 path_file,
304 path_directory,
305 file_content,
306 bytes,
307 output_file,
308 output_directory,
309 };
310 };
311
312 pub const Color = enum(u4) {
313 /// `CLICOLOR_FORCE` is set, and `NO_COLOR` is unset.
314 enable,
315 /// `NO_COLOR` is set, and `CLICOLOR_FORCE` is unset.
316 disable,
317 /// If the build runner is using color, equivalent to `.enable`. Otherwise, equivalent to `.disable`.
318 inherit,
319 /// If stderr is captured or checked, equivalent to `.disable`. Otherwise, equivalent to `.inherit`.
320 auto,
321 /// The build runner does not modify the `CLICOLOR_FORCE` or `NO_COLOR` environment variables.
322 /// They are treated like normal variables, so can be controlled through `setEnvironmentVariable`.
323 manual,
324 };
325
326 pub const StdIn = enum(u2) { none, bytes, lazy_path };
327 pub const TrimWhitespace = enum(u2) { none, all, leading, trailing };
328 pub const StdIo = enum(u2) { infer_from_args, inherit, check, zig_test };
329
330 pub const Flags = packed struct(u32) {
331 tag: Tag = .run,
332
333 disable_zig_progress: bool,
334 skip_foreign_checks: bool,
335 failing_to_execute_foreign_is_an_error: bool,
336 has_side_effects: bool,
337 test_runner_mode: bool,
338 color: Color,
339 stdin: StdIn,
340 stdio: StdIo,
341 stdout_trim_whitespace: TrimWhitespace,
342 stderr_trim_whitespace: TrimWhitespace,
343 stdio_limit: bool,
344 producer: bool,
345 _: u5 = 0,
346 };
347 };
261348};
262349
263350pub const MaxRss = enum(u32) {
......@@ -274,10 +361,15 @@ pub const MaxRss = enum(u32) {
274361 }
275362};
276363
277/// An index into `extra`.
364/// An index into `extra`, or `null`.
278365pub const OptionalLazyPath = enum(u32) {
279366 none = maxInt(u32),
280367 _,
368};
369
370/// An index into `extra`.
371pub const LazyPath = enum(u32) {
372 _,
281373
282374 pub const Tag = enum(u8) {
283375 /// A source file path relative to build root.
......@@ -368,8 +460,22 @@ pub const InstallDir = enum(u32) {
368460 }
369461};
370462
463/// Points into `string_bytes`, null-terminated.
464pub const OptionalString = enum(u32) {
465 empty = 0,
466 none = maxInt(u32),
467 _,
468
469 pub fn init(s: String) OptionalString {
470 const result: OptionalString = @enumFromInt(@intFromEnum(s));
471 assert(result != .none);
472 return result;
473 }
474};
475
371476/// Points into `string_bytes`, null-terminated.
372477pub const String = enum(u32) {
478 empty = 0,
373479 _,
374480
375481 pub fn slice(index: String, c: *const Configuration) [:0]const u8 {