configure runner: add Step.Run serialization

This commit is contained in:
Andrew Kelley
2026-02-15 21:32:33 -08:00
parent c3168cf25a
commit acf57b8244
5 changed files with 178 additions and 41 deletions
+56 -6
View File
@@ -206,6 +206,7 @@ pub fn main(init: process.Init.Minimal) !void {
var wc: Configuration.Wip = .init(gpa);
defer wc.deinit();
assert(try wc.addString("") == .empty);
var stdout_buffer: [1024]u8 = undefined;
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 {
try wc.steps.ensureTotalCapacity(gpa, step_map.entries.capacity);
wc.steps.appendAssumeCapacity(.{
.name = try wc.addString(step.name),
.flags = .{ .tag = step.tag },
.deps = deps,
.max_rss = .fromBytes(step.max_rss),
.extra_index = switch (step.tag) {
@@ -273,6 +273,9 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
.install_artifact => e: {
const ia: *Step.InstallArtifact = @fieldParentPtr("step", step);
break :e try wc.addExtra(@as(Configuration.Step.InstallArtifact, .{
.flags = .{
.dylib_symlinks = ia.dylib_symlinks != null,
},
.dest_dir = try addInstallDir(wc, ia.dest_dir),
.dest_sub_path = try wc.addString(ia.dest_sub_path),
.emitted_bin = try addOptionalLazyPath(wc, ia.emitted_bin),
@@ -293,7 +296,54 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
.translate_c => @panic("TODO"),
.write_file => @panic("TODO"),
.update_source_files => @panic("TODO"),
.run => @panic("TODO"),
.run => e: {
const run: *Step.Run = @fieldParentPtr("step", step);
const captured_stdout: Configuration.OptionalString = if (run.captured_stdout) |cs|
.init(try wc.addString(cs.output.basename))
else
.none;
const captured_stderr: Configuration.OptionalString = if (run.captured_stderr) |cs|
.init(try wc.addString(cs.output.basename))
else
.none;
const extra_index = try wc.addExtra(@as(Configuration.Step.Run, .{
.flags = .{
.disable_zig_progress = run.disable_zig_progress,
.skip_foreign_checks = run.skip_foreign_checks,
.failing_to_execute_foreign_is_an_error = run.failing_to_execute_foreign_is_an_error,
.has_side_effects = run.has_side_effects,
.test_runner_mode = run.test_runner_mode,
.color = run.color,
.stdio = switch (run.stdio) {
.infer_from_args => .infer_from_args,
.inherit => .inherit,
.check => .check,
.zig_test => .zig_test,
},
.stdin = switch (run.stdin) {
.none => .none,
.bytes => .bytes,
.lazy_path => .lazy_path,
},
.stdout_trim_whitespace = if (run.captured_stdout) |cs| cs.trim_whitespace else .none,
.stderr_trim_whitespace = if (run.captured_stderr) |cs| cs.trim_whitespace else .none,
.stdio_limit = run.stdio_limit != .unlimited,
.producer = run.producer != null,
},
.file_inputs_len = @intCast(run.file_inputs.items.len),
.args_len = @intCast(run.argv.items.len),
.cwd = try addOptionalLazyPath(wc, run.cwd),
.captured_stdout = captured_stdout,
.captured_stderr = captured_stderr,
}));
std.log.err("TODO serialize the trailing Run step data", .{});
break :e extra_index;
},
.check_file => @panic("TODO"),
.check_object => @panic("TODO"),
.config_header => @panic("TODO"),
@@ -319,7 +369,7 @@ fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configu
.src_path => |src_path| i: {
const owner = builderToPackage(src_path.owner);
const sub_path = try wc.addString(src_path.sub_path);
break :i try wc.addExtra(@as(Configuration.OptionalLazyPath.SourcePath, .{
break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{
.flags = .{},
.owner = owner,
.sub_path = sub_path,
@@ -327,14 +377,14 @@ fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configu
},
.generated => |generated| i: {
const sub_path = try wc.addString(generated.sub_path);
break :i try wc.addExtra(@as(Configuration.OptionalLazyPath.Generated, .{
break :i try wc.addExtra(@as(Configuration.LazyPath.Generated, .{
.flags = .{ .up = @intCast(generated.up) },
.sub_path = sub_path,
}));
},
.cwd_relative => |cwd_relative_sub_path| i: {
const sub_path = try wc.addString(cwd_relative_sub_path);
break :i try wc.addExtra(@as(Configuration.OptionalLazyPath.Relative, .{
break :i try wc.addExtra(@as(Configuration.LazyPath.Relative, .{
.flags = .{ .base = .cwd },
.sub_path = sub_path,
}));
@@ -342,7 +392,7 @@ fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configu
.dependency => |dependency| i: {
const owner = builderToPackage(dependency.dependency.builder);
const sub_path = try wc.addString(dependency.sub_path);
break :i try wc.addExtra(@as(Configuration.OptionalLazyPath.SourcePath, .{
break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{
.flags = .{},
.owner = owner,
.sub_path = sub_path,
+3
View File
@@ -20,6 +20,9 @@ const Step = @import("../Step.zig");
fuzz_tests: std.ArrayList([]const u8),
cached_test_metadata: ?CachedTestMetadata = null,
/// Populated during the fuzz phase if this run step corresponds to a unit test
/// executable that contains fuzz tests.
rebuilt_executable: ?Path,
fn make(step: *Step, options: Step.MakeOptions) !void {
const b = step.owner;
+2 -2
View File
@@ -1,12 +1,12 @@
const Watch = @This();
const builtin = @import("builtin");
const std = @import("../std.zig");
const std = @import("std");
const Io = std.Io;
const Step = std.Build.Step;
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const fatal = std.process.fatal;
const Watch = @This();
const FsEvents = @import("Watch/FsEvents.zig");
os: Os,
+2 -24
View File
@@ -89,26 +89,10 @@ dep_output_file: ?*Output,
has_side_effects: bool,
test_runner_mode: bool = false,
/// Populated during the fuzz phase if this run step corresponds to a unit test
/// executable that contains fuzz tests.
rebuilt_executable: ?Path,
/// If this Run step was produced by a Compile step, it is tracked here.
producer: ?*Step.Compile,
pub const Color = enum {
/// `CLICOLOR_FORCE` is set, and `NO_COLOR` is unset.
enable,
/// `NO_COLOR` is set, and `CLICOLOR_FORCE` is unset.
disable,
/// If the build runner is using color, equivalent to `.enable`. Otherwise, equivalent to `.disable`.
inherit,
/// If stderr is captured or checked, equivalent to `.disable`. Otherwise, equivalent to `.inherit`.
auto,
/// The build runner does not modify the `CLICOLOR_FORCE` or `NO_COLOR` environment variables.
/// They are treated like normal variables, so can be controlled through `setEnvironmentVariable`.
manual,
};
pub const Color = std.Build.Configuration.Step.Run.Color;
pub const StdIn = union(enum) {
none,
@@ -192,12 +176,7 @@ pub const CapturedStdIo = struct {
trim_whitespace: TrimWhitespace = .none,
};
pub const TrimWhitespace = enum {
none,
all,
leading,
trailing,
};
pub const TrimWhitespace = std.Build.Configuration.Step.Run.TrimWhitespace;
};
pub fn create(owner: *std.Build, name: []const u8) *Run {
@@ -223,7 +202,6 @@ pub fn create(owner: *std.Build, name: []const u8) *Run {
.captured_stderr = null,
.dep_output_file = null,
.has_side_effects = false,
.rebuilt_executable = null,
.producer = null,
};
return run;
+115 -9
View File
@@ -196,17 +196,12 @@ pub const Wip = struct {
pub const Step = extern struct {
name: String,
flags: Flags,
deps: Deps,
max_rss: MaxRss,
/// Points into `extra` for step-specific data.
/// Points into `extra` for step-specific data. First element has flags
/// with `Tag`.
extra_index: u32,
pub const Flags = packed struct(u32) {
tag: Tag,
_: u24 = 0,
};
pub const Index = enum(u32) {
_,
};
@@ -232,10 +227,18 @@ pub const Step = extern struct {
};
pub const TopLevel = struct {
flags: Flags = .{},
description: String,
pub const Flags = packed struct(u32) {
tag: Tag = .top_level,
_: u24 = 0,
};
};
pub const InstallArtifact = struct {
flags: Flags,
dest_dir: InstallDir,
dest_sub_path: String,
emitted_bin: OptionalLazyPath,
@@ -252,12 +255,96 @@ pub const Step = extern struct {
/// Always a compile step.
artifact: Step.Index,
const Flags = packed struct(u32) {
pub const Flags = packed struct(u32) {
tag: Tag = .install_artifact,
dylib_symlinks: bool,
_: u23 = 0,
};
};
/// Trailing:
/// * LazyPath for each file_inputs_len
/// * Arg for each args_len
/// * environ_map if corresponding flag is set
/// * stdin: Bytes, // if StdIn.bytes is chosen
/// * stdin: LazyPath, // if StdIn.lazy_path is chosen
/// * checks: Checks, // if StdIo.check is chosen
/// * stdio_limit: u64, // if stdio_limit is set
/// * producer: Step.Index, // if producer is set. always compile step
pub const Run = struct {
flags: Flags,
file_inputs_len: u32,
args_len: u32,
cwd: OptionalLazyPath,
captured_stdout: OptionalString, // basename
captured_stderr: OptionalString, // basename
/// Trailing:
/// * String if prefix set
/// * String if suffix set
/// * String if basename set
/// * Step.Index which is always a compile step if tag is artifact
/// * LazyPath if tag is path_file, path_directory, or file_content
pub const Arg = struct {
flags: Arg.Flags,
pub const Flags = packed struct(u32) {
tag: Arg.Tag,
prefix: bool,
suffix: bool,
basename: bool,
/// Implies Tag is output_file
dep_file: bool,
_: u20 = 0,
};
pub const Tag = enum(u8) {
artifact,
path_file,
path_directory,
file_content,
bytes,
output_file,
output_directory,
};
};
pub const Color = enum(u4) {
/// `CLICOLOR_FORCE` is set, and `NO_COLOR` is unset.
enable,
/// `NO_COLOR` is set, and `CLICOLOR_FORCE` is unset.
disable,
/// If the build runner is using color, equivalent to `.enable`. Otherwise, equivalent to `.disable`.
inherit,
/// If stderr is captured or checked, equivalent to `.disable`. Otherwise, equivalent to `.inherit`.
auto,
/// The build runner does not modify the `CLICOLOR_FORCE` or `NO_COLOR` environment variables.
/// They are treated like normal variables, so can be controlled through `setEnvironmentVariable`.
manual,
};
pub const StdIn = enum(u2) { none, bytes, lazy_path };
pub const TrimWhitespace = enum(u2) { none, all, leading, trailing };
pub const StdIo = enum(u2) { infer_from_args, inherit, check, zig_test };
pub const Flags = packed struct(u32) {
tag: Tag = .run,
disable_zig_progress: bool,
skip_foreign_checks: bool,
failing_to_execute_foreign_is_an_error: bool,
has_side_effects: bool,
test_runner_mode: bool,
color: Color,
stdin: StdIn,
stdio: StdIo,
stdout_trim_whitespace: TrimWhitespace,
stderr_trim_whitespace: TrimWhitespace,
stdio_limit: bool,
producer: bool,
_: u5 = 0,
};
};
};
pub const MaxRss = enum(u32) {
@@ -274,10 +361,15 @@ pub const MaxRss = enum(u32) {
}
};
/// An index into `extra`.
/// An index into `extra`, or `null`.
pub const OptionalLazyPath = enum(u32) {
none = maxInt(u32),
_,
};
/// An index into `extra`.
pub const LazyPath = enum(u32) {
_,
pub const Tag = enum(u8) {
/// A source file path relative to build root.
@@ -368,8 +460,22 @@ pub const InstallDir = enum(u32) {
}
};
/// Points into `string_bytes`, null-terminated.
pub const OptionalString = enum(u32) {
empty = 0,
none = maxInt(u32),
_,
pub fn init(s: String) OptionalString {
const result: OptionalString = @enumFromInt(@intFromEnum(s));
assert(result != .none);
return result;
}
};
/// Points into `string_bytes`, null-terminated.
pub const String = enum(u32) {
empty = 0,
_,
pub fn slice(index: String, c: *const Configuration) [:0]const u8 {