feature. See also
. The project being documented here (as the example) is the Zig library itself.
Run.spawnChildAndCollect
fn spawnChildAndCollect(
arena: Allocator,
run_index: Configuration.Step.Index,
run: *Run,
maker: *Maker,
progress_node: std.Progress.Node,
argv: []const []const u8,
environ_map: *EnvMap,
has_side_effects: bool,
fuzz_context: ?FuzzContext,
) !?EvalGenericResult
File
Code
fn spawnChildAndCollect(
arena: Allocator,
run_index: Configuration.Step.Index,
run: *Run,
maker: *Maker,
progress_node: std.Progress.Node,
argv: []const []const u8,
environ_map: *EnvMap,
has_side_effects: bool,
fuzz_context: ?FuzzContext,
) !?EvalGenericResult {
const step = maker.stepByIndex(run_index);
const graph = maker.graph;
const io = graph.io;
const gpa = maker.gpa;
const conf = &maker.scanned_config.configuration;
const conf_step = run_index.ptr(conf);
const conf_run = conf_step.extended.get(conf.extra).run;
if (fuzz_context != null) {
assert(!has_side_effects);
assert(conf_run.flags.stdio == .zig_test);
}
const child_cwd: process.Child.Cwd = if (conf_run.cwd.value) |lazy_cwd|
.{ .path = try maker.resolveLazyPathIndexAbs(arena, lazy_cwd, run_index) }
else
.inherit;
const cwd_string = switch (child_cwd) {
.path => |p| p,
.dir => unreachable,
.inherit => null,
};
// function returns an error because only after this function returns
// does the logic determine whether the child process termination was
// success or failure.
step.setFailedCommand(gpa, argv, .{
.cwd = cwd_string,
.child_env = environ_map,
.parent_env = &graph.environ_map,
});
try step.handleChildProcUnsupported(maker);
var spawn_options: process.SpawnOptions = .{
.argv = argv,
.cwd = child_cwd,
.environ_map = environ_map,
.request_resource_usage_statistics = true,
.stdin = if (conf_run.stdin.u != .none) s: {
assert(conf_run.flags.stdio != .inherit);
break :s .pipe;
} else switch (conf_run.flags.stdio) {
.infer_from_args => if (has_side_effects) .inherit else .ignore,
.inherit => .inherit,
.check => .ignore,
.zig_test => .pipe,
},
.stdout = if (conf_run.captured_stdout.value != null) .pipe else switch (conf_run.flags.stdio) {
.infer_from_args => if (has_side_effects) .inherit else .ignore,
.inherit => .inherit,
.check => if (checksContainStdout(&conf_run)) .pipe else .ignore,
.zig_test => .pipe,
},
.stderr = if (conf_run.captured_stderr.value != null) .pipe else switch (conf_run.flags.stdio) {
.infer_from_args => if (has_side_effects) .inherit else .pipe,
.inherit => .inherit,
.check => .pipe,
.zig_test => .pipe,
},
};
if (conf_run.flags.stdio == .zig_test) {
try setColorEnvironmentVariables(&conf_run, environ_map, graph.stderr_mode.?);
const started: Io.Clock.Timestamp = .now(io, .awake);
const result = evalZigTest(run, run_index, maker, progress_node, spawn_options, fuzz_context) catch |err| switch (err) {
error.Canceled => |e| return e,
else => |e| e,
};
step.result_duration_ns = @intCast(started.untilNow(io).raw.nanoseconds);
try result;
return null;
} else {
const inherit = spawn_options.stdout == .inherit or spawn_options.stderr == .inherit;
if (!conf_run.flags.disable_zig_progress and !inherit) {
spawn_options.progress_node = progress_node;
}
const terminal_mode: Io.Terminal.Mode = if (inherit) m: {
const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
break :m stderr.terminal_mode;
} else .no_color;
defer if (inherit) io.unlockStderr();
try setColorEnvironmentVariables(&conf_run, environ_map, terminal_mode);
const started: Io.Clock.Timestamp = .now(io, .awake);
const result = evalGeneric(arena, run_index, maker, spawn_options) catch |err| switch (err) {
error.Canceled => |e| return e,
else => |e| e,
};
step.result_duration_ns = @intCast(started.untilNow(io).raw.nanoseconds);
return try result;
}
}