| author | |
| committer | |
| log | a388a8e5a7193831a349f6d00e04bd15211a931f |
| tree | 0c8a7e5df6bc3e4c88a2fcbb9e8bb77eba6d2ca3 |
| parent | e4456d03f3642c4d0e19176aa09dbc12099e7a4c |
| signature |
Recording the command in a separate field will give the build runner
more freedom to choose how and when the command should be printed.5 files changed, 71 insertions(+), 99 deletions(-)
lib/compiler/build_runner.zig+8| ... | ... | @@ -1443,6 +1443,14 @@ pub fn printErrorMessages( |
| 1443 | 1443 | } |
| 1444 | 1444 | try stderr.writeAll("\n"); |
| 1445 | 1445 | } |
| 1446 | ||
| 1447 | if (failing_step.result_failed_command) |cmd_str| { | |
| 1448 | try ttyconf.setColor(stderr, .red); | |
| 1449 | try stderr.writeAll("failed command: "); | |
| 1450 | try ttyconf.setColor(stderr, .reset); | |
| 1451 | try stderr.writeAll(cmd_str); | |
| 1452 | try stderr.writeByte('\n'); | |
| 1453 | } | |
| 1446 | 1454 | } |
| 1447 | 1455 | |
| 1448 | 1456 | fn printSteps(builder: *std.Build, w: *Writer) !void { |
lib/std/Build.zig+2-16| ... | ... | @@ -1594,20 +1594,6 @@ pub fn validateUserInputDidItFail(b: *Build) bool { |
| 1594 | 1594 | return b.invalid_user_input; |
| 1595 | 1595 | } |
| 1596 | 1596 | |
| 1597 | fn allocPrintCmd(gpa: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) error{OutOfMemory}![]u8 { | |
| 1598 | var buf: ArrayList(u8) = .empty; | |
| 1599 | if (opt_cwd) |cwd| try buf.print(gpa, "cd {s} && ", .{cwd}); | |
| 1600 | for (argv) |arg| { | |
| 1601 | try buf.print(gpa, "{s} ", .{arg}); | |
| 1602 | } | |
| 1603 | return buf.toOwnedSlice(gpa); | |
| 1604 | } | |
| 1605 | ||
| 1606 | fn printCmd(ally: Allocator, cwd: ?[]const u8, argv: []const []const u8) void { | |
| 1607 | const text = allocPrintCmd(ally, cwd, argv) catch @panic("OOM"); | |
| 1608 | std.debug.print("{s}\n", .{text}); | |
| 1609 | } | |
| 1610 | ||
| 1611 | 1597 | /// This creates the install step and adds it to the dependencies of the |
| 1612 | 1598 | /// top-level install step, using all the default options. |
| 1613 | 1599 | /// See `addInstallArtifact` for a more flexible function. |
| ... | ... | @@ -1857,14 +1843,14 @@ pub fn runAllowFail( |
| 1857 | 1843 | pub fn run(b: *Build, argv: []const []const u8) []u8 { |
| 1858 | 1844 | if (!process.can_spawn) { |
| 1859 | 1845 | std.debug.print("unable to spawn the following command: cannot spawn child process\n{s}\n", .{ |
| 1860 | try allocPrintCmd(b.allocator, null, argv), | |
| 1846 | try Step.allocPrintCmd(b.allocator, null, argv), | |
| 1861 | 1847 | }); |
| 1862 | 1848 | process.exit(1); |
| 1863 | 1849 | } |
| 1864 | 1850 | |
| 1865 | 1851 | var code: u8 = undefined; |
| 1866 | 1852 | return b.runAllowFail(argv, &code, .Inherit) catch |err| { |
| 1867 | const printed_cmd = allocPrintCmd(b.allocator, null, argv) catch @panic("OOM"); | |
| 1853 | const printed_cmd = Step.allocPrintCmd(b.allocator, null, argv) catch @panic("OOM"); | |
| 1868 | 1854 | std.debug.print("unable to spawn the following command: {s}\n{s}\n", .{ |
| 1869 | 1855 | @errorName(err), printed_cmd, |
| 1870 | 1856 | }); |
lib/std/Build/Step.zig+40-46| ... | ... | @@ -56,6 +56,9 @@ result_cached: bool, |
| 56 | 56 | result_duration_ns: ?u64, |
| 57 | 57 | /// 0 means unavailable or not reported. |
| 58 | 58 | result_peak_rss: usize, |
| 59 | /// If the step is failed and this field is populated, this is the command which failed. | |
| 60 | /// This field may be populated even if the step succeeded. | |
| 61 | result_failed_command: ?[]const u8, | |
| 59 | 62 | test_results: TestResults, |
| 60 | 63 | |
| 61 | 64 | /// The return address associated with creation of this step that can be useful |
| ... | ... | @@ -257,6 +260,7 @@ pub fn init(options: StepOptions) Step { |
| 257 | 260 | .result_cached = false, |
| 258 | 261 | .result_duration_ns = null, |
| 259 | 262 | .result_peak_rss = 0, |
| 263 | .result_failed_command = null, | |
| 260 | 264 | .test_results = .{}, |
| 261 | 265 | }; |
| 262 | 266 | } |
| ... | ... | @@ -336,20 +340,20 @@ pub fn dump(step: *Step, w: *std.Io.Writer, tty_config: std.Io.tty.Config) void |
| 336 | 340 | } |
| 337 | 341 | } |
| 338 | 342 | |
| 339 | pub fn evalChildProcess(s: *Step, argv: []const []const u8) ![]u8 { | |
| 340 | const run_result = try captureChildProcess(s, std.Progress.Node.none, argv); | |
| 341 | try handleChildProcessTerm(s, run_result.term, null, argv); | |
| 342 | return run_result.stdout; | |
| 343 | } | |
| 344 | ||
| 343 | /// Populates `s.result_failed_command`. | |
| 345 | 344 | pub fn captureChildProcess( |
| 346 | 345 | s: *Step, |
| 346 | gpa: Allocator, | |
| 347 | 347 | progress_node: std.Progress.Node, |
| 348 | 348 | argv: []const []const u8, |
| 349 | 349 | ) !std.process.Child.RunResult { |
| 350 | 350 | const arena = s.owner.allocator; |
| 351 | 351 | |
| 352 | try handleChildProcUnsupported(s, null, argv); | |
| 352 | // If an error occurs, it's happened in this command: | |
| 353 | assert(s.result_failed_command == null); | |
| 354 | s.result_failed_command = try allocPrintCmd(gpa, null, argv); | |
| 355 | ||
| 356 | try handleChildProcUnsupported(s); | |
| 353 | 357 | try handleVerbose(s.owner, null, argv); |
| 354 | 358 | |
| 355 | 359 | const result = std.process.Child.run(.{ |
| ... | ... | @@ -386,6 +390,7 @@ pub const ZigProcess = struct { |
| 386 | 390 | |
| 387 | 391 | /// Assumes that argv contains `--listen=-` and that the process being spawned |
| 388 | 392 | /// is the zig compiler - the same version that compiled the build runner. |
| 393 | /// Populates `s.result_failed_command`. | |
| 389 | 394 | pub fn evalZigProcess( |
| 390 | 395 | s: *Step, |
| 391 | 396 | argv: []const []const u8, |
| ... | ... | @@ -394,6 +399,10 @@ pub fn evalZigProcess( |
| 394 | 399 | web_server: ?*Build.WebServer, |
| 395 | 400 | gpa: Allocator, |
| 396 | 401 | ) !?Path { |
| 402 | // If an error occurs, it's happened in this command: | |
| 403 | assert(s.result_failed_command == null); | |
| 404 | s.result_failed_command = try allocPrintCmd(gpa, null, argv); | |
| 405 | ||
| 397 | 406 | if (s.getZigProcess()) |zp| update: { |
| 398 | 407 | assert(watch); |
| 399 | 408 | if (std.Progress.have_ipc) if (zp.progress_ipc_fd) |fd| prog_node.setIpcFd(fd); |
| ... | ... | @@ -410,8 +419,9 @@ pub fn evalZigProcess( |
| 410 | 419 | else => |e| return e, |
| 411 | 420 | }; |
| 412 | 421 | |
| 413 | if (s.result_error_bundle.errorMessageCount() > 0) | |
| 422 | if (s.result_error_bundle.errorMessageCount() > 0) { | |
| 414 | 423 | return s.fail("{d} compilation errors", .{s.result_error_bundle.errorMessageCount()}); |
| 424 | } | |
| 415 | 425 | |
| 416 | 426 | if (s.result_error_msgs.items.len > 0 and result == null) { |
| 417 | 427 | // Crash detected. |
| ... | ... | @@ -420,7 +430,7 @@ pub fn evalZigProcess( |
| 420 | 430 | }; |
| 421 | 431 | s.result_peak_rss = zp.child.resource_usage_statistics.getMaxRss() orelse 0; |
| 422 | 432 | s.clearZigProcess(gpa); |
| 423 | try handleChildProcessTerm(s, term, null, argv); | |
| 433 | try handleChildProcessTerm(s, term); | |
| 424 | 434 | return error.MakeFailed; |
| 425 | 435 | } |
| 426 | 436 | |
| ... | ... | @@ -430,7 +440,7 @@ pub fn evalZigProcess( |
| 430 | 440 | const b = s.owner; |
| 431 | 441 | const arena = b.allocator; |
| 432 | 442 | |
| 433 | try handleChildProcUnsupported(s, null, argv); | |
| 443 | try handleChildProcUnsupported(s); | |
| 434 | 444 | try handleVerbose(s.owner, null, argv); |
| 435 | 445 | |
| 436 | 446 | var child = std.process.Child.init(argv, arena); |
| ... | ... | @@ -484,16 +494,11 @@ pub fn evalZigProcess( |
| 484 | 494 | else => {}, |
| 485 | 495 | }; |
| 486 | 496 | |
| 487 | try handleChildProcessTerm(s, term, null, argv); | |
| 497 | try handleChildProcessTerm(s, term); | |
| 488 | 498 | } |
| 489 | 499 | |
| 490 | // This is intentionally printed for failure on the first build but not for | |
| 491 | // subsequent rebuilds. | |
| 492 | 500 | if (s.result_error_bundle.errorMessageCount() > 0) { |
| 493 | return s.fail("the following command failed with {d} compilation errors:\n{s}", .{ | |
| 494 | s.result_error_bundle.errorMessageCount(), | |
| 495 | try allocPrintCmd(arena, null, argv), | |
| 496 | }); | |
| 501 | return s.fail("{d} compilation errors", .{s.result_error_bundle.errorMessageCount()}); | |
| 497 | 502 | } |
| 498 | 503 | |
| 499 | 504 | return result; |
| ... | ... | @@ -696,54 +701,38 @@ pub fn handleVerbose2( |
| 696 | 701 | } |
| 697 | 702 | } |
| 698 | 703 | |
| 699 | pub inline fn handleChildProcUnsupported( | |
| 700 | s: *Step, | |
| 701 | opt_cwd: ?[]const u8, | |
| 702 | argv: []const []const u8, | |
| 703 | ) error{ OutOfMemory, MakeFailed }!void { | |
| 704 | /// Asserts that the caller has already populated `s.result_failed_command`. | |
| 705 | pub inline fn handleChildProcUnsupported(s: *Step) error{ OutOfMemory, MakeFailed }!void { | |
| 704 | 706 | if (!std.process.can_spawn) { |
| 705 | return s.fail( | |
| 706 | "unable to execute the following command: host cannot spawn child processes\n{s}", | |
| 707 | .{try allocPrintCmd(s.owner.allocator, opt_cwd, argv)}, | |
| 708 | ); | |
| 707 | return s.fail("unable to spawn process: host cannot spawn child processes", .{}); | |
| 709 | 708 | } |
| 710 | 709 | } |
| 711 | 710 | |
| 712 | pub fn handleChildProcessTerm( | |
| 713 | s: *Step, | |
| 714 | term: std.process.Child.Term, | |
| 715 | opt_cwd: ?[]const u8, | |
| 716 | argv: []const []const u8, | |
| 717 | ) error{ MakeFailed, OutOfMemory }!void { | |
| 718 | const arena = s.owner.allocator; | |
| 711 | /// Asserts that the caller has already populated `s.result_failed_command`. | |
| 712 | pub fn handleChildProcessTerm(s: *Step, term: std.process.Child.Term) error{ MakeFailed, OutOfMemory }!void { | |
| 713 | assert(s.result_failed_command != null); | |
| 719 | 714 | switch (term) { |
| 720 | 715 | .Exited => |code| { |
| 721 | 716 | if (code != 0) { |
| 722 | return s.fail( | |
| 723 | "the following command exited with error code {d}:\n{s}", | |
| 724 | .{ code, try allocPrintCmd(arena, opt_cwd, argv) }, | |
| 725 | ); | |
| 717 | return s.fail("process exited with error code {d}", .{code}); | |
| 726 | 718 | } |
| 727 | 719 | }, |
| 728 | 720 | .Signal, .Stopped, .Unknown => { |
| 729 | return s.fail( | |
| 730 | "the following command terminated unexpectedly:\n{s}", | |
| 731 | .{try allocPrintCmd(arena, opt_cwd, argv)}, | |
| 732 | ); | |
| 721 | return s.fail("process terminated unexpectedly", .{}); | |
| 733 | 722 | }, |
| 734 | 723 | } |
| 735 | 724 | } |
| 736 | 725 | |
| 737 | 726 | pub fn allocPrintCmd( |
| 738 | arena: Allocator, | |
| 727 | gpa: Allocator, | |
| 739 | 728 | opt_cwd: ?[]const u8, |
| 740 | 729 | argv: []const []const u8, |
| 741 | 730 | ) Allocator.Error![]u8 { |
| 742 | return allocPrintCmd2(arena, opt_cwd, null, argv); | |
| 731 | return allocPrintCmd2(gpa, opt_cwd, null, argv); | |
| 743 | 732 | } |
| 744 | 733 | |
| 745 | 734 | pub fn allocPrintCmd2( |
| 746 | arena: Allocator, | |
| 735 | gpa: Allocator, | |
| 747 | 736 | opt_cwd: ?[]const u8, |
| 748 | 737 | opt_env: ?*const std.process.EnvMap, |
| 749 | 738 | argv: []const []const u8, |
| ... | ... | @@ -783,11 +772,13 @@ pub fn allocPrintCmd2( |
| 783 | 772 | } |
| 784 | 773 | }; |
| 785 | 774 | |
| 786 | var aw: std.Io.Writer.Allocating = .init(arena); | |
| 775 | var aw: std.Io.Writer.Allocating = .init(gpa); | |
| 776 | defer aw.deinit(); | |
| 787 | 777 | const writer = &aw.writer; |
| 788 | 778 | if (opt_cwd) |cwd| writer.print("cd {s} && ", .{cwd}) catch return error.OutOfMemory; |
| 789 | 779 | if (opt_env) |env| { |
| 790 | const process_env_map = std.process.getEnvMap(arena) catch std.process.EnvMap.init(arena); | |
| 780 | var process_env_map = std.process.getEnvMap(gpa) catch std.process.EnvMap.init(gpa); | |
| 781 | defer process_env_map.deinit(); | |
| 791 | 782 | var it = env.iterator(); |
| 792 | 783 | while (it.next()) |entry| { |
| 793 | 784 | const key = entry.key_ptr.*; |
| ... | ... | @@ -973,11 +964,14 @@ fn addWatchInputFromPath(step: *Step, path: Build.Cache.Path, basename: []const |
| 973 | 964 | pub fn reset(step: *Step, gpa: Allocator) void { |
| 974 | 965 | assert(step.state == .precheck_done); |
| 975 | 966 | |
| 967 | if (step.result_failed_command) |cmd| gpa.free(cmd); | |
| 968 | ||
| 976 | 969 | step.result_error_msgs.clearRetainingCapacity(); |
| 977 | 970 | step.result_stderr = ""; |
| 978 | 971 | step.result_cached = false; |
| 979 | 972 | step.result_duration_ns = null; |
| 980 | 973 | step.result_peak_rss = 0; |
| 974 | step.result_failed_command = null; | |
| 981 | 975 | step.test_results = .{}; |
| 982 | 976 | |
| 983 | 977 | step.result_error_bundle.deinit(gpa); |
lib/std/Build/Step/Fmt.zig+2-2| ... | ... | @@ -67,7 +67,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 67 | 67 | argv.appendAssumeCapacity(b.pathFromRoot(p)); |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | const run_result = try step.captureChildProcess(prog_node, argv.items); | |
| 70 | const run_result = try step.captureChildProcess(options.gpa, prog_node, argv.items); | |
| 71 | 71 | if (fmt.check) switch (run_result.term) { |
| 72 | 72 | .Exited => |code| if (code != 0 and run_result.stdout.len != 0) { |
| 73 | 73 | var it = std.mem.tokenizeScalar(u8, run_result.stdout, '\n'); |
| ... | ... | @@ -77,5 +77,5 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 77 | 77 | }, |
| 78 | 78 | else => {}, |
| 79 | 79 | }; |
| 80 | try step.handleChildProcessTerm(run_result.term, null, argv.items); | |
| 80 | try step.handleChildProcessTerm(run_result.term); | |
| 81 | 81 | } |
lib/std/Build/Step/Run.zig+19-35| ... | ... | @@ -1212,10 +1212,11 @@ fn runCommand( |
| 1212 | 1212 | const step = &run.step; |
| 1213 | 1213 | const b = step.owner; |
| 1214 | 1214 | const arena = b.allocator; |
| 1215 | const gpa = options.gpa; | |
| 1215 | 1216 | |
| 1216 | 1217 | const cwd: ?[]const u8 = if (run.cwd) |lazy_cwd| lazy_cwd.getPath2(b, step) else null; |
| 1217 | 1218 | |
| 1218 | try step.handleChildProcUnsupported(cwd, argv); | |
| 1219 | try step.handleChildProcUnsupported(); | |
| 1219 | 1220 | try Step.handleVerbose2(step.owner, cwd, run.env_map, argv); |
| 1220 | 1221 | |
| 1221 | 1222 | const allow_skip = switch (run.stdio) { |
| ... | ... | @@ -1365,6 +1366,8 @@ fn runCommand( |
| 1365 | 1366 | run.addPathForDynLibs(exe); |
| 1366 | 1367 | } |
| 1367 | 1368 | |
| 1369 | gpa.free(step.result_failed_command.?); | |
| 1370 | step.result_failed_command = null; | |
| 1368 | 1371 | try Step.handleVerbose2(step.owner, cwd, run.env_map, interp_argv.items); |
| 1369 | 1372 | |
| 1370 | 1373 | break :term spawnChildAndCollect(run, interp_argv.items, env_map, has_side_effects, options, fuzz_context) catch |e| { |
| ... | ... | @@ -1380,18 +1383,11 @@ fn runCommand( |
| 1380 | 1383 | return step.fail("failed to spawn and capture stdio from {s}: {s}", .{ argv[0], @errorName(err) }); |
| 1381 | 1384 | }; |
| 1382 | 1385 | |
| 1383 | const final_argv = if (interp_argv.items.len == 0) argv else interp_argv.items; | |
| 1384 | ||
| 1385 | 1386 | const generic_result = opt_generic_result orelse { |
| 1386 | 1387 | assert(run.stdio == .zig_test); |
| 1387 | // Specific errors have already been reported. All we need to do is detect those and | |
| 1388 | // report the general "test failed" error, which includes the command argv. | |
| 1389 | if (!step.test_results.isSuccess() or step.result_error_msgs.items.len > 0) { | |
| 1390 | return step.fail( | |
| 1391 | "the following test command failed:\n{s}", | |
| 1392 | .{try Step.allocPrintCmd(arena, cwd, final_argv)}, | |
| 1393 | ); | |
| 1394 | } | |
| 1388 | // Specific errors have already been reported, and test results are populated. All we need | |
| 1389 | // to do is report step failure if any test failed. | |
| 1390 | if (!step.test_results.isSuccess()) return error.MakeFailed; | |
| 1395 | 1391 | return; |
| 1396 | 1392 | }; |
| 1397 | 1393 | |
| ... | ... | @@ -1445,93 +1441,77 @@ fn runCommand( |
| 1445 | 1441 | .expect_stderr_exact => |expected_bytes| { |
| 1446 | 1442 | if (!mem.eql(u8, expected_bytes, generic_result.stderr.?)) { |
| 1447 | 1443 | return step.fail( |
| 1448 | \\ | |
| 1449 | 1444 | \\========= expected this stderr: ========= |
| 1450 | 1445 | \\{s} |
| 1451 | 1446 | \\========= but found: ==================== |
| 1452 | 1447 | \\{s} |
| 1453 | \\========= from the following command: === | |
| 1454 | \\{s} | |
| 1455 | 1448 | , .{ |
| 1456 | 1449 | expected_bytes, |
| 1457 | 1450 | generic_result.stderr.?, |
| 1458 | try Step.allocPrintCmd(arena, cwd, final_argv), | |
| 1459 | 1451 | }); |
| 1460 | 1452 | } |
| 1461 | 1453 | }, |
| 1462 | 1454 | .expect_stderr_match => |match| { |
| 1463 | 1455 | if (mem.indexOf(u8, generic_result.stderr.?, match) == null) { |
| 1464 | 1456 | return step.fail( |
| 1465 | \\ | |
| 1466 | 1457 | \\========= expected to find in stderr: ========= |
| 1467 | 1458 | \\{s} |
| 1468 | 1459 | \\========= but stderr does not contain it: ===== |
| 1469 | 1460 | \\{s} |
| 1470 | \\========= from the following command: ========= | |
| 1471 | \\{s} | |
| 1472 | 1461 | , .{ |
| 1473 | 1462 | match, |
| 1474 | 1463 | generic_result.stderr.?, |
| 1475 | try Step.allocPrintCmd(arena, cwd, final_argv), | |
| 1476 | 1464 | }); |
| 1477 | 1465 | } |
| 1478 | 1466 | }, |
| 1479 | 1467 | .expect_stdout_exact => |expected_bytes| { |
| 1480 | 1468 | if (!mem.eql(u8, expected_bytes, generic_result.stdout.?)) { |
| 1481 | 1469 | return step.fail( |
| 1482 | \\ | |
| 1483 | 1470 | \\========= expected this stdout: ========= |
| 1484 | 1471 | \\{s} |
| 1485 | 1472 | \\========= but found: ==================== |
| 1486 | 1473 | \\{s} |
| 1487 | \\========= from the following command: === | |
| 1488 | \\{s} | |
| 1489 | 1474 | , .{ |
| 1490 | 1475 | expected_bytes, |
| 1491 | 1476 | generic_result.stdout.?, |
| 1492 | try Step.allocPrintCmd(arena, cwd, final_argv), | |
| 1493 | 1477 | }); |
| 1494 | 1478 | } |
| 1495 | 1479 | }, |
| 1496 | 1480 | .expect_stdout_match => |match| { |
| 1497 | 1481 | if (mem.indexOf(u8, generic_result.stdout.?, match) == null) { |
| 1498 | 1482 | return step.fail( |
| 1499 | \\ | |
| 1500 | 1483 | \\========= expected to find in stdout: ========= |
| 1501 | 1484 | \\{s} |
| 1502 | 1485 | \\========= but stdout does not contain it: ===== |
| 1503 | 1486 | \\{s} |
| 1504 | \\========= from the following command: ========= | |
| 1505 | \\{s} | |
| 1506 | 1487 | , .{ |
| 1507 | 1488 | match, |
| 1508 | 1489 | generic_result.stdout.?, |
| 1509 | try Step.allocPrintCmd(arena, cwd, final_argv), | |
| 1510 | 1490 | }); |
| 1511 | 1491 | } |
| 1512 | 1492 | }, |
| 1513 | 1493 | .expect_term => |expected_term| { |
| 1514 | 1494 | if (!termMatches(expected_term, generic_result.term)) { |
| 1515 | return step.fail("the following command {f} (expected {f}):\n{s}", .{ | |
| 1495 | return step.fail("process {f} (expected {f})", .{ | |
| 1516 | 1496 | fmtTerm(generic_result.term), |
| 1517 | 1497 | fmtTerm(expected_term), |
| 1518 | try Step.allocPrintCmd(arena, cwd, final_argv), | |
| 1519 | 1498 | }); |
| 1520 | 1499 | } |
| 1521 | 1500 | }, |
| 1522 | 1501 | }, |
| 1523 | 1502 | else => { |
| 1524 | // On failure, print stderr if captured. | |
| 1503 | // On failure, report captured stderr like normal standard error output. | |
| 1525 | 1504 | const bad_exit = switch (generic_result.term) { |
| 1526 | 1505 | .Exited => |code| code != 0, |
| 1527 | 1506 | .Signal, .Stopped, .Unknown => true, |
| 1528 | 1507 | }; |
| 1508 | if (bad_exit) { | |
| 1509 | if (generic_result.stderr) |bytes| { | |
| 1510 | run.step.result_stderr = bytes; | |
| 1511 | } | |
| 1512 | } | |
| 1529 | 1513 | |
| 1530 | if (bad_exit) if (generic_result.stderr) |err| { | |
| 1531 | try step.addError("stderr:\n{s}", .{err}); | |
| 1532 | }; | |
| 1533 | ||
| 1534 | try step.handleChildProcessTerm(generic_result.term, cwd, final_argv); | |
| 1514 | try step.handleChildProcessTerm(generic_result.term); | |
| 1535 | 1515 | }, |
| 1536 | 1516 | } |
| 1537 | 1517 | } |
| ... | ... | @@ -1594,6 +1574,10 @@ fn spawnChildAndCollect( |
| 1594 | 1574 | child.stdin_behavior = .Pipe; |
| 1595 | 1575 | } |
| 1596 | 1576 | |
| 1577 | // If an error occurs, it's caused by this command: | |
| 1578 | assert(run.step.result_failed_command == null); | |
| 1579 | run.step.result_failed_command = try Step.allocPrintCmd(options.gpa, child.cwd, argv); | |
| 1580 | ||
| 1597 | 1581 | if (run.stdio == .zig_test) { |
| 1598 | 1582 | var timer = try std.time.Timer.start(); |
| 1599 | 1583 | const res = try evalZigTest(run, &child, options, fuzz_context); |