| author | |
| committer | |
| log | cce32bd1d505ee5c5ea7878c9e9e57b6b63856f2 |
| tree | 944f136cbdd9d6662cbae2c14bbf7d8d862739bb |
| parent | ec3b5f0c7474b22dfbf2f19e0121a1f87a58efd0 |
8 files changed, 254 insertions(+), 251 deletions(-)
lib/compiler/build_runner.zig+81-68| ... | @@ -12,6 +12,7 @@ const Watch = std.Build.Watch; | ... | @@ -12,6 +12,7 @@ const Watch = std.Build.Watch; |
| 12 | const Fuzz = std.Build.Fuzz; | 12 | const Fuzz = std.Build.Fuzz; |
| 13 | const Allocator = std.mem.Allocator; | 13 | const Allocator = std.mem.Allocator; |
| 14 | const fatal = std.process.fatal; | 14 | const fatal = std.process.fatal; |
| 15 | const Writer = std.io.Writer; | ||
| 15 | const runner = @This(); | 16 | const runner = @This(); |
| 16 | 17 | ||
| 17 | pub const root = @import("@build"); | 18 | pub const root = @import("@build"); |
| ... | @@ -330,7 +331,7 @@ pub fn main() !void { | ... | @@ -330,7 +331,7 @@ pub fn main() !void { |
| 330 | } | 331 | } |
| 331 | } | 332 | } |
| 332 | 333 | ||
| 333 | const stderr = std.fs.File.stderr(); | 334 | const stderr: std.fs.File = .stderr(); |
| 334 | const ttyconf = get_tty_conf(color, stderr); | 335 | const ttyconf = get_tty_conf(color, stderr); |
| 335 | switch (ttyconf) { | 336 | switch (ttyconf) { |
| 336 | .no_color => try graph.env_map.put("NO_COLOR", "1"), | 337 | .no_color => try graph.env_map.put("NO_COLOR", "1"), |
| ... | @@ -378,13 +379,19 @@ pub fn main() !void { | ... | @@ -378,13 +379,19 @@ pub fn main() !void { |
| 378 | 379 | ||
| 379 | validateSystemLibraryOptions(builder); | 380 | validateSystemLibraryOptions(builder); |
| 380 | 381 | ||
| 381 | const stdout_writer = std.fs.File.stdout().deprecatedWriter(); | 382 | if (help_menu) { |
| 382 | 383 | var w = initStdoutWriter(); | |
| 383 | if (help_menu) | 384 | printUsage(builder, w) catch return stdout_writer_allocation.err.?; |
| 384 | return usage(builder, stdout_writer); | 385 | w.flush() catch return stdout_writer_allocation.err.?; |
| 386 | return; | ||
| 387 | } | ||
| 385 | 388 | ||
| 386 | if (steps_menu) | 389 | if (steps_menu) { |
| 387 | return steps(builder, stdout_writer); | 390 | var w = initStdoutWriter(); |
| 391 | printSteps(builder, w) catch return stdout_writer_allocation.err.?; | ||
| 392 | w.flush() catch return stdout_writer_allocation.err.?; | ||
| 393 | return; | ||
| 394 | } | ||
| 388 | 395 | ||
| 389 | var run: Run = .{ | 396 | var run: Run = .{ |
| 390 | .max_rss = max_rss, | 397 | .max_rss = max_rss, |
| ... | @@ -696,24 +703,21 @@ fn runStepNames( | ... | @@ -696,24 +703,21 @@ fn runStepNames( |
| 696 | const ttyconf = run.ttyconf; | 703 | const ttyconf = run.ttyconf; |
| 697 | 704 | ||
| 698 | if (run.summary != .none) { | 705 | if (run.summary != .none) { |
| 699 | std.debug.lockStdErr(); | 706 | const w = std.debug.lockStderrWriter(&stdio_buffer_allocation); |
| 700 | defer std.debug.unlockStdErr(); | 707 | defer std.debug.unlockStderrWriter(); |
| 701 | const stderr = run.stderr; | ||
| 702 | 708 | ||
| 703 | const total_count = success_count + failure_count + pending_count + skipped_count; | 709 | const total_count = success_count + failure_count + pending_count + skipped_count; |
| 704 | ttyconf.setColor(stderr, .cyan) catch {}; | 710 | ttyconf.setColor(w, .cyan) catch {}; |
| 705 | stderr.writeAll("Build Summary:") catch {}; | 711 | w.writeAll("Build Summary:") catch {}; |
| 706 | ttyconf.setColor(stderr, .reset) catch {}; | 712 | ttyconf.setColor(w, .reset) catch {}; |
| 707 | stderr.deprecatedWriter().print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {}; | 713 | w.print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {}; |
| 708 | if (skipped_count > 0) stderr.deprecatedWriter().print("; {d} skipped", .{skipped_count}) catch {}; | 714 | if (skipped_count > 0) w.print("; {d} skipped", .{skipped_count}) catch {}; |
| 709 | if (failure_count > 0) stderr.deprecatedWriter().print("; {d} failed", .{failure_count}) catch {}; | 715 | if (failure_count > 0) w.print("; {d} failed", .{failure_count}) catch {}; |
| 710 | 716 | ||
| 711 | if (test_count > 0) stderr.deprecatedWriter().print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {}; | 717 | if (test_count > 0) w.print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {}; |
| 712 | if (test_skip_count > 0) stderr.deprecatedWriter().print("; {d} skipped", .{test_skip_count}) catch {}; | 718 | if (test_skip_count > 0) w.print("; {d} skipped", .{test_skip_count}) catch {}; |
| 713 | if (test_fail_count > 0) stderr.deprecatedWriter().print("; {d} failed", .{test_fail_count}) catch {}; | 719 | if (test_fail_count > 0) w.print("; {d} failed", .{test_fail_count}) catch {}; |
| 714 | if (test_leak_count > 0) stderr.deprecatedWriter().print("; {d} leaked", .{test_leak_count}) catch {}; | 720 | if (test_leak_count > 0) w.print("; {d} leaked", .{test_leak_count}) catch {}; |
| 715 | |||
| 716 | stderr.writeAll("\n") catch {}; | ||
| 717 | 721 | ||
| 718 | // Print a fancy tree with build results. | 722 | // Print a fancy tree with build results. |
| 719 | var step_stack_copy = try step_stack.clone(gpa); | 723 | var step_stack_copy = try step_stack.clone(gpa); |
| ... | @@ -722,7 +726,7 @@ fn runStepNames( | ... | @@ -722,7 +726,7 @@ fn runStepNames( |
| 722 | var print_node: PrintNode = .{ .parent = null }; | 726 | var print_node: PrintNode = .{ .parent = null }; |
| 723 | if (step_names.len == 0) { | 727 | if (step_names.len == 0) { |
| 724 | print_node.last = true; | 728 | print_node.last = true; |
| 725 | printTreeStep(b, b.default_step, run, stderr, ttyconf, &print_node, &step_stack_copy) catch {}; | 729 | printTreeStep(b, b.default_step, run, w, ttyconf, &print_node, &step_stack_copy) catch {}; |
| 726 | } else { | 730 | } else { |
| 727 | const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: { | 731 | const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: { |
| 728 | var i: usize = step_names.len; | 732 | var i: usize = step_names.len; |
| ... | @@ -741,9 +745,10 @@ fn runStepNames( | ... | @@ -741,9 +745,10 @@ fn runStepNames( |
| 741 | for (step_names, 0..) |step_name, i| { | 745 | for (step_names, 0..) |step_name, i| { |
| 742 | const tls = b.top_level_steps.get(step_name).?; | 746 | const tls = b.top_level_steps.get(step_name).?; |
| 743 | print_node.last = i + 1 == last_index; | 747 | print_node.last = i + 1 == last_index; |
| 744 | printTreeStep(b, &tls.step, run, stderr, ttyconf, &print_node, &step_stack_copy) catch {}; | 748 | printTreeStep(b, &tls.step, run, w, ttyconf, &print_node, &step_stack_copy) catch {}; |
| 745 | } | 749 | } |
| 746 | } | 750 | } |
| 751 | w.writeByte('\n') catch {}; | ||
| 747 | } | 752 | } |
| 748 | 753 | ||
| 749 | if (failure_count == 0) { | 754 | if (failure_count == 0) { |
| ... | @@ -775,7 +780,7 @@ const PrintNode = struct { | ... | @@ -775,7 +780,7 @@ const PrintNode = struct { |
| 775 | last: bool = false, | 780 | last: bool = false, |
| 776 | }; | 781 | }; |
| 777 | 782 | ||
| 778 | fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void { | 783 | fn printPrefix(node: *PrintNode, stderr: *Writer, ttyconf: std.io.tty.Config) !void { |
| 779 | const parent = node.parent orelse return; | 784 | const parent = node.parent orelse return; |
| 780 | if (parent.parent == null) return; | 785 | if (parent.parent == null) return; |
| 781 | try printPrefix(parent, stderr, ttyconf); | 786 | try printPrefix(parent, stderr, ttyconf); |
| ... | @@ -789,7 +794,7 @@ fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void | ... | @@ -789,7 +794,7 @@ fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void |
| 789 | } | 794 | } |
| 790 | } | 795 | } |
| 791 | 796 | ||
| 792 | fn printChildNodePrefix(stderr: File, ttyconf: std.io.tty.Config) !void { | 797 | fn printChildNodePrefix(stderr: *Writer, ttyconf: std.io.tty.Config) !void { |
| 793 | try stderr.writeAll(switch (ttyconf) { | 798 | try stderr.writeAll(switch (ttyconf) { |
| 794 | .no_color, .windows_api => "+- ", | 799 | .no_color, .windows_api => "+- ", |
| 795 | .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ | 800 | .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ |
| ... | @@ -798,7 +803,7 @@ fn printChildNodePrefix(stderr: File, ttyconf: std.io.tty.Config) !void { | ... | @@ -798,7 +803,7 @@ fn printChildNodePrefix(stderr: File, ttyconf: std.io.tty.Config) !void { |
| 798 | 803 | ||
| 799 | fn printStepStatus( | 804 | fn printStepStatus( |
| 800 | s: *Step, | 805 | s: *Step, |
| 801 | stderr: File, | 806 | stderr: *Writer, |
| 802 | ttyconf: std.io.tty.Config, | 807 | ttyconf: std.io.tty.Config, |
| 803 | run: *const Run, | 808 | run: *const Run, |
| 804 | ) !void { | 809 | ) !void { |
| ... | @@ -820,10 +825,10 @@ fn printStepStatus( | ... | @@ -820,10 +825,10 @@ fn printStepStatus( |
| 820 | try stderr.writeAll(" cached"); | 825 | try stderr.writeAll(" cached"); |
| 821 | } else if (s.test_results.test_count > 0) { | 826 | } else if (s.test_results.test_count > 0) { |
| 822 | const pass_count = s.test_results.passCount(); | 827 | const pass_count = s.test_results.passCount(); |
| 823 | try stderr.deprecatedWriter().print(" {d} passed", .{pass_count}); | 828 | try stderr.print(" {d} passed", .{pass_count}); |
| 824 | if (s.test_results.skip_count > 0) { | 829 | if (s.test_results.skip_count > 0) { |
| 825 | try ttyconf.setColor(stderr, .yellow); | 830 | try ttyconf.setColor(stderr, .yellow); |
| 826 | try stderr.deprecatedWriter().print(" {d} skipped", .{s.test_results.skip_count}); | 831 | try stderr.print(" {d} skipped", .{s.test_results.skip_count}); |
| 827 | } | 832 | } |
| 828 | } else { | 833 | } else { |
| 829 | try stderr.writeAll(" success"); | 834 | try stderr.writeAll(" success"); |
| ... | @@ -832,15 +837,15 @@ fn printStepStatus( | ... | @@ -832,15 +837,15 @@ fn printStepStatus( |
| 832 | if (s.result_duration_ns) |ns| { | 837 | if (s.result_duration_ns) |ns| { |
| 833 | try ttyconf.setColor(stderr, .dim); | 838 | try ttyconf.setColor(stderr, .dim); |
| 834 | if (ns >= std.time.ns_per_min) { | 839 | if (ns >= std.time.ns_per_min) { |
| 835 | try stderr.deprecatedWriter().print(" {d}m", .{ns / std.time.ns_per_min}); | 840 | try stderr.print(" {d}m", .{ns / std.time.ns_per_min}); |
| 836 | } else if (ns >= std.time.ns_per_s) { | 841 | } else if (ns >= std.time.ns_per_s) { |
| 837 | try stderr.deprecatedWriter().print(" {d}s", .{ns / std.time.ns_per_s}); | 842 | try stderr.print(" {d}s", .{ns / std.time.ns_per_s}); |
| 838 | } else if (ns >= std.time.ns_per_ms) { | 843 | } else if (ns >= std.time.ns_per_ms) { |
| 839 | try stderr.deprecatedWriter().print(" {d}ms", .{ns / std.time.ns_per_ms}); | 844 | try stderr.print(" {d}ms", .{ns / std.time.ns_per_ms}); |
| 840 | } else if (ns >= std.time.ns_per_us) { | 845 | } else if (ns >= std.time.ns_per_us) { |
| 841 | try stderr.deprecatedWriter().print(" {d}us", .{ns / std.time.ns_per_us}); | 846 | try stderr.print(" {d}us", .{ns / std.time.ns_per_us}); |
| 842 | } else { | 847 | } else { |
| 843 | try stderr.deprecatedWriter().print(" {d}ns", .{ns}); | 848 | try stderr.print(" {d}ns", .{ns}); |
| 844 | } | 849 | } |
| 845 | try ttyconf.setColor(stderr, .reset); | 850 | try ttyconf.setColor(stderr, .reset); |
| 846 | } | 851 | } |
| ... | @@ -848,13 +853,13 @@ fn printStepStatus( | ... | @@ -848,13 +853,13 @@ fn printStepStatus( |
| 848 | const rss = s.result_peak_rss; | 853 | const rss = s.result_peak_rss; |
| 849 | try ttyconf.setColor(stderr, .dim); | 854 | try ttyconf.setColor(stderr, .dim); |
| 850 | if (rss >= 1000_000_000) { | 855 | if (rss >= 1000_000_000) { |
| 851 | try stderr.deprecatedWriter().print(" MaxRSS:{d}G", .{rss / 1000_000_000}); | 856 | try stderr.print(" MaxRSS:{d}G", .{rss / 1000_000_000}); |
| 852 | } else if (rss >= 1000_000) { | 857 | } else if (rss >= 1000_000) { |
| 853 | try stderr.deprecatedWriter().print(" MaxRSS:{d}M", .{rss / 1000_000}); | 858 | try stderr.print(" MaxRSS:{d}M", .{rss / 1000_000}); |
| 854 | } else if (rss >= 1000) { | 859 | } else if (rss >= 1000) { |
| 855 | try stderr.deprecatedWriter().print(" MaxRSS:{d}K", .{rss / 1000}); | 860 | try stderr.print(" MaxRSS:{d}K", .{rss / 1000}); |
| 856 | } else { | 861 | } else { |
| 857 | try stderr.deprecatedWriter().print(" MaxRSS:{d}B", .{rss}); | 862 | try stderr.print(" MaxRSS:{d}B", .{rss}); |
| 858 | } | 863 | } |
| 859 | try ttyconf.setColor(stderr, .reset); | 864 | try ttyconf.setColor(stderr, .reset); |
| 860 | } | 865 | } |
| ... | @@ -866,7 +871,7 @@ fn printStepStatus( | ... | @@ -866,7 +871,7 @@ fn printStepStatus( |
| 866 | if (skip == .skipped_oom) { | 871 | if (skip == .skipped_oom) { |
| 867 | try stderr.writeAll(" (not enough memory)"); | 872 | try stderr.writeAll(" (not enough memory)"); |
| 868 | try ttyconf.setColor(stderr, .dim); | 873 | try ttyconf.setColor(stderr, .dim); |
| 869 | try stderr.deprecatedWriter().print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss }); | 874 | try stderr.print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss }); |
| 870 | try ttyconf.setColor(stderr, .yellow); | 875 | try ttyconf.setColor(stderr, .yellow); |
| 871 | } | 876 | } |
| 872 | try stderr.writeAll("\n"); | 877 | try stderr.writeAll("\n"); |
| ... | @@ -878,23 +883,23 @@ fn printStepStatus( | ... | @@ -878,23 +883,23 @@ fn printStepStatus( |
| 878 | 883 | ||
| 879 | fn printStepFailure( | 884 | fn printStepFailure( |
| 880 | s: *Step, | 885 | s: *Step, |
| 881 | stderr: File, | 886 | stderr: *Writer, |
| 882 | ttyconf: std.io.tty.Config, | 887 | ttyconf: std.io.tty.Config, |
| 883 | ) !void { | 888 | ) !void { |
| 884 | if (s.result_error_bundle.errorMessageCount() > 0) { | 889 | if (s.result_error_bundle.errorMessageCount() > 0) { |
| 885 | try ttyconf.setColor(stderr, .red); | 890 | try ttyconf.setColor(stderr, .red); |
| 886 | try stderr.deprecatedWriter().print(" {d} errors\n", .{ | 891 | try stderr.print(" {d} errors\n", .{ |
| 887 | s.result_error_bundle.errorMessageCount(), | 892 | s.result_error_bundle.errorMessageCount(), |
| 888 | }); | 893 | }); |
| 889 | try ttyconf.setColor(stderr, .reset); | 894 | try ttyconf.setColor(stderr, .reset); |
| 890 | } else if (!s.test_results.isSuccess()) { | 895 | } else if (!s.test_results.isSuccess()) { |
| 891 | try stderr.deprecatedWriter().print(" {d}/{d} passed", .{ | 896 | try stderr.print(" {d}/{d} passed", .{ |
| 892 | s.test_results.passCount(), s.test_results.test_count, | 897 | s.test_results.passCount(), s.test_results.test_count, |
| 893 | }); | 898 | }); |
| 894 | if (s.test_results.fail_count > 0) { | 899 | if (s.test_results.fail_count > 0) { |
| 895 | try stderr.writeAll(", "); | 900 | try stderr.writeAll(", "); |
| 896 | try ttyconf.setColor(stderr, .red); | 901 | try ttyconf.setColor(stderr, .red); |
| 897 | try stderr.deprecatedWriter().print("{d} failed", .{ | 902 | try stderr.print("{d} failed", .{ |
| 898 | s.test_results.fail_count, | 903 | s.test_results.fail_count, |
| 899 | }); | 904 | }); |
| 900 | try ttyconf.setColor(stderr, .reset); | 905 | try ttyconf.setColor(stderr, .reset); |
| ... | @@ -902,7 +907,7 @@ fn printStepFailure( | ... | @@ -902,7 +907,7 @@ fn printStepFailure( |
| 902 | if (s.test_results.skip_count > 0) { | 907 | if (s.test_results.skip_count > 0) { |
| 903 | try stderr.writeAll(", "); | 908 | try stderr.writeAll(", "); |
| 904 | try ttyconf.setColor(stderr, .yellow); | 909 | try ttyconf.setColor(stderr, .yellow); |
| 905 | try stderr.deprecatedWriter().print("{d} skipped", .{ | 910 | try stderr.print("{d} skipped", .{ |
| 906 | s.test_results.skip_count, | 911 | s.test_results.skip_count, |
| 907 | }); | 912 | }); |
| 908 | try ttyconf.setColor(stderr, .reset); | 913 | try ttyconf.setColor(stderr, .reset); |
| ... | @@ -910,7 +915,7 @@ fn printStepFailure( | ... | @@ -910,7 +915,7 @@ fn printStepFailure( |
| 910 | if (s.test_results.leak_count > 0) { | 915 | if (s.test_results.leak_count > 0) { |
| 911 | try stderr.writeAll(", "); | 916 | try stderr.writeAll(", "); |
| 912 | try ttyconf.setColor(stderr, .red); | 917 | try ttyconf.setColor(stderr, .red); |
| 913 | try stderr.deprecatedWriter().print("{d} leaked", .{ | 918 | try stderr.print("{d} leaked", .{ |
| 914 | s.test_results.leak_count, | 919 | s.test_results.leak_count, |
| 915 | }); | 920 | }); |
| 916 | try ttyconf.setColor(stderr, .reset); | 921 | try ttyconf.setColor(stderr, .reset); |
| ... | @@ -932,7 +937,7 @@ fn printTreeStep( | ... | @@ -932,7 +937,7 @@ fn printTreeStep( |
| 932 | b: *std.Build, | 937 | b: *std.Build, |
| 933 | s: *Step, | 938 | s: *Step, |
| 934 | run: *const Run, | 939 | run: *const Run, |
| 935 | stderr: File, | 940 | stderr: *Writer, |
| 936 | ttyconf: std.io.tty.Config, | 941 | ttyconf: std.io.tty.Config, |
| 937 | parent_node: *PrintNode, | 942 | parent_node: *PrintNode, |
| 938 | step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void), | 943 | step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void), |
| ... | @@ -992,7 +997,7 @@ fn printTreeStep( | ... | @@ -992,7 +997,7 @@ fn printTreeStep( |
| 992 | if (s.dependencies.items.len == 0) { | 997 | if (s.dependencies.items.len == 0) { |
| 993 | try stderr.writeAll(" (reused)\n"); | 998 | try stderr.writeAll(" (reused)\n"); |
| 994 | } else { | 999 | } else { |
| 995 | try stderr.deprecatedWriter().print(" (+{d} more reused dependencies)\n", .{ | 1000 | try stderr.print(" (+{d} more reused dependencies)\n", .{ |
| 996 | s.dependencies.items.len, | 1001 | s.dependencies.items.len, |
| 997 | }); | 1002 | }); |
| 998 | } | 1003 | } |
| ... | @@ -1129,11 +1134,11 @@ fn workerMakeOneStep( | ... | @@ -1129,11 +1134,11 @@ fn workerMakeOneStep( |
| 1129 | const show_stderr = s.result_stderr.len > 0; | 1134 | const show_stderr = s.result_stderr.len > 0; |
| 1130 | 1135 | ||
| 1131 | if (show_error_msgs or show_compile_errors or show_stderr) { | 1136 | if (show_error_msgs or show_compile_errors or show_stderr) { |
| 1132 | std.debug.lockStdErr(); | 1137 | const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation); |
| 1133 | defer std.debug.unlockStdErr(); | 1138 | defer std.debug.unlockStderrWriter(); |
| 1134 | 1139 | ||
| 1135 | const gpa = b.allocator; | 1140 | const gpa = b.allocator; |
| 1136 | printErrorMessages(gpa, s, .{ .ttyconf = run.ttyconf }, run.stderr, run.prominent_compile_errors) catch {}; | 1141 | printErrorMessages(gpa, s, .{ .ttyconf = run.ttyconf }, bw, run.prominent_compile_errors) catch {}; |
| 1137 | } | 1142 | } |
| 1138 | 1143 | ||
| 1139 | handle_result: { | 1144 | handle_result: { |
| ... | @@ -1190,7 +1195,7 @@ pub fn printErrorMessages( | ... | @@ -1190,7 +1195,7 @@ pub fn printErrorMessages( |
| 1190 | gpa: Allocator, | 1195 | gpa: Allocator, |
| 1191 | failing_step: *Step, | 1196 | failing_step: *Step, |
| 1192 | options: std.zig.ErrorBundle.RenderOptions, | 1197 | options: std.zig.ErrorBundle.RenderOptions, |
| 1193 | stderr: File, | 1198 | stderr: *Writer, |
| 1194 | prominent_compile_errors: bool, | 1199 | prominent_compile_errors: bool, |
| 1195 | ) !void { | 1200 | ) !void { |
| 1196 | // Provide context for where these error messages are coming from by | 1201 | // Provide context for where these error messages are coming from by |
| ... | @@ -1209,7 +1214,7 @@ pub fn printErrorMessages( | ... | @@ -1209,7 +1214,7 @@ pub fn printErrorMessages( |
| 1209 | var indent: usize = 0; | 1214 | var indent: usize = 0; |
| 1210 | while (step_stack.pop()) |s| : (indent += 1) { | 1215 | while (step_stack.pop()) |s| : (indent += 1) { |
| 1211 | if (indent > 0) { | 1216 | if (indent > 0) { |
| 1212 | try stderr.deprecatedWriter().writeByteNTimes(' ', (indent - 1) * 3); | 1217 | try stderr.splatByteAll(' ', (indent - 1) * 3); |
| 1213 | try printChildNodePrefix(stderr, ttyconf); | 1218 | try printChildNodePrefix(stderr, ttyconf); |
| 1214 | } | 1219 | } |
| 1215 | 1220 | ||
| ... | @@ -1231,7 +1236,7 @@ pub fn printErrorMessages( | ... | @@ -1231,7 +1236,7 @@ pub fn printErrorMessages( |
| 1231 | } | 1236 | } |
| 1232 | 1237 | ||
| 1233 | if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) { | 1238 | if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) { |
| 1234 | try failing_step.result_error_bundle.renderToWriter(options, stderr.deprecatedWriter()); | 1239 | try failing_step.result_error_bundle.renderToWriter(options, stderr); |
| 1235 | } | 1240 | } |
| 1236 | 1241 | ||
| 1237 | for (failing_step.result_error_msgs.items) |msg| { | 1242 | for (failing_step.result_error_msgs.items) |msg| { |
| ... | @@ -1243,27 +1248,27 @@ pub fn printErrorMessages( | ... | @@ -1243,27 +1248,27 @@ pub fn printErrorMessages( |
| 1243 | } | 1248 | } |
| 1244 | } | 1249 | } |
| 1245 | 1250 | ||
| 1246 | fn steps(builder: *std.Build, out_stream: anytype) !void { | 1251 | fn printSteps(builder: *std.Build, w: *Writer) !void { |
| 1247 | const allocator = builder.allocator; | 1252 | const allocator = builder.allocator; |
| 1248 | for (builder.top_level_steps.values()) |top_level_step| { | 1253 | for (builder.top_level_steps.values()) |top_level_step| { |
| 1249 | const name = if (&top_level_step.step == builder.default_step) | 1254 | const name = if (&top_level_step.step == builder.default_step) |
| 1250 | try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name}) | 1255 | try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name}) |
| 1251 | else | 1256 | else |
| 1252 | top_level_step.step.name; | 1257 | top_level_step.step.name; |
| 1253 | try out_stream.print(" {s:<28} {s}\n", .{ name, top_level_step.description }); | 1258 | try w.print(" {s:<28} {s}\n", .{ name, top_level_step.description }); |
| 1254 | } | 1259 | } |
| 1255 | } | 1260 | } |
| 1256 | 1261 | ||
| 1257 | fn usage(b: *std.Build, out_stream: anytype) !void { | 1262 | fn printUsage(b: *std.Build, w: *Writer) !void { |
| 1258 | try out_stream.print( | 1263 | try w.print( |
| 1259 | \\Usage: {s} build [steps] [options] | 1264 | \\Usage: {s} build [steps] [options] |
| 1260 | \\ | 1265 | \\ |
| 1261 | \\Steps: | 1266 | \\Steps: |
| 1262 | \\ | 1267 | \\ |
| 1263 | , .{b.graph.zig_exe}); | 1268 | , .{b.graph.zig_exe}); |
| 1264 | try steps(b, out_stream); | 1269 | try printSteps(b, w); |
| 1265 | 1270 | ||
| 1266 | try out_stream.writeAll( | 1271 | try w.writeAll( |
| 1267 | \\ | 1272 | \\ |
| 1268 | \\General Options: | 1273 | \\General Options: |
| 1269 | \\ -p, --prefix [path] Where to install files (default: zig-out) | 1274 | \\ -p, --prefix [path] Where to install files (default: zig-out) |
| ... | @@ -1319,25 +1324,25 @@ fn usage(b: *std.Build, out_stream: anytype) !void { | ... | @@ -1319,25 +1324,25 @@ fn usage(b: *std.Build, out_stream: anytype) !void { |
| 1319 | 1324 | ||
| 1320 | const arena = b.allocator; | 1325 | const arena = b.allocator; |
| 1321 | if (b.available_options_list.items.len == 0) { | 1326 | if (b.available_options_list.items.len == 0) { |
| 1322 | try out_stream.print(" (none)\n", .{}); | 1327 | try w.print(" (none)\n", .{}); |
| 1323 | } else { | 1328 | } else { |
| 1324 | for (b.available_options_list.items) |option| { | 1329 | for (b.available_options_list.items) |option| { |
| 1325 | const name = try fmt.allocPrint(arena, " -D{s}=[{s}]", .{ | 1330 | const name = try fmt.allocPrint(arena, " -D{s}=[{s}]", .{ |
| 1326 | option.name, | 1331 | option.name, |
| 1327 | @tagName(option.type_id), | 1332 | @tagName(option.type_id), |
| 1328 | }); | 1333 | }); |
| 1329 | try out_stream.print("{s:<30} {s}\n", .{ name, option.description }); | 1334 | try w.print("{s:<30} {s}\n", .{ name, option.description }); |
| 1330 | if (option.enum_options) |enum_options| { | 1335 | if (option.enum_options) |enum_options| { |
| 1331 | const padding = " " ** 33; | 1336 | const padding = " " ** 33; |
| 1332 | try out_stream.writeAll(padding ++ "Supported Values:\n"); | 1337 | try w.writeAll(padding ++ "Supported Values:\n"); |
| 1333 | for (enum_options) |enum_option| { | 1338 | for (enum_options) |enum_option| { |
| 1334 | try out_stream.print(padding ++ " {s}\n", .{enum_option}); | 1339 | try w.print(padding ++ " {s}\n", .{enum_option}); |
| 1335 | } | 1340 | } |
| 1336 | } | 1341 | } |
| 1337 | } | 1342 | } |
| 1338 | } | 1343 | } |
| 1339 | 1344 | ||
| 1340 | try out_stream.writeAll( | 1345 | try w.writeAll( |
| 1341 | \\ | 1346 | \\ |
| 1342 | \\System Integration Options: | 1347 | \\System Integration Options: |
| 1343 | \\ --search-prefix [path] Add a path to look for binaries, libraries, headers | 1348 | \\ --search-prefix [path] Add a path to look for binaries, libraries, headers |
| ... | @@ -1352,7 +1357,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void { | ... | @@ -1352,7 +1357,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void { |
| 1352 | \\ | 1357 | \\ |
| 1353 | ); | 1358 | ); |
| 1354 | if (b.graph.system_library_options.entries.len == 0) { | 1359 | if (b.graph.system_library_options.entries.len == 0) { |
| 1355 | try out_stream.writeAll(" (none) -\n"); | 1360 | try w.writeAll(" (none) -\n"); |
| 1356 | } else { | 1361 | } else { |
| 1357 | for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| { | 1362 | for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| { |
| 1358 | const status = switch (v) { | 1363 | const status = switch (v) { |
| ... | @@ -1360,11 +1365,11 @@ fn usage(b: *std.Build, out_stream: anytype) !void { | ... | @@ -1360,11 +1365,11 @@ fn usage(b: *std.Build, out_stream: anytype) !void { |
| 1360 | .declared_disabled => "no", | 1365 | .declared_disabled => "no", |
| 1361 | .user_enabled, .user_disabled => unreachable, // already emitted error | 1366 | .user_enabled, .user_disabled => unreachable, // already emitted error |
| 1362 | }; | 1367 | }; |
| 1363 | try out_stream.print(" {s:<43} {s}\n", .{ k, status }); | 1368 | try w.print(" {s:<43} {s}\n", .{ k, status }); |
| 1364 | } | 1369 | } |
| 1365 | } | 1370 | } |
| 1366 | 1371 | ||
| 1367 | try out_stream.writeAll( | 1372 | try w.writeAll( |
| 1368 | \\ | 1373 | \\ |
| 1369 | \\Advanced Options: | 1374 | \\Advanced Options: |
| 1370 | \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error | 1375 | \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error |
| ... | @@ -1544,3 +1549,11 @@ fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void { | ... | @@ -1544,3 +1549,11 @@ fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void { |
| 1544 | }; | 1549 | }; |
| 1545 | } | 1550 | } |
| 1546 | } | 1551 | } |
| 1552 | |||
| 1553 | var stdio_buffer_allocation: [256]u8 = undefined; | ||
| 1554 | var stdout_writer_allocation: std.fs.File.Writer = undefined; | ||
| 1555 | |||
| 1556 | fn initStdoutWriter() *Writer { | ||
| 1557 | stdout_writer_allocation = std.fs.File.stdout().writerStreaming(&stdio_buffer_allocation); | ||
| 1558 | return &stdout_writer_allocation.interface; | ||
| 1559 | } |
lib/std/Build.zig+31-41| ... | @@ -284,7 +284,7 @@ pub fn create( | ... | @@ -284,7 +284,7 @@ pub fn create( |
| 284 | .h_dir = undefined, | 284 | .h_dir = undefined, |
| 285 | .dest_dir = graph.env_map.get("DESTDIR"), | 285 | .dest_dir = graph.env_map.get("DESTDIR"), |
| 286 | .install_tls = .{ | 286 | .install_tls = .{ |
| 287 | .step = Step.init(.{ | 287 | .step = .init(.{ |
| 288 | .id = TopLevelStep.base_id, | 288 | .id = TopLevelStep.base_id, |
| 289 | .name = "install", | 289 | .name = "install", |
| 290 | .owner = b, | 290 | .owner = b, |
| ... | @@ -292,7 +292,7 @@ pub fn create( | ... | @@ -292,7 +292,7 @@ pub fn create( |
| 292 | .description = "Copy build artifacts to prefix path", | 292 | .description = "Copy build artifacts to prefix path", |
| 293 | }, | 293 | }, |
| 294 | .uninstall_tls = .{ | 294 | .uninstall_tls = .{ |
| 295 | .step = Step.init(.{ | 295 | .step = .init(.{ |
| 296 | .id = TopLevelStep.base_id, | 296 | .id = TopLevelStep.base_id, |
| 297 | .name = "uninstall", | 297 | .name = "uninstall", |
| 298 | .owner = b, | 298 | .owner = b, |
| ... | @@ -342,7 +342,7 @@ fn createChildOnly( | ... | @@ -342,7 +342,7 @@ fn createChildOnly( |
| 342 | .graph = parent.graph, | 342 | .graph = parent.graph, |
| 343 | .allocator = allocator, | 343 | .allocator = allocator, |
| 344 | .install_tls = .{ | 344 | .install_tls = .{ |
| 345 | .step = Step.init(.{ | 345 | .step = .init(.{ |
| 346 | .id = TopLevelStep.base_id, | 346 | .id = TopLevelStep.base_id, |
| 347 | .name = "install", | 347 | .name = "install", |
| 348 | .owner = child, | 348 | .owner = child, |
| ... | @@ -350,7 +350,7 @@ fn createChildOnly( | ... | @@ -350,7 +350,7 @@ fn createChildOnly( |
| 350 | .description = "Copy build artifacts to prefix path", | 350 | .description = "Copy build artifacts to prefix path", |
| 351 | }, | 351 | }, |
| 352 | .uninstall_tls = .{ | 352 | .uninstall_tls = .{ |
| 353 | .step = Step.init(.{ | 353 | .step = .init(.{ |
| 354 | .id = TopLevelStep.base_id, | 354 | .id = TopLevelStep.base_id, |
| 355 | .name = "uninstall", | 355 | .name = "uninstall", |
| 356 | .owner = child, | 356 | .owner = child, |
| ... | @@ -1525,7 +1525,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw | ... | @@ -1525,7 +1525,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw |
| 1525 | pub fn step(b: *Build, name: []const u8, description: []const u8) *Step { | 1525 | pub fn step(b: *Build, name: []const u8, description: []const u8) *Step { |
| 1526 | const step_info = b.allocator.create(TopLevelStep) catch @panic("OOM"); | 1526 | const step_info = b.allocator.create(TopLevelStep) catch @panic("OOM"); |
| 1527 | step_info.* = .{ | 1527 | step_info.* = .{ |
| 1528 | .step = Step.init(.{ | 1528 | .step = .init(.{ |
| 1529 | .id = TopLevelStep.base_id, | 1529 | .id = TopLevelStep.base_id, |
| 1530 | .name = name, | 1530 | .name = name, |
| 1531 | .owner = b, | 1531 | .owner = b, |
| ... | @@ -1824,13 +1824,13 @@ pub fn validateUserInputDidItFail(b: *Build) bool { | ... | @@ -1824,13 +1824,13 @@ pub fn validateUserInputDidItFail(b: *Build) bool { |
| 1824 | return b.invalid_user_input; | 1824 | return b.invalid_user_input; |
| 1825 | } | 1825 | } |
| 1826 | 1826 | ||
| 1827 | fn allocPrintCmd(ally: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) error{OutOfMemory}![]u8 { | 1827 | fn allocPrintCmd(gpa: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) error{OutOfMemory}![]u8 { |
| 1828 | var buf = ArrayList(u8).init(ally); | 1828 | var buf: std.ArrayListUnmanaged(u8) = .empty; |
| 1829 | if (opt_cwd) |cwd| try buf.writer().print("cd {s} && ", .{cwd}); | 1829 | if (opt_cwd) |cwd| try buf.print(gpa, "cd {s} && ", .{cwd}); |
| 1830 | for (argv) |arg| { | 1830 | for (argv) |arg| { |
| 1831 | try buf.writer().print("{s} ", .{arg}); | 1831 | try buf.print(gpa, "{s} ", .{arg}); |
| 1832 | } | 1832 | } |
| 1833 | return buf.toOwnedSlice(); | 1833 | return buf.toOwnedSlice(gpa); |
| 1834 | } | 1834 | } |
| 1835 | 1835 | ||
| 1836 | fn printCmd(ally: Allocator, cwd: ?[]const u8, argv: []const []const u8) void { | 1836 | fn printCmd(ally: Allocator, cwd: ?[]const u8, argv: []const []const u8) void { |
| ... | @@ -2466,10 +2466,9 @@ pub const GeneratedFile = struct { | ... | @@ -2466,10 +2466,9 @@ pub const GeneratedFile = struct { |
| 2466 | 2466 | ||
| 2467 | pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 { | 2467 | pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 { |
| 2468 | return gen.path orelse { | 2468 | return gen.path orelse { |
| 2469 | std.debug.lockStdErr(); | 2469 | const w = debug.lockStderrWriter(&.{}); |
| 2470 | const stderr = std.fs.File.stderr(); | 2470 | dumpBadGetPathHelp(gen.step, w, .detect(.stderr()), src_builder, asking_step) catch {}; |
| 2471 | dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {}; | 2471 | debug.unlockStderrWriter(); |
| 2472 | std.debug.unlockStdErr(); | ||
| 2473 | @panic("misconfigured build script"); | 2472 | @panic("misconfigured build script"); |
| 2474 | }; | 2473 | }; |
| 2475 | } | 2474 | } |
| ... | @@ -2676,10 +2675,9 @@ pub const LazyPath = union(enum) { | ... | @@ -2676,10 +2675,9 @@ pub const LazyPath = union(enum) { |
| 2676 | var file_path: Cache.Path = .{ | 2675 | var file_path: Cache.Path = .{ |
| 2677 | .root_dir = Cache.Directory.cwd(), | 2676 | .root_dir = Cache.Directory.cwd(), |
| 2678 | .sub_path = gen.file.path orelse { | 2677 | .sub_path = gen.file.path orelse { |
| 2679 | std.debug.lockStdErr(); | 2678 | const w = debug.lockStderrWriter(&.{}); |
| 2680 | const stderr: fs.File = .stderr(); | 2679 | dumpBadGetPathHelp(gen.file.step, w, .detect(.stderr()), src_builder, asking_step) catch {}; |
| 2681 | dumpBadGetPathHelp(gen.file.step, stderr, src_builder, asking_step) catch {}; | 2680 | debug.unlockStderrWriter(); |
| 2682 | std.debug.unlockStdErr(); | ||
| 2683 | @panic("misconfigured build script"); | 2681 | @panic("misconfigured build script"); |
| 2684 | }, | 2682 | }, |
| 2685 | }; | 2683 | }; |
| ... | @@ -2766,44 +2764,42 @@ fn dumpBadDirnameHelp( | ... | @@ -2766,44 +2764,42 @@ fn dumpBadDirnameHelp( |
| 2766 | comptime msg: []const u8, | 2764 | comptime msg: []const u8, |
| 2767 | args: anytype, | 2765 | args: anytype, |
| 2768 | ) anyerror!void { | 2766 | ) anyerror!void { |
| 2769 | debug.lockStdErr(); | 2767 | const w = debug.lockStderrWriter(&.{}); |
| 2770 | defer debug.unlockStdErr(); | 2768 | defer debug.unlockStderrWriter(); |
| 2771 | 2769 | ||
| 2772 | const stderr: fs.File = .stderr(); | ||
| 2773 | const w = stderr.deprecatedWriter(); | ||
| 2774 | try w.print(msg, args); | 2770 | try w.print(msg, args); |
| 2775 | 2771 | ||
| 2776 | const tty_config = std.io.tty.detectConfig(stderr); | 2772 | const tty_config = std.io.tty.detectConfig(.stderr()); |
| 2777 | 2773 | ||
| 2778 | if (fail_step) |s| { | 2774 | if (fail_step) |s| { |
| 2779 | tty_config.setColor(w, .red) catch {}; | 2775 | tty_config.setColor(w, .red) catch {}; |
| 2780 | try stderr.writeAll(" The step was created by this stack trace:\n"); | 2776 | try w.writeAll(" The step was created by this stack trace:\n"); |
| 2781 | tty_config.setColor(w, .reset) catch {}; | 2777 | tty_config.setColor(w, .reset) catch {}; |
| 2782 | 2778 | ||
| 2783 | s.dump(stderr); | 2779 | s.dump(w, tty_config); |
| 2784 | } | 2780 | } |
| 2785 | 2781 | ||
| 2786 | if (asking_step) |as| { | 2782 | if (asking_step) |as| { |
| 2787 | tty_config.setColor(w, .red) catch {}; | 2783 | tty_config.setColor(w, .red) catch {}; |
| 2788 | try stderr.deprecatedWriter().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name}); | 2784 | try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name}); |
| 2789 | tty_config.setColor(w, .reset) catch {}; | 2785 | tty_config.setColor(w, .reset) catch {}; |
| 2790 | 2786 | ||
| 2791 | as.dump(stderr); | 2787 | as.dump(w, tty_config); |
| 2792 | } | 2788 | } |
| 2793 | 2789 | ||
| 2794 | tty_config.setColor(w, .red) catch {}; | 2790 | tty_config.setColor(w, .red) catch {}; |
| 2795 | try stderr.writeAll(" Hope that helps. Proceeding to panic.\n"); | 2791 | try w.writeAll(" Hope that helps. Proceeding to panic.\n"); |
| 2796 | tty_config.setColor(w, .reset) catch {}; | 2792 | tty_config.setColor(w, .reset) catch {}; |
| 2797 | } | 2793 | } |
| 2798 | 2794 | ||
| 2799 | /// In this function the stderr mutex has already been locked. | 2795 | /// In this function the stderr mutex has already been locked. |
| 2800 | pub fn dumpBadGetPathHelp( | 2796 | pub fn dumpBadGetPathHelp( |
| 2801 | s: *Step, | 2797 | s: *Step, |
| 2802 | stderr: fs.File, | 2798 | w: *std.io.Writer, |
| 2799 | tty_config: std.io.tty.Config, | ||
| 2803 | src_builder: *Build, | 2800 | src_builder: *Build, |
| 2804 | asking_step: ?*Step, | 2801 | asking_step: ?*Step, |
| 2805 | ) anyerror!void { | 2802 | ) anyerror!void { |
| 2806 | const w = stderr.deprecatedWriter(); | ||
| 2807 | try w.print( | 2803 | try w.print( |
| 2808 | \\getPath() was called on a GeneratedFile that wasn't built yet. | 2804 | \\getPath() was called on a GeneratedFile that wasn't built yet. |
| 2809 | \\ source package path: {s} | 2805 | \\ source package path: {s} |
| ... | @@ -2814,21 +2810,20 @@ pub fn dumpBadGetPathHelp( | ... | @@ -2814,21 +2810,20 @@ pub fn dumpBadGetPathHelp( |
| 2814 | s.name, | 2810 | s.name, |
| 2815 | }); | 2811 | }); |
| 2816 | 2812 | ||
| 2817 | const tty_config = std.io.tty.detectConfig(stderr); | ||
| 2818 | tty_config.setColor(w, .red) catch {}; | 2813 | tty_config.setColor(w, .red) catch {}; |
| 2819 | try stderr.writeAll(" The step was created by this stack trace:\n"); | 2814 | try w.writeAll(" The step was created by this stack trace:\n"); |
| 2820 | tty_config.setColor(w, .reset) catch {}; | 2815 | tty_config.setColor(w, .reset) catch {}; |
| 2821 | 2816 | ||
| 2822 | s.dump(stderr); | 2817 | s.dump(w, tty_config); |
| 2823 | if (asking_step) |as| { | 2818 | if (asking_step) |as| { |
| 2824 | tty_config.setColor(w, .red) catch {}; | 2819 | tty_config.setColor(w, .red) catch {}; |
| 2825 | try stderr.deprecatedWriter().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name}); | 2820 | try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name}); |
| 2826 | tty_config.setColor(w, .reset) catch {}; | 2821 | tty_config.setColor(w, .reset) catch {}; |
| 2827 | 2822 | ||
| 2828 | as.dump(stderr); | 2823 | as.dump(w, tty_config); |
| 2829 | } | 2824 | } |
| 2830 | tty_config.setColor(w, .red) catch {}; | 2825 | tty_config.setColor(w, .red) catch {}; |
| 2831 | try stderr.writeAll(" Hope that helps. Proceeding to panic.\n"); | 2826 | try w.writeAll(" Hope that helps. Proceeding to panic.\n"); |
| 2832 | tty_config.setColor(w, .reset) catch {}; | 2827 | tty_config.setColor(w, .reset) catch {}; |
| 2833 | } | 2828 | } |
| 2834 | 2829 | ||
| ... | @@ -2866,11 +2861,6 @@ pub fn makeTempPath(b: *Build) []const u8 { | ... | @@ -2866,11 +2861,6 @@ pub fn makeTempPath(b: *Build) []const u8 { |
| 2866 | return result_path; | 2861 | return result_path; |
| 2867 | } | 2862 | } |
| 2868 | 2863 | ||
| 2869 | /// Deprecated; use `std.fmt.hex` instead. | ||
| 2870 | pub fn hex64(x: u64) [16]u8 { | ||
| 2871 | return std.fmt.hex(x); | ||
| 2872 | } | ||
| 2873 | |||
| 2874 | /// A pair of target query and fully resolved target. | 2864 | /// A pair of target query and fully resolved target. |
| 2875 | /// This type is generally required by build system API that need to be given a | 2865 | /// This type is generally required by build system API that need to be given a |
| 2876 | /// target. The query is kept because the Zig toolchain needs to know which parts | 2866 | /// target. The query is kept because the Zig toolchain needs to know which parts |
lib/std/Build/Fuzz.zig+8-8| ... | @@ -112,7 +112,6 @@ fn rebuildTestsWorkerRun(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog | ... | @@ -112,7 +112,6 @@ fn rebuildTestsWorkerRun(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog |
| 112 | 112 | ||
| 113 | fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog_node: std.Progress.Node) !void { | 113 | fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog_node: std.Progress.Node) !void { |
| 114 | const gpa = run.step.owner.allocator; | 114 | const gpa = run.step.owner.allocator; |
| 115 | const stderr = std.fs.File.stderr(); | ||
| 116 | 115 | ||
| 117 | const compile = run.producer.?; | 116 | const compile = run.producer.?; |
| 118 | const prog_node = parent_prog_node.start(compile.step.name, 0); | 117 | const prog_node = parent_prog_node.start(compile.step.name, 0); |
| ... | @@ -125,9 +124,10 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, par | ... | @@ -125,9 +124,10 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, par |
| 125 | const show_stderr = compile.step.result_stderr.len > 0; | 124 | const show_stderr = compile.step.result_stderr.len > 0; |
| 126 | 125 | ||
| 127 | if (show_error_msgs or show_compile_errors or show_stderr) { | 126 | if (show_error_msgs or show_compile_errors or show_stderr) { |
| 128 | std.debug.lockStdErr(); | 127 | var buf: [256]u8 = undefined; |
| 129 | defer std.debug.unlockStdErr(); | 128 | const w = std.debug.lockStderrWriter(&buf); |
| 130 | build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, stderr, false) catch {}; | 129 | defer std.debug.unlockStderrWriter(); |
| 130 | build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, w, false) catch {}; | ||
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | const rebuilt_bin_path = result catch |err| switch (err) { | 133 | const rebuilt_bin_path = result catch |err| switch (err) { |
| ... | @@ -152,10 +152,10 @@ fn fuzzWorkerRun( | ... | @@ -152,10 +152,10 @@ fn fuzzWorkerRun( |
| 152 | 152 | ||
| 153 | run.rerunInFuzzMode(web_server, unit_test_index, prog_node) catch |err| switch (err) { | 153 | run.rerunInFuzzMode(web_server, unit_test_index, prog_node) catch |err| switch (err) { |
| 154 | error.MakeFailed => { | 154 | error.MakeFailed => { |
| 155 | const stderr = std.fs.File.stderr(); | 155 | var buf: [256]u8 = undefined; |
| 156 | std.debug.lockStdErr(); | 156 | const w = std.debug.lockStderrWriter(&buf); |
| 157 | defer std.debug.unlockStdErr(); | 157 | defer std.debug.unlockStderrWriter(); |
| 158 | build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = ttyconf }, stderr, false) catch {}; | 158 | build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = ttyconf }, w, false) catch {}; |
| 159 | return; | 159 | return; |
| 160 | }, | 160 | }, |
| 161 | else => { | 161 | else => { |
lib/std/Build/Step.zig+1-4| ... | @@ -286,10 +286,7 @@ pub fn cast(step: *Step, comptime T: type) ?*T { | ... | @@ -286,10 +286,7 @@ pub fn cast(step: *Step, comptime T: type) ?*T { |
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | /// For debugging purposes, prints identifying information about this Step. | 288 | /// For debugging purposes, prints identifying information about this Step. |
| 289 | pub fn dump(step: *Step, file: std.fs.File) void { | 289 | pub fn dump(step: *Step, w: *std.io.Writer, tty_config: std.io.tty.Config) void { |
| 290 | var fw = file.writer(&.{}); | ||
| 291 | const w = &fw.interface; | ||
| 292 | const tty_config = std.io.tty.detectConfig(file); | ||
| 293 | const debug_info = std.debug.getSelfDebugInfo() catch |err| { | 290 | const debug_info = std.debug.getSelfDebugInfo() catch |err| { |
| 294 | w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{ | 291 | w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{ |
| 295 | @errorName(err), | 292 | @errorName(err), |
lib/std/Build/Step/Compile.zig+30-31| ... | @@ -409,7 +409,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { | ... | @@ -409,7 +409,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { |
| 409 | .linkage = options.linkage, | 409 | .linkage = options.linkage, |
| 410 | .kind = options.kind, | 410 | .kind = options.kind, |
| 411 | .name = name, | 411 | .name = name, |
| 412 | .step = Step.init(.{ | 412 | .step = .init(.{ |
| 413 | .id = base_id, | 413 | .id = base_id, |
| 414 | .name = step_name, | 414 | .name = step_name, |
| 415 | .owner = owner, | 415 | .owner = owner, |
| ... | @@ -1017,20 +1017,16 @@ fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking | ... | @@ -1017,20 +1017,16 @@ fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking |
| 1017 | const maybe_path: ?*GeneratedFile = @field(compile, tag_name); | 1017 | const maybe_path: ?*GeneratedFile = @field(compile, tag_name); |
| 1018 | 1018 | ||
| 1019 | const generated_file = maybe_path orelse { | 1019 | const generated_file = maybe_path orelse { |
| 1020 | std.debug.lockStdErr(); | 1020 | const w = std.debug.lockStderrWriter(&.{}); |
| 1021 | const stderr: fs.File = .stderr(); | 1021 | std.Build.dumpBadGetPathHelp(&compile.step, w, .detect(.stderr()), compile.step.owner, asking_step) catch {}; |
| 1022 | 1022 | std.debug.unlockStderrWriter(); | |
| 1023 | std.Build.dumpBadGetPathHelp(&compile.step, stderr, compile.step.owner, asking_step) catch {}; | ||
| 1024 | |||
| 1025 | @panic("missing emit option for " ++ tag_name); | 1023 | @panic("missing emit option for " ++ tag_name); |
| 1026 | }; | 1024 | }; |
| 1027 | 1025 | ||
| 1028 | const path = generated_file.path orelse { | 1026 | const path = generated_file.path orelse { |
| 1029 | std.debug.lockStdErr(); | 1027 | const w = std.debug.lockStderrWriter(&.{}); |
| 1030 | const stderr: fs.File = .stderr(); | 1028 | std.Build.dumpBadGetPathHelp(&compile.step, w, .detect(.stderr()), compile.step.owner, asking_step) catch {}; |
| 1031 | 1029 | std.debug.unlockStderrWriter(); | |
| 1032 | std.Build.dumpBadGetPathHelp(&compile.step, stderr, compile.step.owner, asking_step) catch {}; | ||
| 1033 | |||
| 1034 | @panic(tag_name ++ " is null. Is there a missing step dependency?"); | 1030 | @panic(tag_name ++ " is null. Is there a missing step dependency?"); |
| 1035 | }; | 1031 | }; |
| 1036 | 1032 | ||
| ... | @@ -1768,12 +1764,12 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -1768,12 +1764,12 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 1768 | for (arg, 0..) |c, arg_idx| { | 1764 | for (arg, 0..) |c, arg_idx| { |
| 1769 | if (c == '\\' or c == '"') { | 1765 | if (c == '\\' or c == '"') { |
| 1770 | // Slow path for arguments that need to be escaped. We'll need to allocate and copy | 1766 | // Slow path for arguments that need to be escaped. We'll need to allocate and copy |
| 1771 | var escaped = try ArrayList(u8).initCapacity(arena, arg.len + 1); | 1767 | var escaped: std.ArrayListUnmanaged(u8) = .empty; |
| 1772 | const writer = escaped.writer(); | 1768 | try escaped.ensureTotalCapacityPrecise(arena, arg.len + 1); |
| 1773 | try writer.writeAll(arg[0..arg_idx]); | 1769 | try escaped.appendSlice(arena, arg[0..arg_idx]); |
| 1774 | for (arg[arg_idx..]) |to_escape| { | 1770 | for (arg[arg_idx..]) |to_escape| { |
| 1775 | if (to_escape == '\\' or to_escape == '"') try writer.writeByte('\\'); | 1771 | if (to_escape == '\\' or to_escape == '"') try escaped.append(arena, '\\'); |
| 1776 | try writer.writeByte(to_escape); | 1772 | try escaped.append(arena, to_escape); |
| 1777 | } | 1773 | } |
| 1778 | escaped_args.appendAssumeCapacity(escaped.items); | 1774 | escaped_args.appendAssumeCapacity(escaped.items); |
| 1779 | continue :arg_blk; | 1775 | continue :arg_blk; |
| ... | @@ -1963,20 +1959,23 @@ fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool) | ... | @@ -1963,20 +1959,23 @@ fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool) |
| 1963 | fn checkCompileErrors(compile: *Compile) !void { | 1959 | fn checkCompileErrors(compile: *Compile) !void { |
| 1964 | // Clear this field so that it does not get printed by the build runner. | 1960 | // Clear this field so that it does not get printed by the build runner. |
| 1965 | const actual_eb = compile.step.result_error_bundle; | 1961 | const actual_eb = compile.step.result_error_bundle; |
| 1966 | compile.step.result_error_bundle = std.zig.ErrorBundle.empty; | 1962 | compile.step.result_error_bundle = .empty; |
| 1967 | 1963 | ||
| 1968 | const arena = compile.step.owner.allocator; | 1964 | const arena = compile.step.owner.allocator; |
| 1969 | 1965 | ||
| 1970 | var actual_errors_list = std.ArrayList(u8).init(arena); | 1966 | const actual_errors = ae: { |
| 1971 | try actual_eb.renderToWriter(.{ | 1967 | var aw: std.io.Writer.Allocating = .init(arena); |
| 1972 | .ttyconf = .no_color, | 1968 | defer aw.deinit(); |
| 1973 | .include_reference_trace = false, | 1969 | try actual_eb.renderToWriter(.{ |
| 1974 | .include_source_line = false, | 1970 | .ttyconf = .no_color, |
| 1975 | }, actual_errors_list.writer()); | 1971 | .include_reference_trace = false, |
| 1976 | const actual_errors = try actual_errors_list.toOwnedSlice(); | 1972 | .include_source_line = false, |
| 1973 | }, &aw.writer); | ||
| 1974 | break :ae try aw.toOwnedSlice(); | ||
| 1975 | }; | ||
| 1977 | 1976 | ||
| 1978 | // Render the expected lines into a string that we can compare verbatim. | 1977 | // Render the expected lines into a string that we can compare verbatim. |
| 1979 | var expected_generated = std.ArrayList(u8).init(arena); | 1978 | var expected_generated: std.ArrayListUnmanaged(u8) = .empty; |
| 1980 | const expect_errors = compile.expect_errors.?; | 1979 | const expect_errors = compile.expect_errors.?; |
| 1981 | 1980 | ||
| 1982 | var actual_line_it = mem.splitScalar(u8, actual_errors, '\n'); | 1981 | var actual_line_it = mem.splitScalar(u8, actual_errors, '\n'); |
| ... | @@ -2035,17 +2034,17 @@ fn checkCompileErrors(compile: *Compile) !void { | ... | @@ -2035,17 +2034,17 @@ fn checkCompileErrors(compile: *Compile) !void { |
| 2035 | .exact => |expect_lines| { | 2034 | .exact => |expect_lines| { |
| 2036 | for (expect_lines) |expect_line| { | 2035 | for (expect_lines) |expect_line| { |
| 2037 | const actual_line = actual_line_it.next() orelse { | 2036 | const actual_line = actual_line_it.next() orelse { |
| 2038 | try expected_generated.appendSlice(expect_line); | 2037 | try expected_generated.appendSlice(arena, expect_line); |
| 2039 | try expected_generated.append('\n'); | 2038 | try expected_generated.append(arena, '\n'); |
| 2040 | continue; | 2039 | continue; |
| 2041 | }; | 2040 | }; |
| 2042 | if (matchCompileError(actual_line, expect_line)) { | 2041 | if (matchCompileError(actual_line, expect_line)) { |
| 2043 | try expected_generated.appendSlice(actual_line); | 2042 | try expected_generated.appendSlice(arena, actual_line); |
| 2044 | try expected_generated.append('\n'); | 2043 | try expected_generated.append(arena, '\n'); |
| 2045 | continue; | 2044 | continue; |
| 2046 | } | 2045 | } |
| 2047 | try expected_generated.appendSlice(expect_line); | 2046 | try expected_generated.appendSlice(arena, expect_line); |
| 2048 | try expected_generated.append('\n'); | 2047 | try expected_generated.append(arena, '\n'); |
| 2049 | } | 2048 | } |
| 2050 | 2049 | ||
| 2051 | if (mem.eql(u8, expected_generated.items, actual_errors)) return; | 2050 | if (mem.eql(u8, expected_generated.items, actual_errors)) return; |
lib/std/fs/File.zig-4| ... | @@ -1725,10 +1725,6 @@ pub const Writer = struct { | ... | @@ -1725,10 +1725,6 @@ pub const Writer = struct { |
| 1725 | iovecs[len] = .{ .base = splat_buffer.ptr, .len = remaining_splat }; | 1725 | iovecs[len] = .{ .base = splat_buffer.ptr, .len = remaining_splat }; |
| 1726 | len += 1; | 1726 | len += 1; |
| 1727 | } | 1727 | } |
| 1728 | return std.posix.writev(handle, iovecs[0..len]) catch |err| { | ||
| 1729 | w.err = err; | ||
| 1730 | return error.WriteFailed; | ||
| 1731 | }; | ||
| 1732 | }, | 1728 | }, |
| 1733 | else => for (0..splat - 1) |_| { | 1729 | else => for (0..splat - 1) |_| { |
| 1734 | if (iovecs.len - len == 0) break; | 1730 | if (iovecs.len - len == 0) break; |
lib/std/io/tty.zig+35-29| ... | @@ -5,36 +5,9 @@ const process = std.process; | ... | @@ -5,36 +5,9 @@ const process = std.process; |
| 5 | const windows = std.os.windows; | 5 | const windows = std.os.windows; |
| 6 | const native_os = builtin.os.tag; | 6 | const native_os = builtin.os.tag; |
| 7 | 7 | ||
| 8 | /// Detect suitable TTY configuration options for the given file (commonly stdout/stderr). | 8 | /// Deprecated in favor of `Config.detect`. |
| 9 | /// This includes feature checks for ANSI escape codes and the Windows console API, as well as | ||
| 10 | /// respecting the `NO_COLOR` and `CLICOLOR_FORCE` environment variables to override the default. | ||
| 11 | /// Will attempt to enable ANSI escape code support if necessary/possible. | ||
| 12 | pub fn detectConfig(file: File) Config { | 9 | pub fn detectConfig(file: File) Config { |
| 13 | const force_color: ?bool = if (builtin.os.tag == .wasi) | 10 | return .detect(file); |
| 14 | null // wasi does not support environment variables | ||
| 15 | else if (process.hasNonEmptyEnvVarConstant("NO_COLOR")) | ||
| 16 | false | ||
| 17 | else if (process.hasNonEmptyEnvVarConstant("CLICOLOR_FORCE")) | ||
| 18 | true | ||
| 19 | else | ||
| 20 | null; | ||
| 21 | |||
| 22 | if (force_color == false) return .no_color; | ||
| 23 | |||
| 24 | if (file.getOrEnableAnsiEscapeSupport()) return .escape_codes; | ||
| 25 | |||
| 26 | if (native_os == .windows and file.isTty()) { | ||
| 27 | var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; | ||
| 28 | if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) == windows.FALSE) { | ||
| 29 | return if (force_color == true) .escape_codes else .no_color; | ||
| 30 | } | ||
| 31 | return .{ .windows_api = .{ | ||
| 32 | .handle = file.handle, | ||
| 33 | .reset_attributes = info.wAttributes, | ||
| 34 | } }; | ||
| 35 | } | ||
| 36 | |||
| 37 | return if (force_color == true) .escape_codes else .no_color; | ||
| 38 | } | 11 | } |
| 39 | 12 | ||
| 40 | pub const Color = enum { | 13 | pub const Color = enum { |
| ... | @@ -66,6 +39,38 @@ pub const Config = union(enum) { | ... | @@ -66,6 +39,38 @@ pub const Config = union(enum) { |
| 66 | escape_codes, | 39 | escape_codes, |
| 67 | windows_api: if (native_os == .windows) WindowsContext else void, | 40 | windows_api: if (native_os == .windows) WindowsContext else void, |
| 68 | 41 | ||
| 42 | /// Detect suitable TTY configuration options for the given file (commonly stdout/stderr). | ||
| 43 | /// This includes feature checks for ANSI escape codes and the Windows console API, as well as | ||
| 44 | /// respecting the `NO_COLOR` and `CLICOLOR_FORCE` environment variables to override the default. | ||
| 45 | /// Will attempt to enable ANSI escape code support if necessary/possible. | ||
| 46 | pub fn detect(file: File) Config { | ||
| 47 | const force_color: ?bool = if (builtin.os.tag == .wasi) | ||
| 48 | null // wasi does not support environment variables | ||
| 49 | else if (process.hasNonEmptyEnvVarConstant("NO_COLOR")) | ||
| 50 | false | ||
| 51 | else if (process.hasNonEmptyEnvVarConstant("CLICOLOR_FORCE")) | ||
| 52 | true | ||
| 53 | else | ||
| 54 | null; | ||
| 55 | |||
| 56 | if (force_color == false) return .no_color; | ||
| 57 | |||
| 58 | if (file.getOrEnableAnsiEscapeSupport()) return .escape_codes; | ||
| 59 | |||
| 60 | if (native_os == .windows and file.isTty()) { | ||
| 61 | var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; | ||
| 62 | if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) == windows.FALSE) { | ||
| 63 | return if (force_color == true) .escape_codes else .no_color; | ||
| 64 | } | ||
| 65 | return .{ .windows_api = .{ | ||
| 66 | .handle = file.handle, | ||
| 67 | .reset_attributes = info.wAttributes, | ||
| 68 | } }; | ||
| 69 | } | ||
| 70 | |||
| 71 | return if (force_color == true) .escape_codes else .no_color; | ||
| 72 | } | ||
| 73 | |||
| 69 | pub const WindowsContext = struct { | 74 | pub const WindowsContext = struct { |
| 70 | handle: File.Handle, | 75 | handle: File.Handle, |
| 71 | reset_attributes: u16, | 76 | reset_attributes: u16, |
| ... | @@ -123,6 +128,7 @@ pub const Config = union(enum) { | ... | @@ -123,6 +128,7 @@ pub const Config = union(enum) { |
| 123 | .dim => windows.FOREGROUND_INTENSITY, | 128 | .dim => windows.FOREGROUND_INTENSITY, |
| 124 | .reset => ctx.reset_attributes, | 129 | .reset => ctx.reset_attributes, |
| 125 | }; | 130 | }; |
| 131 | try w.flush(); | ||
| 126 | try windows.SetConsoleTextAttribute(ctx.handle, attributes); | 132 | try windows.SetConsoleTextAttribute(ctx.handle, attributes); |
| 127 | } else { | 133 | } else { |
| 128 | unreachable; | 134 | unreachable; |
lib/std/zig/ErrorBundle.zig+68-66| ... | @@ -11,6 +11,7 @@ const std = @import("std"); | ... | @@ -11,6 +11,7 @@ const std = @import("std"); |
| 11 | const ErrorBundle = @This(); | 11 | const ErrorBundle = @This(); |
| 12 | const Allocator = std.mem.Allocator; | 12 | const Allocator = std.mem.Allocator; |
| 13 | const assert = std.debug.assert; | 13 | const assert = std.debug.assert; |
| 14 | const Writer = std.io.Writer; | ||
| 14 | 15 | ||
| 15 | string_bytes: []const u8, | 16 | string_bytes: []const u8, |
| 16 | /// The first thing in this array is an `ErrorMessageList`. | 17 | /// The first thing in this array is an `ErrorMessageList`. |
| ... | @@ -162,23 +163,23 @@ pub const RenderOptions = struct { | ... | @@ -162,23 +163,23 @@ pub const RenderOptions = struct { |
| 162 | }; | 163 | }; |
| 163 | 164 | ||
| 164 | pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void { | 165 | pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void { |
| 165 | std.debug.lockStdErr(); | 166 | var buffer: [256]u8 = undefined; |
| 166 | defer std.debug.unlockStdErr(); | 167 | const w = std.debug.lockStderrWriter(&buffer); |
| 167 | const stderr: std.fs.File = .stderr(); | 168 | defer std.debug.unlockStderrWriter(); |
| 168 | return renderToWriter(eb, options, stderr.deprecatedWriter()) catch return; | 169 | renderToWriter(eb, options, w) catch return; |
| 169 | } | 170 | } |
| 170 | 171 | ||
| 171 | pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, writer: anytype) anyerror!void { | 172 | pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer) (Writer.Error || std.posix.UnexpectedError)!void { |
| 172 | if (eb.extra.len == 0) return; | 173 | if (eb.extra.len == 0) return; |
| 173 | for (eb.getMessages()) |err_msg| { | 174 | for (eb.getMessages()) |err_msg| { |
| 174 | try renderErrorMessageToWriter(eb, options, err_msg, writer, "error", .red, 0); | 175 | try renderErrorMessageToWriter(eb, options, err_msg, w, "error", .red, 0); |
| 175 | } | 176 | } |
| 176 | 177 | ||
| 177 | if (options.include_log_text) { | 178 | if (options.include_log_text) { |
| 178 | const log_text = eb.getCompileLogOutput(); | 179 | const log_text = eb.getCompileLogOutput(); |
| 179 | if (log_text.len != 0) { | 180 | if (log_text.len != 0) { |
| 180 | try writer.writeAll("\nCompile Log Output:\n"); | 181 | try w.writeAll("\nCompile Log Output:\n"); |
| 181 | try writer.writeAll(log_text); | 182 | try w.writeAll(log_text); |
| 182 | } | 183 | } |
| 183 | } | 184 | } |
| 184 | } | 185 | } |
| ... | @@ -187,74 +188,73 @@ fn renderErrorMessageToWriter( | ... | @@ -187,74 +188,73 @@ fn renderErrorMessageToWriter( |
| 187 | eb: ErrorBundle, | 188 | eb: ErrorBundle, |
| 188 | options: RenderOptions, | 189 | options: RenderOptions, |
| 189 | err_msg_index: MessageIndex, | 190 | err_msg_index: MessageIndex, |
| 190 | stderr: anytype, | 191 | w: *Writer, |
| 191 | kind: []const u8, | 192 | kind: []const u8, |
| 192 | color: std.io.tty.Color, | 193 | color: std.io.tty.Color, |
| 193 | indent: usize, | 194 | indent: usize, |
| 194 | ) anyerror!void { | 195 | ) (Writer.Error || std.posix.UnexpectedError)!void { |
| 195 | const ttyconf = options.ttyconf; | 196 | const ttyconf = options.ttyconf; |
| 196 | var counting_writer = std.io.countingWriter(stderr); | ||
| 197 | const counting_stderr = counting_writer.writer(); | ||
| 198 | const err_msg = eb.getErrorMessage(err_msg_index); | 197 | const err_msg = eb.getErrorMessage(err_msg_index); |
| 198 | const prefix_start = w.count; | ||
| 199 | if (err_msg.src_loc != .none) { | 199 | if (err_msg.src_loc != .none) { |
| 200 | const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc)); | 200 | const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc)); |
| 201 | try counting_stderr.writeByteNTimes(' ', indent); | 201 | try w.splatByteAll(' ', indent); |
| 202 | try ttyconf.setColor(stderr, .bold); | 202 | try ttyconf.setColor(w, .bold); |
| 203 | try counting_stderr.print("{s}:{d}:{d}: ", .{ | 203 | try w.print("{s}:{d}:{d}: ", .{ |
| 204 | eb.nullTerminatedString(src.data.src_path), | 204 | eb.nullTerminatedString(src.data.src_path), |
| 205 | src.data.line + 1, | 205 | src.data.line + 1, |
| 206 | src.data.column + 1, | 206 | src.data.column + 1, |
| 207 | }); | 207 | }); |
| 208 | try ttyconf.setColor(stderr, color); | 208 | try ttyconf.setColor(w, color); |
| 209 | try counting_stderr.writeAll(kind); | 209 | try w.writeAll(kind); |
| 210 | try counting_stderr.writeAll(": "); | 210 | try w.writeAll(": "); |
| 211 | // This is the length of the part before the error message: | 211 | // This is the length of the part before the error message: |
| 212 | // e.g. "file.zig:4:5: error: " | 212 | // e.g. "file.zig:4:5: error: " |
| 213 | const prefix_len: usize = @intCast(counting_stderr.context.bytes_written); | 213 | const prefix_len = w.count - prefix_start; |
| 214 | try ttyconf.setColor(stderr, .reset); | 214 | try ttyconf.setColor(w, .reset); |
| 215 | try ttyconf.setColor(stderr, .bold); | 215 | try ttyconf.setColor(w, .bold); |
| 216 | if (err_msg.count == 1) { | 216 | if (err_msg.count == 1) { |
| 217 | try writeMsg(eb, err_msg, stderr, prefix_len); | 217 | try writeMsg(eb, err_msg, w, prefix_len); |
| 218 | try stderr.writeByte('\n'); | 218 | try w.writeByte('\n'); |
| 219 | } else { | 219 | } else { |
| 220 | try writeMsg(eb, err_msg, stderr, prefix_len); | 220 | try writeMsg(eb, err_msg, w, prefix_len); |
| 221 | try ttyconf.setColor(stderr, .dim); | 221 | try ttyconf.setColor(w, .dim); |
| 222 | try stderr.print(" ({d} times)\n", .{err_msg.count}); | 222 | try w.print(" ({d} times)\n", .{err_msg.count}); |
| 223 | } | 223 | } |
| 224 | try ttyconf.setColor(stderr, .reset); | 224 | try ttyconf.setColor(w, .reset); |
| 225 | if (src.data.source_line != 0 and options.include_source_line) { | 225 | if (src.data.source_line != 0 and options.include_source_line) { |
| 226 | const line = eb.nullTerminatedString(src.data.source_line); | 226 | const line = eb.nullTerminatedString(src.data.source_line); |
| 227 | for (line) |b| switch (b) { | 227 | for (line) |b| switch (b) { |
| 228 | '\t' => try stderr.writeByte(' '), | 228 | '\t' => try w.writeByte(' '), |
| 229 | else => try stderr.writeByte(b), | 229 | else => try w.writeByte(b), |
| 230 | }; | 230 | }; |
| 231 | try stderr.writeByte('\n'); | 231 | try w.writeByte('\n'); |
| 232 | // TODO basic unicode code point monospace width | 232 | // TODO basic unicode code point monospace width |
| 233 | const before_caret = src.data.span_main - src.data.span_start; | 233 | const before_caret = src.data.span_main - src.data.span_start; |
| 234 | // -1 since span.main includes the caret | 234 | // -1 since span.main includes the caret |
| 235 | const after_caret = src.data.span_end -| src.data.span_main -| 1; | 235 | const after_caret = src.data.span_end -| src.data.span_main -| 1; |
| 236 | try stderr.writeByteNTimes(' ', src.data.column - before_caret); | 236 | try w.splatByteAll(' ', src.data.column - before_caret); |
| 237 | try ttyconf.setColor(stderr, .green); | 237 | try ttyconf.setColor(w, .green); |
| 238 | try stderr.writeByteNTimes('~', before_caret); | 238 | try w.splatByteAll('~', before_caret); |
| 239 | try stderr.writeByte('^'); | 239 | try w.writeByte('^'); |
| 240 | try stderr.writeByteNTimes('~', after_caret); | 240 | try w.splatByteAll('~', after_caret); |
| 241 | try stderr.writeByte('\n'); | 241 | try w.writeByte('\n'); |
| 242 | try ttyconf.setColor(stderr, .reset); | 242 | try ttyconf.setColor(w, .reset); |
| 243 | } | 243 | } |
| 244 | for (eb.getNotes(err_msg_index)) |note| { | 244 | for (eb.getNotes(err_msg_index)) |note| { |
| 245 | try renderErrorMessageToWriter(eb, options, note, stderr, "note", .cyan, indent); | 245 | try renderErrorMessageToWriter(eb, options, note, w, "note", .cyan, indent); |
| 246 | } | 246 | } |
| 247 | if (src.data.reference_trace_len > 0 and options.include_reference_trace) { | 247 | if (src.data.reference_trace_len > 0 and options.include_reference_trace) { |
| 248 | try ttyconf.setColor(stderr, .reset); | 248 | try ttyconf.setColor(w, .reset); |
| 249 | try ttyconf.setColor(stderr, .dim); | 249 | try ttyconf.setColor(w, .dim); |
| 250 | try stderr.print("referenced by:\n", .{}); | 250 | try w.print("referenced by:\n", .{}); |
| 251 | var ref_index = src.end; | 251 | var ref_index = src.end; |
| 252 | for (0..src.data.reference_trace_len) |_| { | 252 | for (0..src.data.reference_trace_len) |_| { |
| 253 | const ref_trace = eb.extraData(ReferenceTrace, ref_index); | 253 | const ref_trace = eb.extraData(ReferenceTrace, ref_index); |
| 254 | ref_index = ref_trace.end; | 254 | ref_index = ref_trace.end; |
| 255 | if (ref_trace.data.src_loc != .none) { | 255 | if (ref_trace.data.src_loc != .none) { |
| 256 | const ref_src = eb.getSourceLocation(ref_trace.data.src_loc); | 256 | const ref_src = eb.getSourceLocation(ref_trace.data.src_loc); |
| 257 | try stderr.print(" {s}: {s}:{d}:{d}\n", .{ | 257 | try w.print(" {s}: {s}:{d}:{d}\n", .{ |
| 258 | eb.nullTerminatedString(ref_trace.data.decl_name), | 258 | eb.nullTerminatedString(ref_trace.data.decl_name), |
| 259 | eb.nullTerminatedString(ref_src.src_path), | 259 | eb.nullTerminatedString(ref_src.src_path), |
| 260 | ref_src.line + 1, | 260 | ref_src.line + 1, |
| ... | @@ -262,36 +262,36 @@ fn renderErrorMessageToWriter( | ... | @@ -262,36 +262,36 @@ fn renderErrorMessageToWriter( |
| 262 | }); | 262 | }); |
| 263 | } else if (ref_trace.data.decl_name != 0) { | 263 | } else if (ref_trace.data.decl_name != 0) { |
| 264 | const count = ref_trace.data.decl_name; | 264 | const count = ref_trace.data.decl_name; |
| 265 | try stderr.print( | 265 | try w.print( |
| 266 | " {d} reference(s) hidden; use '-freference-trace={d}' to see all references\n", | 266 | " {d} reference(s) hidden; use '-freference-trace={d}' to see all references\n", |
| 267 | .{ count, count + src.data.reference_trace_len - 1 }, | 267 | .{ count, count + src.data.reference_trace_len - 1 }, |
| 268 | ); | 268 | ); |
| 269 | } else { | 269 | } else { |
| 270 | try stderr.print( | 270 | try w.print( |
| 271 | " remaining reference traces hidden; use '-freference-trace' to see all reference traces\n", | 271 | " remaining reference traces hidden; use '-freference-trace' to see all reference traces\n", |
| 272 | .{}, | 272 | .{}, |
| 273 | ); | 273 | ); |
| 274 | } | 274 | } |
| 275 | } | 275 | } |
| 276 | try ttyconf.setColor(stderr, .reset); | 276 | try ttyconf.setColor(w, .reset); |
| 277 | } | 277 | } |
| 278 | } else { | 278 | } else { |
| 279 | try ttyconf.setColor(stderr, color); | 279 | try ttyconf.setColor(w, color); |
| 280 | try stderr.writeByteNTimes(' ', indent); | 280 | try w.splatByteAll(' ', indent); |
| 281 | try stderr.writeAll(kind); | 281 | try w.writeAll(kind); |
| 282 | try stderr.writeAll(": "); | 282 | try w.writeAll(": "); |
| 283 | try ttyconf.setColor(stderr, .reset); | 283 | try ttyconf.setColor(w, .reset); |
| 284 | const msg = eb.nullTerminatedString(err_msg.msg); | 284 | const msg = eb.nullTerminatedString(err_msg.msg); |
| 285 | if (err_msg.count == 1) { | 285 | if (err_msg.count == 1) { |
| 286 | try stderr.print("{s}\n", .{msg}); | 286 | try w.print("{s}\n", .{msg}); |
| 287 | } else { | 287 | } else { |
| 288 | try stderr.print("{s}", .{msg}); | 288 | try w.print("{s}", .{msg}); |
| 289 | try ttyconf.setColor(stderr, .dim); | 289 | try ttyconf.setColor(w, .dim); |
| 290 | try stderr.print(" ({d} times)\n", .{err_msg.count}); | 290 | try w.print(" ({d} times)\n", .{err_msg.count}); |
| 291 | } | 291 | } |
| 292 | try ttyconf.setColor(stderr, .reset); | 292 | try ttyconf.setColor(w, .reset); |
| 293 | for (eb.getNotes(err_msg_index)) |note| { | 293 | for (eb.getNotes(err_msg_index)) |note| { |
| 294 | try renderErrorMessageToWriter(eb, options, note, stderr, "note", .cyan, indent + 4); | 294 | try renderErrorMessageToWriter(eb, options, note, w, "note", .cyan, indent + 4); |
| 295 | } | 295 | } |
| 296 | } | 296 | } |
| 297 | } | 297 | } |
| ... | @@ -300,13 +300,13 @@ fn renderErrorMessageToWriter( | ... | @@ -300,13 +300,13 @@ fn renderErrorMessageToWriter( |
| 300 | /// to allow for long, good-looking error messages. | 300 | /// to allow for long, good-looking error messages. |
| 301 | /// | 301 | /// |
| 302 | /// This is used to split the message in `@compileError("hello\nworld")` for example. | 302 | /// This is used to split the message in `@compileError("hello\nworld")` for example. |
| 303 | fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, stderr: anytype, indent: usize) !void { | 303 | fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, w: *Writer, indent: usize) !void { |
| 304 | var lines = std.mem.splitScalar(u8, eb.nullTerminatedString(err_msg.msg), '\n'); | 304 | var lines = std.mem.splitScalar(u8, eb.nullTerminatedString(err_msg.msg), '\n'); |
| 305 | while (lines.next()) |line| { | 305 | while (lines.next()) |line| { |
| 306 | try stderr.writeAll(line); | 306 | try w.writeAll(line); |
| 307 | if (lines.index == null) break; | 307 | if (lines.index == null) break; |
| 308 | try stderr.writeByte('\n'); | 308 | try w.writeByte('\n'); |
| 309 | try stderr.writeByteNTimes(' ', indent); | 309 | try w.splatByteAll(' ', indent); |
| 310 | } | 310 | } |
| 311 | } | 311 | } |
| 312 | 312 | ||
| ... | @@ -398,7 +398,7 @@ pub const Wip = struct { | ... | @@ -398,7 +398,7 @@ pub const Wip = struct { |
| 398 | pub fn printString(wip: *Wip, comptime fmt: []const u8, args: anytype) Allocator.Error!String { | 398 | pub fn printString(wip: *Wip, comptime fmt: []const u8, args: anytype) Allocator.Error!String { |
| 399 | const gpa = wip.gpa; | 399 | const gpa = wip.gpa; |
| 400 | const index: String = @intCast(wip.string_bytes.items.len); | 400 | const index: String = @intCast(wip.string_bytes.items.len); |
| 401 | try wip.string_bytes.writer(gpa).print(fmt, args); | 401 | try wip.string_bytes.print(gpa, fmt, args); |
| 402 | try wip.string_bytes.append(gpa, 0); | 402 | try wip.string_bytes.append(gpa, 0); |
| 403 | return index; | 403 | return index; |
| 404 | } | 404 | } |
| ... | @@ -788,9 +788,10 @@ pub const Wip = struct { | ... | @@ -788,9 +788,10 @@ pub const Wip = struct { |
| 788 | 788 | ||
| 789 | const ttyconf: std.io.tty.Config = .no_color; | 789 | const ttyconf: std.io.tty.Config = .no_color; |
| 790 | 790 | ||
| 791 | var bundle_buf = std.ArrayList(u8).init(std.testing.allocator); | 791 | var bundle_buf: std.io.Writer.Allocating = .init(std.testing.allocator); |
| 792 | const bundle_bw = &bundle_buf.interface; | ||
| 792 | defer bundle_buf.deinit(); | 793 | defer bundle_buf.deinit(); |
| 793 | try bundle.renderToWriter(.{ .ttyconf = ttyconf }, bundle_buf.writer()); | 794 | try bundle.renderToWriter(.{ .ttyconf = ttyconf }, bundle_bw); |
| 794 | 795 | ||
| 795 | var copy = copy: { | 796 | var copy = copy: { |
| 796 | var wip: ErrorBundle.Wip = undefined; | 797 | var wip: ErrorBundle.Wip = undefined; |
| ... | @@ -803,10 +804,11 @@ pub const Wip = struct { | ... | @@ -803,10 +804,11 @@ pub const Wip = struct { |
| 803 | }; | 804 | }; |
| 804 | defer copy.deinit(std.testing.allocator); | 805 | defer copy.deinit(std.testing.allocator); |
| 805 | 806 | ||
| 806 | var copy_buf = std.ArrayList(u8).init(std.testing.allocator); | 807 | var copy_buf: std.io.Writer.Allocating = .init(std.testing.allocator); |
| 808 | const copy_bw = &copy_buf.interface; | ||
| 807 | defer copy_buf.deinit(); | 809 | defer copy_buf.deinit(); |
| 808 | try copy.renderToWriter(.{ .ttyconf = ttyconf }, copy_buf.writer()); | 810 | try copy.renderToWriter(.{ .ttyconf = ttyconf }, copy_bw); |
| 809 | 811 | ||
| 810 | try std.testing.expectEqualStrings(bundle_buf.items, copy_buf.items); | 812 | try std.testing.expectEqualStrings(bundle_bw.getWritten(), copy_bw.getWritten()); |
| 811 | } | 813 | } |
| 812 | }; | 814 | }; |