diff --git a/ci/x86_64-linux-debug-llvm.sh b/ci/x86_64-linux-debug-llvm.sh index 1cde5f8a1a42faf82f129406bc9160bf90199a73..a97b9f01baa6c1ad1df088297e9ae29c43e14dc5 100755 --- a/ci/x86_64-linux-debug-llvm.sh +++ b/ci/x86_64-linux-debug-llvm.sh @@ -49,7 +49,6 @@ stage3-debug/bin/zig build \ -Dno-lib stage3-debug/bin/zig build test docs \ - --maker-opt=Debug \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dlldb=$HOME/deps/lldb-zig/Debug-33ec8d3c11/bin/lldb \ -Dlibc-test-path=$HOME/deps/libc-test-f2bac77 \ diff --git a/ci/x86_64-linux-debug.sh b/ci/x86_64-linux-debug.sh index 8defcf95f2197c06b1cfff55580862c9e8d1db7c..3fc8e5484f394159491f6b94bcbe2586f0e06445 100755 --- a/ci/x86_64-linux-debug.sh +++ b/ci/x86_64-linux-debug.sh @@ -48,6 +48,7 @@ stage3-debug/bin/zig build \ -Dno-lib stage3-debug/bin/zig build test docs \ + --maker-opt=Debug \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dlldb=$HOME/deps/lldb-zig/Debug-33ec8d3c11/bin/lldb \ -fqemu \ diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig index 5aaf6e9d13f4255f84323b2d8876065ed094057d..af3253fb0803e8d4f2947a8a03b4559bbb0dae69 100644 --- a/lib/compiler/Maker.zig +++ b/lib/compiler/Maker.zig @@ -16,6 +16,7 @@ const fmt = std.fmt; const log = std.log; const mem = std.mem; const process = std.process; +const Color = std.zig.Color; const Fuzz = @import("Maker/Fuzz.zig"); const Graph = @import("Maker/Graph.zig"); @@ -55,12 +56,59 @@ error_style: ErrorStyle, multiline_errors: MultilineErrors, summary: Summary, +var safe_allocator_instance: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); +var stdio_buffer_allocation: [256]u8 = undefined; +var stdout_writer_allocation: Io.File.Writer = undefined; +var debug_maker_leaks: bool = false; + +const is_debug_mode = builtin.mode == .Debug; +const use_safe_allocator = switch (builtin.mode) { + .Debug, .ReleaseSafe => true, + .ReleaseFast, .ReleaseSmall => false, +}; + +const InstallPaths = struct { + prefix: Path, + lib: Path, + bin: Path, + include: Path, +}; + +const PrintNode = struct { + parent: ?*PrintNode, + last: bool = false, +}; + +const ErrorStyle = enum { + verbose, + minimal, + verbose_clear, + minimal_clear, + fn verboseContext(s: ErrorStyle) bool { + return switch (s) { + .verbose, .verbose_clear => true, + .minimal, .minimal_clear => false, + }; + } + fn clearOnUpdate(s: ErrorStyle) bool { + return switch (s) { + .verbose, .minimal => false, + .verbose_clear, .minimal_clear => true, + }; + } +}; +const MultilineErrors = enum { indent, newline, none }; +const Summary = enum { all, new, failures, line, none }; + pub fn main(init: process.Init.Minimal) !void { - // The build runner is often short-lived, but thanks to `--watch` and `--webui`, that's not - // always the case. So, we do need a true gpa for some things. - var safe_gpa_state: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); - defer _ = safe_gpa_state.deinit(); - const gpa = safe_gpa_state.allocator(); + // The build runner is long-lived in the following use cases: + // * `--watch` mode + // * `--webui` mode + // * A project that has a large, complex build graph. + const gpa = if (use_safe_allocator) safe_allocator_instance.allocator() else std.heap.smp_allocator; + defer if (use_safe_allocator) { + _ = safe_allocator_instance.deinit(); + }; var threaded: std.Io.Threaded = .init(gpa, .{ .environ = init.environ, @@ -689,13 +737,6 @@ fn countSubProcesses(maker: *Maker) usize { return count; } -const InstallPaths = struct { - prefix: Path, - lib: Path, - bin: Path, - include: Path, -}; - pub fn stepByIndex(maker: *const Maker, i: Configuration.Step.Index) *Step { return &maker.steps[@intFromEnum(i)]; } @@ -1018,6 +1059,7 @@ fn makeStepNames( fn deinit(maker: *Maker) void { const gpa = maker.gpa; for (maker.steps) |*step| { + step.clearResultStderr(gpa); step.clearFailedCommand(gpa); step.clearErrorBundle(gpa); step.inputs.deinit(gpa); @@ -1424,11 +1466,6 @@ fn printStepFailure( } } -const PrintNode = struct { - parent: ?*PrintNode, - last: bool = false, -}; - fn printPrefix(node: *PrintNode, stderr: Io.Terminal) !void { const parent = node.parent orelse return; const writer = stderr.writer; @@ -1657,28 +1694,6 @@ fn argsRest(args: []const [:0]const u8, idx: usize) ?[]const [:0]const u8 { return args[idx..]; } -const Color = std.zig.Color; -const ErrorStyle = enum { - verbose, - minimal, - verbose_clear, - minimal_clear, - fn verboseContext(s: ErrorStyle) bool { - return switch (s) { - .verbose, .verbose_clear => true, - .minimal, .minimal_clear => false, - }; - } - fn clearOnUpdate(s: ErrorStyle) bool { - return switch (s) { - .verbose, .minimal => false, - .verbose_clear, .minimal_clear => true, - }; - } -}; -const MultilineErrors = enum { indent, newline, none }; -const Summary = enum { all, new, failures, line, none }; - fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn { log.info("to access the help menu: zig build -h", .{}); fatal(f, args); @@ -1701,9 +1716,6 @@ fn cleanTmpFiles(maker: *Maker, steps: []const Configuration.Step.Index) void { } } -var stdio_buffer_allocation: [256]u8 = undefined; -var stdout_writer_allocation: Io.File.Writer = undefined; - fn initStdoutWriter(io: Io) *Writer { stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation); return &stdout_writer_allocation.interface; @@ -2043,8 +2055,6 @@ fn removePoisonedConfiguration(io: Io, scanned_config: *const ScannedConfig) voi } } -const is_debug_mode = builtin.mode == .Debug; -var debug_maker_leaks: bool = false; inline fn debugMakerLeaks() bool { if (!is_debug_mode) return false; return debug_maker_leaks; diff --git a/lib/compiler/Maker/PkgConfig.zig b/lib/compiler/Maker/PkgConfig.zig index 09fcbacfbdab1c07973a6fabd942f406a3ebb941..56bf8f08d721aee1cfd0e678cc8f320e3b540d98 100644 --- a/lib/compiler/Maker/PkgConfig.zig +++ b/lib/compiler/Maker/PkgConfig.zig @@ -2,6 +2,7 @@ const std = @import("std"); const Io = std.Io; const mem = std.mem; const assert = std.debug.assert; +const Allocator = std.mem.Allocator; const Maker = @import("../Maker.zig"); const Step = @import("Step.zig"); @@ -23,6 +24,7 @@ pub const Result = std.zig.PkgConfig.Parsed; pub fn run( maker: *Maker, step: *Step, + arena: Allocator, progress_node: std.Progress.Node, lib_name: []const u8, /// If true, reports failure error messages on step rather than returning @@ -31,7 +33,6 @@ pub fn run( ) RunError!Result { const pc = &maker.pkg_config; const graph = maker.graph; - const arena = graph.arena; // TODO don't leak into process arena const pkg_config_exe = getExe(graph); const pkgs = try getPkgs(maker, step, progress_node, force); @@ -41,7 +42,7 @@ pub fn run( }; const pkg = pkgs.all[found_index]; - const stdout = try captureChildProcess(maker, step, .{ + const stdout = try captureChildProcess(maker, step, arena, .{ .argv = &.{ pkg_config_exe, pkg.name, "--cflags", "--libs" }, .progress_node = progress_node, .allow_failure = !force, @@ -69,11 +70,16 @@ fn getExe(graph: *const Graph) []const u8 { return std.zig.PkgConfig.exe(&graph.environ_map); } -fn getPkgs(maker: *Maker, step: *Step, progress_node: std.Progress.Node, force: bool) RunError!std.zig.PkgConfig { +fn getPkgs( + maker: *Maker, + step: *Step, + progress_node: std.Progress.Node, + force: bool, +) RunError!std.zig.PkgConfig { const graph = maker.graph; - const arena = graph.arena; // TODO don't leak into process arena const io = graph.io; const pc = &maker.pkg_config; + const arena = graph.arena; try pc.mutex.lock(io); defer pc.mutex.unlock(io); @@ -81,7 +87,7 @@ fn getPkgs(maker: *Maker, step: *Step, progress_node: std.Progress.Node, force: if (pc.pkgs) |pkgs| return pkgs; const pkg_config_exe = getExe(graph); - const stdout = try captureChildProcess(maker, step, .{ + const stdout = try captureChildProcess(maker, step, arena, .{ .argv = &.{ pkg_config_exe, "--list-all" }, .progress_node = progress_node, .allow_failure = !force, @@ -102,11 +108,12 @@ fn getPkgs(maker: *Maker, step: *Step, progress_node: std.Progress.Node, force: return result; } -fn captureChildProcess(maker: *Maker, step: *Step, options: Step.CaptureChildProcessOptions) ![]const u8 { - const captured = step.captureChildProcess(maker, options) catch |err| switch (err) { +fn captureChildProcess(maker: *Maker, step: *Step, arena: Allocator, options: Step.CaptureChildProcessOptions) ![]const u8 { + const captured = step.captureChildProcess(maker, arena, options) catch |err| switch (err) { error.FileNotFound => return error.PkgConfigUnavailable, else => |e| return e, }; + if (captured.stderr.len != 0) try step.setResultStderr(maker.gpa, captured.stderr); assert(step.result_failed_command != null); if (captured.term.success()) return captured.stdout; if (!options.allow_failure) return step.fail(maker, "{s} {f}", .{ options.argv[0], captured.term }); diff --git a/lib/compiler/Maker/Step.zig b/lib/compiler/Maker/Step.zig index 69d3676c32f4567c40cd97be29de8196f65f7756..6a6f5c1cf3718c2dce6c957283e528d7b0844ac4 100644 --- a/lib/compiler/Maker/Step.zig +++ b/lib/compiler/Maker/Step.zig @@ -54,8 +54,10 @@ dependants: std.ArrayList(Configuration.Step.Index) = .empty, inputs: Inputs = .init, pending_deps: u32 = undefined, +/// Array list and internal memory owned by process arena. result_error_msgs: std.ArrayList([]const u8) = .empty, result_error_bundle: std.zig.ErrorBundle = .empty, +/// Owned by `Maker.gpa`. result_stderr: []const u8 = "", result_cached: bool = false, /// Indicates error information is missing due to allocation failure. @@ -310,9 +312,8 @@ pub fn reset(step: *Step, maker: *Maker) void { const gpa = maker.gpa; clearFailedCommand(step, gpa); - + clearResultStderr(step, gpa); step.result_error_msgs.clearRetainingCapacity(); - step.result_stderr = ""; step.result_cached = false; step.result_duration_ns = null; step.result_peak_rss = 0; @@ -332,20 +333,23 @@ pub const CaptureChildProcessOptions = struct { allow_failure: bool = false, }; -/// Populates `s.result_failed_command`. -pub fn captureChildProcess(s: *Step, maker: *Maker, options: CaptureChildProcessOptions) !std.process.RunResult { +/// Populates `s.result_failed_command` unconditionally. +pub fn captureChildProcess( + s: *Step, + maker: *Maker, + allocator: Allocator, + options: CaptureChildProcessOptions, +) !std.process.RunResult { const gpa = maker.gpa; const graph = maker.graph; - const arena = graph.arena; // TODO stop leaking into process arena const io = graph.io; - clearFailedCommand(s, gpa); - s.result_failed_command = try std.zig.allocPrintCmd(gpa, options.argv, .{}); + s.setFailedCommand(gpa, options.argv, .{}); try handleChildProcUnsupported(s, maker); try graph.handleVerbose(null, null, options.argv); - const result = std.process.run(arena, io, .{ + const result = std.process.run(allocator, io, .{ .argv = options.argv, .environ_map = options.environ_map orelse &graph.environ_map, .progress_node = options.progress_node, @@ -358,7 +362,7 @@ pub fn captureChildProcess(s: *Step, maker: *Maker, options: CaptureChildProcess return s.fail(maker, "failed to run {s}: {t}", .{ options.argv[0], err }); }; - if (result.stderr.len > 0) try s.result_error_msgs.append(arena, result.stderr); + if (result.stderr.len > 0) try s.result_error_msgs.append(graph.arena, result.stderr); return result; } @@ -375,6 +379,21 @@ pub fn clearFailedCommand(s: *Step, gpa: Allocator) void { } } +pub fn setFailedCommand( + s: *Step, + gpa: Allocator, + argv: []const []const u8, + options: std.zig.AllocPrintCmdOptions, +) void { + s.clearFailedCommand(gpa); + s.result_failed_command = std.zig.allocPrintCmd(gpa, argv, options) catch |err| switch (err) { + error.OutOfMemory => { + s.result_oom = true; + return; + }, + }; +} + pub const FailError = error{ OutOfMemory, MakeFailed }; pub fn fail(step: *Step, maker: *const Maker, comptime fmt: []const u8, args: anytype) FailError { @@ -410,7 +429,8 @@ pub const ZigProcess = struct { /// Assumes that argv contains `--listen=-` and that the process being spawned /// is the zig compiler - the same version that compiled the build runner. -/// Populates `s.result_failed_command`. +/// +/// Populates `s.result_failed_command` on failure. pub fn evalZigProcess( step_index: Configuration.Step.Index, maker: *Maker, @@ -424,8 +444,7 @@ pub fn evalZigProcess( const io = graph.io; // If an error occurs, it's happened in this command: - clearFailedCommand(s, gpa); - s.result_failed_command = try std.zig.allocPrintCmd(gpa, argv, .{}); + errdefer s.setFailedCommand(gpa, argv, .{}); if (s.getZigProcess()) |zp| update: { assert(watch); @@ -683,16 +702,12 @@ fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void { }; } -/// Asserts that the caller has already populated `s.result_failed_command`. pub inline fn handleChildProcUnsupported(s: *Step, maker: *Maker) FailError!void { - assert(s.result_failed_command != null); if (!std.process.can_spawn) return s.fail(maker, "unable to spawn process: host cannot spawn child processes", .{}); } -/// Asserts that the caller has already populated `s.result_failed_command`. pub fn handleChildProcessTerm(s: *Step, maker: *Maker, term: std.process.Child.Term) FailError!void { - assert(s.result_failed_command != null); if (!term.success()) return s.fail(maker, "process {f}", .{term}); } @@ -861,3 +876,19 @@ fn oomWrap(s: *Step, result: error{OutOfMemory}!void) void { s.result_oom = true; }; } + +pub fn clearResultStderr(step: *Step, gpa: Allocator) void { + if (step.result_stderr.len != 0) { + gpa.free(step.result_stderr); + step.result_stderr = ""; + } +} + +pub fn setResultStderr(step: *Step, gpa: Allocator, bytes: []const u8) Allocator.Error!void { + takeResultStderr(step, gpa, try gpa.dupe(u8, bytes)); +} + +pub fn takeResultStderr(step: *Step, gpa: Allocator, owned: []const u8) void { + clearResultStderr(step, gpa); + step.result_stderr = owned; +} diff --git a/lib/compiler/Maker/Step/Compile.zig b/lib/compiler/Maker/Step/Compile.zig index 0b66dc282c801cd3cabff5c0a72e69cb36aab0c2..67006980770166273380ae96f8d592051aab8497 100644 --- a/lib/compiler/Maker/Step/Compile.zig +++ b/lib/compiler/Maker/Step/Compile.zig @@ -328,10 +328,10 @@ fn lowerZigArgs( const pkg_conf_node = progress_node.start("pkg-config", 0); defer pkg_conf_node.end(); - if (PkgConfig.run(maker, step, pkg_conf_node, system_lib_name, force)) |result| { - try zig_args.appendSlice(gpa, result.cflags); - try zig_args.appendSlice(gpa, result.libs); - try seen_system_libs.put(arena, system_lib.name, result.cflags); + if (PkgConfig.run(maker, step, arena, pkg_conf_node, system_lib_name, force)) |pc| { + try zig_args.appendSlice(gpa, pc.cflags); + try zig_args.appendSlice(gpa, pc.libs); + try seen_system_libs.put(arena, system_lib.name, pc.cflags); break :l; } else |err| switch (err) { error.PkgConfigUnavailable, @@ -960,8 +960,8 @@ pub fn rebuildInFuzzMode( const arena = arena_allocator.allocator(); step.result_error_msgs.clearRetainingCapacity(); - step.result_stderr = ""; - + step.clearResultStderr(gpa); + step.clearErrorBundle(gpa); step.result_error_bundle.deinit(gpa); step.result_error_bundle = std.zig.ErrorBundle.empty; diff --git a/lib/compiler/Maker/Step/Fmt.zig b/lib/compiler/Maker/Step/Fmt.zig index 281686bed57d488d5db088d9f1c2593edf4f6371..ef54df4fdc5c06942b4b8943f26bf01b7587cc59 100644 --- a/lib/compiler/Maker/Step/Fmt.zig +++ b/lib/compiler/Maker/Step/Fmt.zig @@ -43,7 +43,7 @@ pub fn make( argv.appendAssumeCapacity(try maker.resolveLazyPathIndexAbs(arena, lp, step_index)); } - const run_result = step.captureChildProcess(maker, .{ + const run_result = step.captureChildProcess(maker, arena, .{ .progress_node = progress_node, .argv = argv.items, .allow_failure = false, diff --git a/lib/compiler/Maker/Step/Run.zig b/lib/compiler/Maker/Step/Run.zig index e8d8f4f2ba56842a8daf7d4fe4ce0fb8da994bf8..1fb85a908c632e16121c3c574dd212ec79cc3b77 100644 --- a/lib/compiler/Maker/Step/Run.zig +++ b/lib/compiler/Maker/Step/Run.zig @@ -713,7 +713,7 @@ const FuzzTestRunner = struct { } } - fn listen(f: *FuzzTestRunner, arena: Allocator) !void { + fn listen(f: *FuzzTestRunner) !void { const maker = f.ctx.fuzz.maker; const graph = maker.graph; const io = graph.io; @@ -737,7 +737,7 @@ const FuzzTestRunner = struct { else => |read_e| return read_e, }), 2 => try f.completeStderrRead(id, result.file_read_streaming catch |e| switch (e) { - error.EndOfStream => return f.instanceEos(arena, id), + error.EndOfStream => return f.instanceEos(id), else => |read_e| return read_e, }), else => unreachable, @@ -899,8 +899,9 @@ const FuzzTestRunner = struct { } }); } - fn instanceEos(f: *FuzzTestRunner, arena: Allocator, id: u32) !void { + fn instanceEos(f: *FuzzTestRunner, id: u32) !void { const maker = f.ctx.fuzz.maker; + const gpa = maker.gpa; const instance = &f.instances[id]; const run_index = f.run_index; @@ -912,7 +913,7 @@ const FuzzTestRunner = struct { instance.child.stdin = null; const term = try instance.child.wait(io); if (!termMatches(.{ .exited = 0 }, term)) { - step.result_stderr = try f.mergedStderr(arena); + step.takeResultStderr(gpa, try f.mergedStderr(gpa)); try f.saveCrash(id, term); return step.fail(maker, "test process unexpectedly {f}", .{fmtTerm(term)}); } @@ -1055,7 +1056,7 @@ const FuzzTestRunner = struct { } } - fn mergedStderr(f: *FuzzTestRunner, arena: Allocator) Allocator.Error![]const u8 { + fn mergedStderr(f: *FuzzTestRunner, gpa: Allocator) Allocator.Error![]const u8 { // Collect any available stderr while (f.batch.next()) |completion| { if (completion.index % 3 != 2) continue; @@ -1065,7 +1066,7 @@ const FuzzTestRunner = struct { var stderr_len: usize = 0; for (f.instances) |*instance| stderr_len += instance.stderr.items.len; - const stderr = try arena.alloc(u8, stderr_len); + const stderr = try gpa.alloc(u8, stderr_len); stderr_len = 0; for (f.instances) |*instance| { @@ -1086,13 +1087,12 @@ fn evalFuzzTest( var f: FuzzTestRunner = try .init(run, run_index, fuzz_context, progress_node, spawn_options); defer f.deinit(); try f.startInstances(); - try f.listen(fuzz_context.fuzz.maker.graph.arena); + try f.listen(); } const StdioPollEnum = enum { stdout, stderr }; fn evalZigTest( - arena: Allocator, run: *Run, run_index: Configuration.Step.Index, maker: *Maker, @@ -1140,7 +1140,7 @@ fn evalZigTest( }; switch (try waitZigTest( - arena, + graph.arena, run, run_index, maker, @@ -1158,7 +1158,7 @@ fn evalZigTest( error.ReadFailed => return stderr_fr.err.?, error.EndOfStream => {}, } - step.result_stderr = try arena.dupe(u8, stderr_fr.interface.buffered()); + step.takeResultStderr(gpa, try multi_reader.toOwnedSlice(1)); // Clean up everything and wait for the child to exit. child.stdin.?.close(io); @@ -1180,8 +1180,9 @@ fn evalZigTest( .no_poll => |no_poll| { // This might be a success (we requested exit and the child dutifully closed stdout) or // a crash of some kind. Either way, the child will terminate by itself -- wait for it. - const stderr_reader = multi_reader.reader(1); - const stderr_owned = try arena.dupe(u8, stderr_reader.buffered()); + const stderr_owned = try multi_reader.toOwnedSlice(1); + var keep_stderr_owned = false; + defer if (!keep_stderr_owned) gpa.free(stderr_owned); // Clean up everything and wait for the child to exit. child.stdin.?.close(io); @@ -1209,7 +1210,9 @@ fn evalZigTest( } // Report an error if the child terminated uncleanly or if we were still trying to run more tests. - step.result_stderr = stderr_owned; + step.takeResultStderr(gpa, stderr_owned); + keep_stderr_owned = true; + const tests_done = test_metadata != null and test_metadata.?.next_index == std.math.maxInt(u32); if (!tests_done or !termMatches(.{ .exited = 0 }, term)) { // The individual unit test results are irrelevant: the test runner itself broke! @@ -1234,9 +1237,10 @@ fn evalZigTest( return; }, .timeout => |timeout| { - const stderr_reader = multi_reader.reader(1); - const stderr = stderr_reader.buffered(); - stderr_reader.tossBuffered(); + const stderr_owned = try multi_reader.toOwnedSlice(1); + var keep_stderr_owned = false; + defer if (!keep_stderr_owned) gpa.free(stderr_owned); + if (timeout.active_test_index) |test_index| { // A test was running. Report the timeout against that test, and continue on to // the next test. @@ -1245,16 +1249,20 @@ fn evalZigTest( try step.addError(maker, "'{s}' timed out after {f}{s}{s}", .{ test_metadata.?.testName(test_index), Io.Duration{ .nanoseconds = timeout.ns_elapsed }, - if (stderr.len != 0) " with stderr:\n" else "", - std.mem.trim(u8, stderr, "\n"), + if (stderr_owned.len != 0) " with stderr:\n" else "", + std.mem.trim(u8, stderr_owned, "\n"), }); continue; } // Just log an error and let the child be killed. - step.result_stderr = try arena.dupe(u8, stderr); + step.takeResultStderr(gpa, stderr_owned); + keep_stderr_owned = true; + // The individual unit test results in `results` are irrelevant: the test runner // is broken! Fail immediately without populating `s.test_results`. - return step.fail(maker, "test runner failed to respond for {f}", .{Io.Duration{ .nanoseconds = timeout.ns_elapsed }}); + return step.fail(maker, "test runner failed to respond for {f}", .{ + Io.Duration{ .nanoseconds = timeout.ns_elapsed }, + }); }, } comptime unreachable; @@ -1456,8 +1464,8 @@ fn evalGeneric( try multi_reader.checkAnyError(); - stdout_bytes = try multi_reader.toOwnedSlice(0); - stderr_bytes = try multi_reader.toOwnedSlice(1); + stdout_bytes = multi_reader.reader(0).buffered(); + stderr_bytes = multi_reader.reader(1).buffered(); } else { var stdout_reader = stdout.readerStreaming(io, &.{}); const stdio_limit: Io.Limit = if (conf_run.stdio_limit.value) |x| .limited64(x) else .unlimited; @@ -1484,7 +1492,7 @@ fn evalGeneric( else => true, }; if (stderr_is_diagnostic) { - step.result_stderr = bytes; + try step.setResultStderr(maker.gpa, bytes); } }; @@ -2084,16 +2092,11 @@ fn runCommand( }, else => { // On failure, report captured stderr like normal standard error output. - const bad_exit = switch (generic_result.term) { - .exited => |code| code != 0, - .signal, .stopped, .unknown => true, - }; - if (bad_exit) { + if (!generic_result.term.success()) { if (generic_result.stderr) |bytes| { - step.result_stderr = bytes; + try step.setResultStderr(gpa, bytes); } } - try step.handleChildProcessTerm(maker, generic_result.term); }, } @@ -2135,13 +2138,13 @@ fn spawnChildAndCollect( .inherit; // If an error occurs, it's caused by this command: - step.clearFailedCommand(gpa); - step.result_failed_command = try std.zig.allocPrintCmd(gpa, argv, .{ - .cwd = switch (child_cwd) { - .path => |p| p, - .dir => unreachable, - .inherit => null, - }, + const cwd_string = switch (child_cwd) { + .path => |p| p, + .dir => unreachable, + .inherit => null, + }; + errdefer step.setFailedCommand(gpa, argv, .{ + .cwd = cwd_string, .child_env = environ_map, .parent_env = &graph.environ_map, }); @@ -2178,7 +2181,7 @@ fn spawnChildAndCollect( if (conf_run.flags.stdio == .zig_test) { const started: Io.Clock.Timestamp = .now(io, .awake); - const result = evalZigTest(graph.arena, run, run_index, maker, progress_node, spawn_options, fuzz_context) catch |err| switch (err) { + 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, }; @@ -2198,7 +2201,7 @@ fn spawnChildAndCollect( try setColorEnvironmentVariables(&conf_run, environ_map, terminal_mode); const started: Io.Clock.Timestamp = .now(io, .awake); - const result = evalGeneric(graph.arena, run_index, maker, spawn_options) catch |err| switch (err) { + const result = evalGeneric(arena, run_index, maker, spawn_options) catch |err| switch (err) { error.Canceled => |e| return e, else => |e| e, }; diff --git a/lib/compiler/Maker/Step/TranslateC.zig b/lib/compiler/Maker/Step/TranslateC.zig index 84176dde10f0fde70a9175803c3a325888920d82..f0355d8bcc913c4694bc547fdef8bd2de46ceeb5 100644 --- a/lib/compiler/Maker/Step/TranslateC.zig +++ b/lib/compiler/Maker/Step/TranslateC.zig @@ -112,7 +112,7 @@ pub fn make( const pkg_conf_node = progress_node.start("pkg-config", 0); defer pkg_conf_node.end(); - if (PkgConfig.run(maker, step, pkg_conf_node, system_lib_name, force)) |result| { + if (PkgConfig.run(maker, step, arena, pkg_conf_node, system_lib_name, force)) |result| { try argv.appendSlice(arena, result.cflags); try argv.appendSlice(arena, result.libs); try seen_system_libs.put(arena, system_lib.name, result.cflags); diff --git a/src/main.zig b/src/main.zig index 80443b5709c9be7364e7f2439667711c4e4b3b30..d4a2b0d77c293bddcc1964e8bb5400acf060d376 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5810,7 +5810,7 @@ const MakeRunner = struct { }; fn compileMakeRunner(gpa: Allocator, arena: Allocator, io: Io, options: MakeRunner.Options) !MakeRunner { - const compile_prog_node = options.parent_prog_node.start("Compile Maker", 0); + const compile_prog_node = options.parent_prog_node.start("Compiling maker (first time setup)", 0); defer compile_prog_node.end(); const strip = options.optimize_mode != .Debug;