evalZigProcess
Assumes that argv contains --listen=- and that the process being spawned
is the zig compiler - the same version that compiled the build runner.
Function parameters
Parameters
Type definitions in this namespace
Types
Functions in this namespace
Functions
- make
- If the Step's `make` function reports `error.MakeFailed`, it indicates they
- dump
- For debugging purposes, prints identifying information about this Step.
- evalZigProcess
- Assumes that argv contains `--listen=-` and that the process being spawned
- installFile
- Wrapper around `std.fs.Dir.updateFile` that handles verbose and error output.
- installDir
- Wrapper around `std.fs.Dir.makePathStatus` that handles verbose and error output.
- cacheHit
- Prefer `cacheHitAndWatch` unless you already added watch inputs
- cacheHitAndWatch
- Clears previous watch inputs, if any, and then populates watch inputs from
- writeManifest
- Prefer `writeManifestAndWatch` unless you already added watch inputs
- writeManifestAndWatch
- Clears previous watch inputs, if any, and then populates watch inputs from
- singleUnchangingWatchInput
- For steps that have a single input that never changes when re-running `make`.
- addWatchInput
- Places a *file* dependency on the path.
- addDirectoryWatchInput
- Any changes inside the directory will trigger invalidation.
- addDirectoryWatchInputFromPath
- Any changes inside the directory will trigger invalidation.
- reset
- Implementation detail of file watching and forced rebuilds.
- recursiveReset
- Implementation detail of file watching.
Source
Implementation
pub fn evalZigProcess(
s: *Step,
argv: []const []const u8,
prog_node: std.Progress.Node,
watch: bool,
web_server: ?*Build.WebServer,
gpa: Allocator,
) !?Path {
if (s.getZigProcess()) |zp| update: {
assert(watch);
if (std.Progress.have_ipc) if (zp.progress_ipc_fd) |fd| prog_node.setIpcFd(fd);
const result = zigProcessUpdate(s, zp, watch, web_server, gpa) catch |err| switch (err) {
error.BrokenPipe => {
// Process restart required.
const term = zp.child.wait() catch |e| {
return s.fail("unable to wait for {s}: {s}", .{ argv[0], @errorName(e) });
};
_ = term;
s.clearZigProcess(gpa);
break :update;
},
else => |e| return e,
};
if (s.result_error_bundle.errorMessageCount() > 0)
return s.fail("{d} compilation errors", .{s.result_error_bundle.errorMessageCount()});
if (s.result_error_msgs.items.len > 0 and result == null) {
// Crash detected.
const term = zp.child.wait() catch |e| {
return s.fail("unable to wait for {s}: {s}", .{ argv[0], @errorName(e) });
};
s.result_peak_rss = zp.child.resource_usage_statistics.getMaxRss() orelse 0;
s.clearZigProcess(gpa);
try handleChildProcessTerm(s, term, null, argv);
return error.MakeFailed;
}
return result;
}
assert(argv.len != 0);
const b = s.owner;
const arena = b.allocator;
try handleChildProcUnsupported(s, null, argv);
try handleVerbose(s.owner, null, argv);
var child = std.process.Child.init(argv, arena);
child.env_map = &b.graph.env_map;
child.stdin_behavior = .Pipe;
child.stdout_behavior = .Pipe;
child.stderr_behavior = .Pipe;
child.request_resource_usage_statistics = true;
child.progress_node = prog_node;
child.spawn() catch |err| return s.fail("failed to spawn zig compiler {s}: {s}", .{
argv[0], @errorName(err),
});
const zp = try gpa.create(ZigProcess);
zp.* = .{
.child = child,
.poller = std.Io.poll(gpa, ZigProcess.StreamEnum, .{
.stdout = child.stdout.?,
.stderr = child.stderr.?,
}),
.progress_ipc_fd = if (std.Progress.have_ipc) child.progress_node.getIpcFd() else {},
};
if (watch) s.setZigProcess(zp);
defer if (!watch) {
zp.poller.deinit();
gpa.destroy(zp);
};
const result = try zigProcessUpdate(s, zp, watch, web_server, gpa);
if (!watch) {
// Send EOF to stdin.
zp.child.stdin.?.close();
zp.child.stdin = null;
const term = zp.child.wait() catch |err| {
return s.fail("unable to wait for {s}: {s}", .{ argv[0], @errorName(err) });
};
s.result_peak_rss = zp.child.resource_usage_statistics.getMaxRss() orelse 0;
// Special handling for Compile step that is expecting compile errors.
if (s.cast(Compile)) |compile| switch (term) {
.Exited => {
// Note that the exit code may be 0 in this case due to the
// compiler server protocol.
if (compile.expect_errors != null) {
return error.NeedCompileErrorCheck;
}
},
else => {},
};
try handleChildProcessTerm(s, term, null, argv);
}
// This is intentionally printed for failure on the first build but not for
// subsequent rebuilds.
if (s.result_error_bundle.errorMessageCount() > 0) {
return s.fail("the following command failed with {d} compilation errors:\n{s}", .{
s.result_error_bundle.errorMessageCount(),
try allocPrintCmd(arena, null, argv),
});
}
return result;
}