Commit baead472d7

Jonathan Marler <johnnymarler@gmail.com>
2021-10-20 23:49:48
reduce build error noise
Address https://github.com/ziglang/zig/issues/3477 This provides a mechanism for builds to fully report an error to the user and prevent zig from piling on extra noise.
1 parent e2ad95c
Changed files (5)
lib
src
test
standalone
fail_full_report
lib/std/build.zig
@@ -3438,3 +3438,17 @@ test "LibExeObjStep.addPackage" {
     const dupe = exe.packages.items[0];
     try std.testing.expectEqualStrings(pkg_top.name, dupe.name);
 }
+
+/// This exit code from either "zig build" or the build_runner indicates
+/// the "full reason" for a build failure has already been reported to stderr.
+/// This will prevent 'zig` from piling on errors to the ones reported by the
+/// build_runner.
+pub const fail_fully_reported_exit_code = 0x3f;
+
+/// Print an error message to stderr and exit with a special exit
+/// code that notifies the invoking process that the build error
+/// has already been fully reported to stderr.
+pub fn fatalFullReport(comptime error_fmt: []const u8, args: anytype) noreturn {
+    std.log.err(error_fmt, args);
+    std.os.exit(fail_fully_reported_exit_code);
+}
src/main.zig
@@ -3616,7 +3616,9 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
             .Exited => |code| {
                 if (code == 0) return cleanExit();
 
-                if (prominent_compile_errors) {
+                if (code == std.build.fail_fully_reported_exit_code) {
+                    process.exit(std.build.fail_fully_reported_exit_code);
+                } else if (prominent_compile_errors) {
                     fatal("the build command failed with exit code {d}", .{code});
                 } else {
                     const cmd = try std.mem.join(arena, " ", child_argv);
test/standalone/fail_full_report/build.zig
@@ -0,0 +1,32 @@
+const std = @import("std");
+const Builder = std.build.Builder;
+
+pub fn build(b: *Builder) !void {
+    const test_step = b.step("test", "The test");
+
+    {
+        const run_step = b.addSystemCommand(&[_][]const u8{
+            b.zig_exe,
+            "build",
+            "--build-file",
+            "build2.zig",
+        });
+        run_step.stdout_action = .{ .expect_exact = "" };
+        test_step.dependOn(&run_step.step);
+    }
+
+    {
+        const run_step = b.addSystemCommand(&[_][]const u8{
+            b.zig_exe,
+            "build",
+            "--build-file",
+            "build2.zig",
+            "-Dbadoption",
+        });
+        run_step.stderr_action = .{ .expect_exact = "error: got a bad build option!\n" };
+        run_step.expected_exit_code = std.build.fail_fully_reported_exit_code;
+        test_step.dependOn(&run_step.step);
+    }
+
+    b.default_step.dependOn(test_step);
+}
test/standalone/fail_full_report/build2.zig
@@ -0,0 +1,8 @@
+const std = @import("std");
+const Builder = std.build.Builder;
+
+pub fn build(b: *Builder) !void {
+    const bad_option = if (b.option(bool, "badoption", "Use this to emulator a bad build option")) |o| o else false;
+    if (bad_option)
+        std.build.fatalFullReport("got a bad build option!", .{});
+}
test/standalone.zig
@@ -49,6 +49,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
     cases.addBuildFile("test/standalone/issue_7030/build.zig", .{});
     cases.addBuildFile("test/standalone/install_raw_hex/build.zig", .{});
     cases.addBuildFile("test/standalone/issue_9812/build.zig", .{});
+    cases.addBuildFile("test/standalone/fail_full_report/build.zig", .{});
     if (builtin.os.tag != .wasi) {
         cases.addBuildFile("test/standalone/load_dynamic_library/build.zig", .{});
     }