| author | |
| committer | |
| log | 4d56c6636251a90926467dfe65c99adf5ff7222a |
| tree | 5b5265368a236ab18def983268268f3792272d87 |
| parent | 7451f5d1174c1113da50c883c7b3f7e8415cea0a |
| parent | 33680ced58de7efb5bfe18fc95d2b67fc8496aed |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/3547110 files changed, 167 insertions(+), 116 deletions(-)
ci/x86_64-linux-debug-llvm.sh-1| ... | ... | @@ -49,7 +49,6 @@ stage3-debug/bin/zig build \ |
| 49 | 49 | -Dno-lib |
| 50 | 50 | |
| 51 | 51 | stage3-debug/bin/zig build test docs \ |
| 52 | --maker-opt=Debug \ | |
| 53 | 52 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 54 | 53 | -Dlldb=$HOME/deps/lldb-zig/Debug-33ec8d3c11/bin/lldb \ |
| 55 | 54 | -Dlibc-test-path=$HOME/deps/libc-test-f2bac77 \ |
ci/x86_64-linux-debug.sh+1| ... | ... | @@ -48,6 +48,7 @@ stage3-debug/bin/zig build \ |
| 48 | 48 | -Dno-lib |
| 49 | 49 | |
| 50 | 50 | stage3-debug/bin/zig build test docs \ |
| 51 | --maker-opt=Debug \ | |
| 51 | 52 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 52 | 53 | -Dlldb=$HOME/deps/lldb-zig/Debug-33ec8d3c11/bin/lldb \ |
| 53 | 54 | -fqemu \ |
lib/compiler/Maker.zig+54-44| ... | ... | @@ -16,6 +16,7 @@ const fmt = std.fmt; |
| 16 | 16 | const log = std.log; |
| 17 | 17 | const mem = std.mem; |
| 18 | 18 | const process = std.process; |
| 19 | const Color = std.zig.Color; | |
| 19 | 20 | |
| 20 | 21 | const Fuzz = @import("Maker/Fuzz.zig"); |
| 21 | 22 | const Graph = @import("Maker/Graph.zig"); |
| ... | ... | @@ -55,12 +56,59 @@ error_style: ErrorStyle, |
| 55 | 56 | multiline_errors: MultilineErrors, |
| 56 | 57 | summary: Summary, |
| 57 | 58 | |
| 59 | var safe_allocator_instance: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); | |
| 60 | var stdio_buffer_allocation: [256]u8 = undefined; | |
| 61 | var stdout_writer_allocation: Io.File.Writer = undefined; | |
| 62 | var debug_maker_leaks: bool = false; | |
| 63 | ||
| 64 | const is_debug_mode = builtin.mode == .Debug; | |
| 65 | const use_safe_allocator = switch (builtin.mode) { | |
| 66 | .Debug, .ReleaseSafe => true, | |
| 67 | .ReleaseFast, .ReleaseSmall => false, | |
| 68 | }; | |
| 69 | ||
| 70 | const InstallPaths = struct { | |
| 71 | prefix: Path, | |
| 72 | lib: Path, | |
| 73 | bin: Path, | |
| 74 | include: Path, | |
| 75 | }; | |
| 76 | ||
| 77 | const PrintNode = struct { | |
| 78 | parent: ?*PrintNode, | |
| 79 | last: bool = false, | |
| 80 | }; | |
| 81 | ||
| 82 | const ErrorStyle = enum { | |
| 83 | verbose, | |
| 84 | minimal, | |
| 85 | verbose_clear, | |
| 86 | minimal_clear, | |
| 87 | fn verboseContext(s: ErrorStyle) bool { | |
| 88 | return switch (s) { | |
| 89 | .verbose, .verbose_clear => true, | |
| 90 | .minimal, .minimal_clear => false, | |
| 91 | }; | |
| 92 | } | |
| 93 | fn clearOnUpdate(s: ErrorStyle) bool { | |
| 94 | return switch (s) { | |
| 95 | .verbose, .minimal => false, | |
| 96 | .verbose_clear, .minimal_clear => true, | |
| 97 | }; | |
| 98 | } | |
| 99 | }; | |
| 100 | const MultilineErrors = enum { indent, newline, none }; | |
| 101 | const Summary = enum { all, new, failures, line, none }; | |
| 102 | ||
| 58 | 103 | pub fn main(init: process.Init.Minimal) !void { |
| 59 | // The build runner is often short-lived, but thanks to `--watch` and `--webui`, that's not | |
| 60 | // always the case. So, we do need a true gpa for some things. | |
| 61 | var safe_gpa_state: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); | |
| 62 | defer _ = safe_gpa_state.deinit(); | |
| 63 | const gpa = safe_gpa_state.allocator(); | |
| 104 | // The build runner is long-lived in the following use cases: | |
| 105 | // * `--watch` mode | |
| 106 | // * `--webui` mode | |
| 107 | // * A project that has a large, complex build graph. | |
| 108 | const gpa = if (use_safe_allocator) safe_allocator_instance.allocator() else std.heap.smp_allocator; | |
| 109 | defer if (use_safe_allocator) { | |
| 110 | _ = safe_allocator_instance.deinit(); | |
| 111 | }; | |
| 64 | 112 | |
| 65 | 113 | var threaded: std.Io.Threaded = .init(gpa, .{ |
| 66 | 114 | .environ = init.environ, |
| ... | ... | @@ -689,13 +737,6 @@ fn countSubProcesses(maker: *Maker) usize { |
| 689 | 737 | return count; |
| 690 | 738 | } |
| 691 | 739 | |
| 692 | const InstallPaths = struct { | |
| 693 | prefix: Path, | |
| 694 | lib: Path, | |
| 695 | bin: Path, | |
| 696 | include: Path, | |
| 697 | }; | |
| 698 | ||
| 699 | 740 | pub fn stepByIndex(maker: *const Maker, i: Configuration.Step.Index) *Step { |
| 700 | 741 | return &maker.steps[@intFromEnum(i)]; |
| 701 | 742 | } |
| ... | ... | @@ -1018,6 +1059,7 @@ fn makeStepNames( |
| 1018 | 1059 | fn deinit(maker: *Maker) void { |
| 1019 | 1060 | const gpa = maker.gpa; |
| 1020 | 1061 | for (maker.steps) |*step| { |
| 1062 | step.clearResultStderr(gpa); | |
| 1021 | 1063 | step.clearFailedCommand(gpa); |
| 1022 | 1064 | step.clearErrorBundle(gpa); |
| 1023 | 1065 | step.inputs.deinit(gpa); |
| ... | ... | @@ -1424,11 +1466,6 @@ fn printStepFailure( |
| 1424 | 1466 | } |
| 1425 | 1467 | } |
| 1426 | 1468 | |
| 1427 | const PrintNode = struct { | |
| 1428 | parent: ?*PrintNode, | |
| 1429 | last: bool = false, | |
| 1430 | }; | |
| 1431 | ||
| 1432 | 1469 | fn printPrefix(node: *PrintNode, stderr: Io.Terminal) !void { |
| 1433 | 1470 | const parent = node.parent orelse return; |
| 1434 | 1471 | const writer = stderr.writer; |
| ... | ... | @@ -1657,28 +1694,6 @@ fn argsRest(args: []const [:0]const u8, idx: usize) ?[]const [:0]const u8 { |
| 1657 | 1694 | return args[idx..]; |
| 1658 | 1695 | } |
| 1659 | 1696 | |
| 1660 | const Color = std.zig.Color; | |
| 1661 | const ErrorStyle = enum { | |
| 1662 | verbose, | |
| 1663 | minimal, | |
| 1664 | verbose_clear, | |
| 1665 | minimal_clear, | |
| 1666 | fn verboseContext(s: ErrorStyle) bool { | |
| 1667 | return switch (s) { | |
| 1668 | .verbose, .verbose_clear => true, | |
| 1669 | .minimal, .minimal_clear => false, | |
| 1670 | }; | |
| 1671 | } | |
| 1672 | fn clearOnUpdate(s: ErrorStyle) bool { | |
| 1673 | return switch (s) { | |
| 1674 | .verbose, .minimal => false, | |
| 1675 | .verbose_clear, .minimal_clear => true, | |
| 1676 | }; | |
| 1677 | } | |
| 1678 | }; | |
| 1679 | const MultilineErrors = enum { indent, newline, none }; | |
| 1680 | const Summary = enum { all, new, failures, line, none }; | |
| 1681 | ||
| 1682 | 1697 | fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn { |
| 1683 | 1698 | log.info("to access the help menu: zig build -h", .{}); |
| 1684 | 1699 | fatal(f, args); |
| ... | ... | @@ -1701,9 +1716,6 @@ fn cleanTmpFiles(maker: *Maker, steps: []const Configuration.Step.Index) void { |
| 1701 | 1716 | } |
| 1702 | 1717 | } |
| 1703 | 1718 | |
| 1704 | var stdio_buffer_allocation: [256]u8 = undefined; | |
| 1705 | var stdout_writer_allocation: Io.File.Writer = undefined; | |
| 1706 | ||
| 1707 | 1719 | fn initStdoutWriter(io: Io) *Writer { |
| 1708 | 1720 | stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation); |
| 1709 | 1721 | return &stdout_writer_allocation.interface; |
| ... | ... | @@ -2043,8 +2055,6 @@ fn removePoisonedConfiguration(io: Io, scanned_config: *const ScannedConfig) voi |
| 2043 | 2055 | } |
| 2044 | 2056 | } |
| 2045 | 2057 | |
| 2046 | const is_debug_mode = builtin.mode == .Debug; | |
| 2047 | var debug_maker_leaks: bool = false; | |
| 2048 | 2058 | inline fn debugMakerLeaks() bool { |
| 2049 | 2059 | if (!is_debug_mode) return false; |
| 2050 | 2060 | return debug_maker_leaks; |
lib/compiler/Maker/PkgConfig.zig+14-7| ... | ... | @@ -2,6 +2,7 @@ const std = @import("std"); |
| 2 | 2 | const Io = std.Io; |
| 3 | 3 | const mem = std.mem; |
| 4 | 4 | const assert = std.debug.assert; |
| 5 | const Allocator = std.mem.Allocator; | |
| 5 | 6 | |
| 6 | 7 | const Maker = @import("../Maker.zig"); |
| 7 | 8 | const Step = @import("Step.zig"); |
| ... | ... | @@ -23,6 +24,7 @@ pub const Result = std.zig.PkgConfig.Parsed; |
| 23 | 24 | pub fn run( |
| 24 | 25 | maker: *Maker, |
| 25 | 26 | step: *Step, |
| 27 | arena: Allocator, | |
| 26 | 28 | progress_node: std.Progress.Node, |
| 27 | 29 | lib_name: []const u8, |
| 28 | 30 | /// If true, reports failure error messages on step rather than returning |
| ... | ... | @@ -31,7 +33,6 @@ pub fn run( |
| 31 | 33 | ) RunError!Result { |
| 32 | 34 | const pc = &maker.pkg_config; |
| 33 | 35 | const graph = maker.graph; |
| 34 | const arena = graph.arena; // TODO don't leak into process arena | |
| 35 | 36 | |
| 36 | 37 | const pkg_config_exe = getExe(graph); |
| 37 | 38 | const pkgs = try getPkgs(maker, step, progress_node, force); |
| ... | ... | @@ -41,7 +42,7 @@ pub fn run( |
| 41 | 42 | }; |
| 42 | 43 | const pkg = pkgs.all[found_index]; |
| 43 | 44 | |
| 44 | const stdout = try captureChildProcess(maker, step, .{ | |
| 45 | const stdout = try captureChildProcess(maker, step, arena, .{ | |
| 45 | 46 | .argv = &.{ pkg_config_exe, pkg.name, "--cflags", "--libs" }, |
| 46 | 47 | .progress_node = progress_node, |
| 47 | 48 | .allow_failure = !force, |
| ... | ... | @@ -69,11 +70,16 @@ fn getExe(graph: *const Graph) []const u8 { |
| 69 | 70 | return std.zig.PkgConfig.exe(&graph.environ_map); |
| 70 | 71 | } |
| 71 | 72 | |
| 72 | fn getPkgs(maker: *Maker, step: *Step, progress_node: std.Progress.Node, force: bool) RunError!std.zig.PkgConfig { | |
| 73 | fn getPkgs( | |
| 74 | maker: *Maker, | |
| 75 | step: *Step, | |
| 76 | progress_node: std.Progress.Node, | |
| 77 | force: bool, | |
| 78 | ) RunError!std.zig.PkgConfig { | |
| 73 | 79 | const graph = maker.graph; |
| 74 | const arena = graph.arena; // TODO don't leak into process arena | |
| 75 | 80 | const io = graph.io; |
| 76 | 81 | const pc = &maker.pkg_config; |
| 82 | const arena = graph.arena; | |
| 77 | 83 | |
| 78 | 84 | try pc.mutex.lock(io); |
| 79 | 85 | defer pc.mutex.unlock(io); |
| ... | ... | @@ -81,7 +87,7 @@ fn getPkgs(maker: *Maker, step: *Step, progress_node: std.Progress.Node, force: |
| 81 | 87 | if (pc.pkgs) |pkgs| return pkgs; |
| 82 | 88 | |
| 83 | 89 | const pkg_config_exe = getExe(graph); |
| 84 | const stdout = try captureChildProcess(maker, step, .{ | |
| 90 | const stdout = try captureChildProcess(maker, step, arena, .{ | |
| 85 | 91 | .argv = &.{ pkg_config_exe, "--list-all" }, |
| 86 | 92 | .progress_node = progress_node, |
| 87 | 93 | .allow_failure = !force, |
| ... | ... | @@ -102,11 +108,12 @@ fn getPkgs(maker: *Maker, step: *Step, progress_node: std.Progress.Node, force: |
| 102 | 108 | return result; |
| 103 | 109 | } |
| 104 | 110 | |
| 105 | fn captureChildProcess(maker: *Maker, step: *Step, options: Step.CaptureChildProcessOptions) ![]const u8 { | |
| 106 | const captured = step.captureChildProcess(maker, options) catch |err| switch (err) { | |
| 111 | fn captureChildProcess(maker: *Maker, step: *Step, arena: Allocator, options: Step.CaptureChildProcessOptions) ![]const u8 { | |
| 112 | const captured = step.captureChildProcess(maker, arena, options) catch |err| switch (err) { | |
| 107 | 113 | error.FileNotFound => return error.PkgConfigUnavailable, |
| 108 | 114 | else => |e| return e, |
| 109 | 115 | }; |
| 116 | if (captured.stderr.len != 0) try step.setResultStderr(maker.gpa, captured.stderr); | |
| 110 | 117 | assert(step.result_failed_command != null); |
| 111 | 118 | if (captured.term.success()) return captured.stdout; |
| 112 | 119 | if (!options.allow_failure) return step.fail(maker, "{s} {f}", .{ options.argv[0], captured.term }); |
lib/compiler/Maker/Step.zig+47-16| ... | ... | @@ -54,8 +54,10 @@ dependants: std.ArrayList(Configuration.Step.Index) = .empty, |
| 54 | 54 | inputs: Inputs = .init, |
| 55 | 55 | pending_deps: u32 = undefined, |
| 56 | 56 | |
| 57 | /// Array list and internal memory owned by process arena. | |
| 57 | 58 | result_error_msgs: std.ArrayList([]const u8) = .empty, |
| 58 | 59 | result_error_bundle: std.zig.ErrorBundle = .empty, |
| 60 | /// Owned by `Maker.gpa`. | |
| 59 | 61 | result_stderr: []const u8 = "", |
| 60 | 62 | result_cached: bool = false, |
| 61 | 63 | /// Indicates error information is missing due to allocation failure. |
| ... | ... | @@ -310,9 +312,8 @@ pub fn reset(step: *Step, maker: *Maker) void { |
| 310 | 312 | const gpa = maker.gpa; |
| 311 | 313 | |
| 312 | 314 | clearFailedCommand(step, gpa); |
| 313 | ||
| 315 | clearResultStderr(step, gpa); | |
| 314 | 316 | step.result_error_msgs.clearRetainingCapacity(); |
| 315 | step.result_stderr = ""; | |
| 316 | 317 | step.result_cached = false; |
| 317 | 318 | step.result_duration_ns = null; |
| 318 | 319 | step.result_peak_rss = 0; |
| ... | ... | @@ -332,20 +333,23 @@ pub const CaptureChildProcessOptions = struct { |
| 332 | 333 | allow_failure: bool = false, |
| 333 | 334 | }; |
| 334 | 335 | |
| 335 | /// Populates `s.result_failed_command`. | |
| 336 | pub fn captureChildProcess(s: *Step, maker: *Maker, options: CaptureChildProcessOptions) !std.process.RunResult { | |
| 336 | /// Populates `s.result_failed_command` unconditionally. | |
| 337 | pub fn captureChildProcess( | |
| 338 | s: *Step, | |
| 339 | maker: *Maker, | |
| 340 | allocator: Allocator, | |
| 341 | options: CaptureChildProcessOptions, | |
| 342 | ) !std.process.RunResult { | |
| 337 | 343 | const gpa = maker.gpa; |
| 338 | 344 | const graph = maker.graph; |
| 339 | const arena = graph.arena; // TODO stop leaking into process arena | |
| 340 | 345 | const io = graph.io; |
| 341 | 346 | |
| 342 | clearFailedCommand(s, gpa); | |
| 343 | s.result_failed_command = try std.zig.allocPrintCmd(gpa, options.argv, .{}); | |
| 347 | s.setFailedCommand(gpa, options.argv, .{}); | |
| 344 | 348 | |
| 345 | 349 | try handleChildProcUnsupported(s, maker); |
| 346 | 350 | try graph.handleVerbose(null, null, options.argv); |
| 347 | 351 | |
| 348 | const result = std.process.run(arena, io, .{ | |
| 352 | const result = std.process.run(allocator, io, .{ | |
| 349 | 353 | .argv = options.argv, |
| 350 | 354 | .environ_map = options.environ_map orelse &graph.environ_map, |
| 351 | 355 | .progress_node = options.progress_node, |
| ... | ... | @@ -358,7 +362,7 @@ pub fn captureChildProcess(s: *Step, maker: *Maker, options: CaptureChildProcess |
| 358 | 362 | return s.fail(maker, "failed to run {s}: {t}", .{ options.argv[0], err }); |
| 359 | 363 | }; |
| 360 | 364 | |
| 361 | if (result.stderr.len > 0) try s.result_error_msgs.append(arena, result.stderr); | |
| 365 | if (result.stderr.len > 0) try s.result_error_msgs.append(graph.arena, result.stderr); | |
| 362 | 366 | |
| 363 | 367 | return result; |
| 364 | 368 | } |
| ... | ... | @@ -375,6 +379,21 @@ pub fn clearFailedCommand(s: *Step, gpa: Allocator) void { |
| 375 | 379 | } |
| 376 | 380 | } |
| 377 | 381 | |
| 382 | pub fn setFailedCommand( | |
| 383 | s: *Step, | |
| 384 | gpa: Allocator, | |
| 385 | argv: []const []const u8, | |
| 386 | options: std.zig.AllocPrintCmdOptions, | |
| 387 | ) void { | |
| 388 | s.clearFailedCommand(gpa); | |
| 389 | s.result_failed_command = std.zig.allocPrintCmd(gpa, argv, options) catch |err| switch (err) { | |
| 390 | error.OutOfMemory => { | |
| 391 | s.result_oom = true; | |
| 392 | return; | |
| 393 | }, | |
| 394 | }; | |
| 395 | } | |
| 396 | ||
| 378 | 397 | pub const FailError = error{ OutOfMemory, MakeFailed }; |
| 379 | 398 | |
| 380 | 399 | pub fn fail(step: *Step, maker: *const Maker, comptime fmt: []const u8, args: anytype) FailError { |
| ... | ... | @@ -410,7 +429,8 @@ pub const ZigProcess = struct { |
| 410 | 429 | |
| 411 | 430 | /// Assumes that argv contains `--listen=-` and that the process being spawned |
| 412 | 431 | /// is the zig compiler - the same version that compiled the build runner. |
| 413 | /// Populates `s.result_failed_command`. | |
| 432 | /// | |
| 433 | /// Populates `s.result_failed_command` on failure. | |
| 414 | 434 | pub fn evalZigProcess( |
| 415 | 435 | step_index: Configuration.Step.Index, |
| 416 | 436 | maker: *Maker, |
| ... | ... | @@ -424,8 +444,7 @@ pub fn evalZigProcess( |
| 424 | 444 | const io = graph.io; |
| 425 | 445 | |
| 426 | 446 | // If an error occurs, it's happened in this command: |
| 427 | clearFailedCommand(s, gpa); | |
| 428 | s.result_failed_command = try std.zig.allocPrintCmd(gpa, argv, .{}); | |
| 447 | errdefer s.setFailedCommand(gpa, argv, .{}); | |
| 429 | 448 | |
| 430 | 449 | if (s.getZigProcess()) |zp| update: { |
| 431 | 450 | assert(watch); |
| ... | ... | @@ -683,16 +702,12 @@ fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void { |
| 683 | 702 | }; |
| 684 | 703 | } |
| 685 | 704 | |
| 686 | /// Asserts that the caller has already populated `s.result_failed_command`. | |
| 687 | 705 | pub inline fn handleChildProcUnsupported(s: *Step, maker: *Maker) FailError!void { |
| 688 | assert(s.result_failed_command != null); | |
| 689 | 706 | if (!std.process.can_spawn) |
| 690 | 707 | return s.fail(maker, "unable to spawn process: host cannot spawn child processes", .{}); |
| 691 | 708 | } |
| 692 | 709 | |
| 693 | /// Asserts that the caller has already populated `s.result_failed_command`. | |
| 694 | 710 | pub fn handleChildProcessTerm(s: *Step, maker: *Maker, term: std.process.Child.Term) FailError!void { |
| 695 | assert(s.result_failed_command != null); | |
| 696 | 711 | if (!term.success()) return s.fail(maker, "process {f}", .{term}); |
| 697 | 712 | } |
| 698 | 713 | |
| ... | ... | @@ -861,3 +876,19 @@ fn oomWrap(s: *Step, result: error{OutOfMemory}!void) void { |
| 861 | 876 | s.result_oom = true; |
| 862 | 877 | }; |
| 863 | 878 | } |
| 879 | ||
| 880 | pub fn clearResultStderr(step: *Step, gpa: Allocator) void { | |
| 881 | if (step.result_stderr.len != 0) { | |
| 882 | gpa.free(step.result_stderr); | |
| 883 | step.result_stderr = ""; | |
| 884 | } | |
| 885 | } | |
| 886 | ||
| 887 | pub fn setResultStderr(step: *Step, gpa: Allocator, bytes: []const u8) Allocator.Error!void { | |
| 888 | takeResultStderr(step, gpa, try gpa.dupe(u8, bytes)); | |
| 889 | } | |
| 890 | ||
| 891 | pub fn takeResultStderr(step: *Step, gpa: Allocator, owned: []const u8) void { | |
| 892 | clearResultStderr(step, gpa); | |
| 893 | step.result_stderr = owned; | |
| 894 | } |
lib/compiler/Maker/Step/Compile.zig+6-6| ... | ... | @@ -328,10 +328,10 @@ fn lowerZigArgs( |
| 328 | 328 | const pkg_conf_node = progress_node.start("pkg-config", 0); |
| 329 | 329 | defer pkg_conf_node.end(); |
| 330 | 330 | |
| 331 | if (PkgConfig.run(maker, step, pkg_conf_node, system_lib_name, force)) |result| { | |
| 332 | try zig_args.appendSlice(gpa, result.cflags); | |
| 333 | try zig_args.appendSlice(gpa, result.libs); | |
| 334 | try seen_system_libs.put(arena, system_lib.name, result.cflags); | |
| 331 | if (PkgConfig.run(maker, step, arena, pkg_conf_node, system_lib_name, force)) |pc| { | |
| 332 | try zig_args.appendSlice(gpa, pc.cflags); | |
| 333 | try zig_args.appendSlice(gpa, pc.libs); | |
| 334 | try seen_system_libs.put(arena, system_lib.name, pc.cflags); | |
| 335 | 335 | break :l; |
| 336 | 336 | } else |err| switch (err) { |
| 337 | 337 | error.PkgConfigUnavailable, |
| ... | ... | @@ -960,8 +960,8 @@ pub fn rebuildInFuzzMode( |
| 960 | 960 | const arena = arena_allocator.allocator(); |
| 961 | 961 | |
| 962 | 962 | step.result_error_msgs.clearRetainingCapacity(); |
| 963 | step.result_stderr = ""; | |
| 964 | ||
| 963 | step.clearResultStderr(gpa); | |
| 964 | step.clearErrorBundle(gpa); | |
| 965 | 965 | step.result_error_bundle.deinit(gpa); |
| 966 | 966 | step.result_error_bundle = std.zig.ErrorBundle.empty; |
| 967 | 967 |
lib/compiler/Maker/Step/Fmt.zig+1-1| ... | ... | @@ -43,7 +43,7 @@ pub fn make( |
| 43 | 43 | argv.appendAssumeCapacity(try maker.resolveLazyPathIndexAbs(arena, lp, step_index)); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | const run_result = step.captureChildProcess(maker, .{ | |
| 46 | const run_result = step.captureChildProcess(maker, arena, .{ | |
| 47 | 47 | .progress_node = progress_node, |
| 48 | 48 | .argv = argv.items, |
| 49 | 49 | .allow_failure = false, |
lib/compiler/Maker/Step/Run.zig+42-39| ... | ... | @@ -713,7 +713,7 @@ const FuzzTestRunner = struct { |
| 713 | 713 | } |
| 714 | 714 | } |
| 715 | 715 | |
| 716 | fn listen(f: *FuzzTestRunner, arena: Allocator) !void { | |
| 716 | fn listen(f: *FuzzTestRunner) !void { | |
| 717 | 717 | const maker = f.ctx.fuzz.maker; |
| 718 | 718 | const graph = maker.graph; |
| 719 | 719 | const io = graph.io; |
| ... | ... | @@ -737,7 +737,7 @@ const FuzzTestRunner = struct { |
| 737 | 737 | else => |read_e| return read_e, |
| 738 | 738 | }), |
| 739 | 739 | 2 => try f.completeStderrRead(id, result.file_read_streaming catch |e| switch (e) { |
| 740 | error.EndOfStream => return f.instanceEos(arena, id), | |
| 740 | error.EndOfStream => return f.instanceEos(id), | |
| 741 | 741 | else => |read_e| return read_e, |
| 742 | 742 | }), |
| 743 | 743 | else => unreachable, |
| ... | ... | @@ -899,8 +899,9 @@ const FuzzTestRunner = struct { |
| 899 | 899 | } }); |
| 900 | 900 | } |
| 901 | 901 | |
| 902 | fn instanceEos(f: *FuzzTestRunner, arena: Allocator, id: u32) !void { | |
| 902 | fn instanceEos(f: *FuzzTestRunner, id: u32) !void { | |
| 903 | 903 | const maker = f.ctx.fuzz.maker; |
| 904 | const gpa = maker.gpa; | |
| 904 | 905 | const instance = &f.instances[id]; |
| 905 | 906 | const run_index = f.run_index; |
| 906 | 907 | |
| ... | ... | @@ -912,7 +913,7 @@ const FuzzTestRunner = struct { |
| 912 | 913 | instance.child.stdin = null; |
| 913 | 914 | const term = try instance.child.wait(io); |
| 914 | 915 | if (!termMatches(.{ .exited = 0 }, term)) { |
| 915 | step.result_stderr = try f.mergedStderr(arena); | |
| 916 | step.takeResultStderr(gpa, try f.mergedStderr(gpa)); | |
| 916 | 917 | try f.saveCrash(id, term); |
| 917 | 918 | return step.fail(maker, "test process unexpectedly {f}", .{fmtTerm(term)}); |
| 918 | 919 | } |
| ... | ... | @@ -1055,7 +1056,7 @@ const FuzzTestRunner = struct { |
| 1055 | 1056 | } |
| 1056 | 1057 | } |
| 1057 | 1058 | |
| 1058 | fn mergedStderr(f: *FuzzTestRunner, arena: Allocator) Allocator.Error![]const u8 { | |
| 1059 | fn mergedStderr(f: *FuzzTestRunner, gpa: Allocator) Allocator.Error![]const u8 { | |
| 1059 | 1060 | // Collect any available stderr |
| 1060 | 1061 | while (f.batch.next()) |completion| { |
| 1061 | 1062 | if (completion.index % 3 != 2) continue; |
| ... | ... | @@ -1065,7 +1066,7 @@ const FuzzTestRunner = struct { |
| 1065 | 1066 | |
| 1066 | 1067 | var stderr_len: usize = 0; |
| 1067 | 1068 | for (f.instances) |*instance| stderr_len += instance.stderr.items.len; |
| 1068 | const stderr = try arena.alloc(u8, stderr_len); | |
| 1069 | const stderr = try gpa.alloc(u8, stderr_len); | |
| 1069 | 1070 | |
| 1070 | 1071 | stderr_len = 0; |
| 1071 | 1072 | for (f.instances) |*instance| { |
| ... | ... | @@ -1086,13 +1087,12 @@ fn evalFuzzTest( |
| 1086 | 1087 | var f: FuzzTestRunner = try .init(run, run_index, fuzz_context, progress_node, spawn_options); |
| 1087 | 1088 | defer f.deinit(); |
| 1088 | 1089 | try f.startInstances(); |
| 1089 | try f.listen(fuzz_context.fuzz.maker.graph.arena); | |
| 1090 | try f.listen(); | |
| 1090 | 1091 | } |
| 1091 | 1092 | |
| 1092 | 1093 | const StdioPollEnum = enum { stdout, stderr }; |
| 1093 | 1094 | |
| 1094 | 1095 | fn evalZigTest( |
| 1095 | arena: Allocator, | |
| 1096 | 1096 | run: *Run, |
| 1097 | 1097 | run_index: Configuration.Step.Index, |
| 1098 | 1098 | maker: *Maker, |
| ... | ... | @@ -1140,7 +1140,7 @@ fn evalZigTest( |
| 1140 | 1140 | }; |
| 1141 | 1141 | |
| 1142 | 1142 | switch (try waitZigTest( |
| 1143 | arena, | |
| 1143 | graph.arena, | |
| 1144 | 1144 | run, |
| 1145 | 1145 | run_index, |
| 1146 | 1146 | maker, |
| ... | ... | @@ -1158,7 +1158,7 @@ fn evalZigTest( |
| 1158 | 1158 | error.ReadFailed => return stderr_fr.err.?, |
| 1159 | 1159 | error.EndOfStream => {}, |
| 1160 | 1160 | } |
| 1161 | step.result_stderr = try arena.dupe(u8, stderr_fr.interface.buffered()); | |
| 1161 | step.takeResultStderr(gpa, try multi_reader.toOwnedSlice(1)); | |
| 1162 | 1162 | |
| 1163 | 1163 | // Clean up everything and wait for the child to exit. |
| 1164 | 1164 | child.stdin.?.close(io); |
| ... | ... | @@ -1180,8 +1180,9 @@ fn evalZigTest( |
| 1180 | 1180 | .no_poll => |no_poll| { |
| 1181 | 1181 | // This might be a success (we requested exit and the child dutifully closed stdout) or |
| 1182 | 1182 | // a crash of some kind. Either way, the child will terminate by itself -- wait for it. |
| 1183 | const stderr_reader = multi_reader.reader(1); | |
| 1184 | const stderr_owned = try arena.dupe(u8, stderr_reader.buffered()); | |
| 1183 | const stderr_owned = try multi_reader.toOwnedSlice(1); | |
| 1184 | var keep_stderr_owned = false; | |
| 1185 | defer if (!keep_stderr_owned) gpa.free(stderr_owned); | |
| 1185 | 1186 | |
| 1186 | 1187 | // Clean up everything and wait for the child to exit. |
| 1187 | 1188 | child.stdin.?.close(io); |
| ... | ... | @@ -1209,7 +1210,9 @@ fn evalZigTest( |
| 1209 | 1210 | } |
| 1210 | 1211 | |
| 1211 | 1212 | // Report an error if the child terminated uncleanly or if we were still trying to run more tests. |
| 1212 | step.result_stderr = stderr_owned; | |
| 1213 | step.takeResultStderr(gpa, stderr_owned); | |
| 1214 | keep_stderr_owned = true; | |
| 1215 | ||
| 1213 | 1216 | const tests_done = test_metadata != null and test_metadata.?.next_index == std.math.maxInt(u32); |
| 1214 | 1217 | if (!tests_done or !termMatches(.{ .exited = 0 }, term)) { |
| 1215 | 1218 | // The individual unit test results are irrelevant: the test runner itself broke! |
| ... | ... | @@ -1234,9 +1237,10 @@ fn evalZigTest( |
| 1234 | 1237 | return; |
| 1235 | 1238 | }, |
| 1236 | 1239 | .timeout => |timeout| { |
| 1237 | const stderr_reader = multi_reader.reader(1); | |
| 1238 | const stderr = stderr_reader.buffered(); | |
| 1239 | stderr_reader.tossBuffered(); | |
| 1240 | const stderr_owned = try multi_reader.toOwnedSlice(1); | |
| 1241 | var keep_stderr_owned = false; | |
| 1242 | defer if (!keep_stderr_owned) gpa.free(stderr_owned); | |
| 1243 | ||
| 1240 | 1244 | if (timeout.active_test_index) |test_index| { |
| 1241 | 1245 | // A test was running. Report the timeout against that test, and continue on to |
| 1242 | 1246 | // the next test. |
| ... | ... | @@ -1245,16 +1249,20 @@ fn evalZigTest( |
| 1245 | 1249 | try step.addError(maker, "'{s}' timed out after {f}{s}{s}", .{ |
| 1246 | 1250 | test_metadata.?.testName(test_index), |
| 1247 | 1251 | Io.Duration{ .nanoseconds = timeout.ns_elapsed }, |
| 1248 | if (stderr.len != 0) " with stderr:\n" else "", | |
| 1249 | std.mem.trim(u8, stderr, "\n"), | |
| 1252 | if (stderr_owned.len != 0) " with stderr:\n" else "", | |
| 1253 | std.mem.trim(u8, stderr_owned, "\n"), | |
| 1250 | 1254 | }); |
| 1251 | 1255 | continue; |
| 1252 | 1256 | } |
| 1253 | 1257 | // Just log an error and let the child be killed. |
| 1254 | step.result_stderr = try arena.dupe(u8, stderr); | |
| 1258 | step.takeResultStderr(gpa, stderr_owned); | |
| 1259 | keep_stderr_owned = true; | |
| 1260 | ||
| 1255 | 1261 | // The individual unit test results in `results` are irrelevant: the test runner |
| 1256 | 1262 | // is broken! Fail immediately without populating `s.test_results`. |
| 1257 | return step.fail(maker, "test runner failed to respond for {f}", .{Io.Duration{ .nanoseconds = timeout.ns_elapsed }}); | |
| 1263 | return step.fail(maker, "test runner failed to respond for {f}", .{ | |
| 1264 | Io.Duration{ .nanoseconds = timeout.ns_elapsed }, | |
| 1265 | }); | |
| 1258 | 1266 | }, |
| 1259 | 1267 | } |
| 1260 | 1268 | comptime unreachable; |
| ... | ... | @@ -1456,8 +1464,8 @@ fn evalGeneric( |
| 1456 | 1464 | |
| 1457 | 1465 | try multi_reader.checkAnyError(); |
| 1458 | 1466 | |
| 1459 | stdout_bytes = try multi_reader.toOwnedSlice(0); | |
| 1460 | stderr_bytes = try multi_reader.toOwnedSlice(1); | |
| 1467 | stdout_bytes = multi_reader.reader(0).buffered(); | |
| 1468 | stderr_bytes = multi_reader.reader(1).buffered(); | |
| 1461 | 1469 | } else { |
| 1462 | 1470 | var stdout_reader = stdout.readerStreaming(io, &.{}); |
| 1463 | 1471 | const stdio_limit: Io.Limit = if (conf_run.stdio_limit.value) |x| .limited64(x) else .unlimited; |
| ... | ... | @@ -1484,7 +1492,7 @@ fn evalGeneric( |
| 1484 | 1492 | else => true, |
| 1485 | 1493 | }; |
| 1486 | 1494 | if (stderr_is_diagnostic) { |
| 1487 | step.result_stderr = bytes; | |
| 1495 | try step.setResultStderr(maker.gpa, bytes); | |
| 1488 | 1496 | } |
| 1489 | 1497 | }; |
| 1490 | 1498 | |
| ... | ... | @@ -2084,16 +2092,11 @@ fn runCommand( |
| 2084 | 2092 | }, |
| 2085 | 2093 | else => { |
| 2086 | 2094 | // On failure, report captured stderr like normal standard error output. |
| 2087 | const bad_exit = switch (generic_result.term) { | |
| 2088 | .exited => |code| code != 0, | |
| 2089 | .signal, .stopped, .unknown => true, | |
| 2090 | }; | |
| 2091 | if (bad_exit) { | |
| 2095 | if (!generic_result.term.success()) { | |
| 2092 | 2096 | if (generic_result.stderr) |bytes| { |
| 2093 | step.result_stderr = bytes; | |
| 2097 | try step.setResultStderr(gpa, bytes); | |
| 2094 | 2098 | } |
| 2095 | 2099 | } |
| 2096 | ||
| 2097 | 2100 | try step.handleChildProcessTerm(maker, generic_result.term); |
| 2098 | 2101 | }, |
| 2099 | 2102 | } |
| ... | ... | @@ -2135,13 +2138,13 @@ fn spawnChildAndCollect( |
| 2135 | 2138 | .inherit; |
| 2136 | 2139 | |
| 2137 | 2140 | // If an error occurs, it's caused by this command: |
| 2138 | step.clearFailedCommand(gpa); | |
| 2139 | step.result_failed_command = try std.zig.allocPrintCmd(gpa, argv, .{ | |
| 2140 | .cwd = switch (child_cwd) { | |
| 2141 | .path => |p| p, | |
| 2142 | .dir => unreachable, | |
| 2143 | .inherit => null, | |
| 2144 | }, | |
| 2141 | const cwd_string = switch (child_cwd) { | |
| 2142 | .path => |p| p, | |
| 2143 | .dir => unreachable, | |
| 2144 | .inherit => null, | |
| 2145 | }; | |
| 2146 | errdefer step.setFailedCommand(gpa, argv, .{ | |
| 2147 | .cwd = cwd_string, | |
| 2145 | 2148 | .child_env = environ_map, |
| 2146 | 2149 | .parent_env = &graph.environ_map, |
| 2147 | 2150 | }); |
| ... | ... | @@ -2178,7 +2181,7 @@ fn spawnChildAndCollect( |
| 2178 | 2181 | |
| 2179 | 2182 | if (conf_run.flags.stdio == .zig_test) { |
| 2180 | 2183 | const started: Io.Clock.Timestamp = .now(io, .awake); |
| 2181 | const result = evalZigTest(graph.arena, run, run_index, maker, progress_node, spawn_options, fuzz_context) catch |err| switch (err) { | |
| 2184 | const result = evalZigTest(run, run_index, maker, progress_node, spawn_options, fuzz_context) catch |err| switch (err) { | |
| 2182 | 2185 | error.Canceled => |e| return e, |
| 2183 | 2186 | else => |e| e, |
| 2184 | 2187 | }; |
| ... | ... | @@ -2198,7 +2201,7 @@ fn spawnChildAndCollect( |
| 2198 | 2201 | try setColorEnvironmentVariables(&conf_run, environ_map, terminal_mode); |
| 2199 | 2202 | |
| 2200 | 2203 | const started: Io.Clock.Timestamp = .now(io, .awake); |
| 2201 | const result = evalGeneric(graph.arena, run_index, maker, spawn_options) catch |err| switch (err) { | |
| 2204 | const result = evalGeneric(arena, run_index, maker, spawn_options) catch |err| switch (err) { | |
| 2202 | 2205 | error.Canceled => |e| return e, |
| 2203 | 2206 | else => |e| e, |
| 2204 | 2207 | }; |
lib/compiler/Maker/Step/TranslateC.zig+1-1| ... | ... | @@ -112,7 +112,7 @@ pub fn make( |
| 112 | 112 | const pkg_conf_node = progress_node.start("pkg-config", 0); |
| 113 | 113 | defer pkg_conf_node.end(); |
| 114 | 114 | |
| 115 | if (PkgConfig.run(maker, step, pkg_conf_node, system_lib_name, force)) |result| { | |
| 115 | if (PkgConfig.run(maker, step, arena, pkg_conf_node, system_lib_name, force)) |result| { | |
| 116 | 116 | try argv.appendSlice(arena, result.cflags); |
| 117 | 117 | try argv.appendSlice(arena, result.libs); |
| 118 | 118 | try seen_system_libs.put(arena, system_lib.name, result.cflags); |
src/main.zig+1-1| ... | ... | @@ -5810,7 +5810,7 @@ const MakeRunner = struct { |
| 5810 | 5810 | }; |
| 5811 | 5811 | |
| 5812 | 5812 | fn compileMakeRunner(gpa: Allocator, arena: Allocator, io: Io, options: MakeRunner.Options) !MakeRunner { |
| 5813 | const compile_prog_node = options.parent_prog_node.start("Compile Maker", 0); | |
| 5813 | const compile_prog_node = options.parent_prog_node.start("Compiling maker (first time setup)", 0); | |
| 5814 | 5814 | defer compile_prog_node.end(); |
| 5815 | 5815 | |
| 5816 | 5816 | const strip = options.optimize_mode != .Debug; |