Function evalZigProcess [src]

Assumes that argv contains --listen=- and that the process being spawned is the zig compiler - the same version that compiled the build runner.

Prototype

pub fn evalZigProcess( s: *Step, argv: []const []const u8, prog_node: std.Progress.Node, watch: bool, ) !?Path

Parameters

s: *Stepargv: []const []const u8prog_node: std.Progress.Nodewatch: bool

Source

pub fn evalZigProcess( s: *Step, argv: []const []const u8, prog_node: std.Progress.Node, watch: bool, ) !?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) 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(); 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(); try handleChildProcessTerm(s, term, null, argv); return error.MakeFailed; } return result; } assert(argv.len != 0); const b = s.owner; const arena = b.allocator; const gpa = arena; 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(); const result = try zigProcessUpdate(s, zp, watch); 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; }