| author | |
| committer | |
| log | 078e3305555f117efbaa83a91b2e79444847363c |
| tree | 0149ebe23cd28dcbfb5f6ec4d3fe1b65e47467e9 |
| parent | 0461a64a93f0596e98b62d596bb547e5455577d2 |
2 files changed, 70 insertions(+), 42 deletions(-)
lib/std/Build.zig+40-20| ... | ... | @@ -102,6 +102,10 @@ args: ?[][]const u8 = null, |
| 102 | 102 | debug_log_scopes: []const []const u8 = &.{}, |
| 103 | 103 | debug_compile_errors: bool = false, |
| 104 | 104 | debug_pkg_config: bool = false, |
| 105 | /// Number of stack frames captured when a `StackTrace` is recorded for debug purposes, | |
| 106 | /// in particular at `Step` creation. | |
| 107 | /// Set to 0 to disable stack collection. | |
| 108 | debug_stack_frames_count: u8 = 8, | |
| 105 | 109 | |
| 106 | 110 | /// Experimental. Use system Darling installation to run cross compiled macOS build artifacts. |
| 107 | 111 | enable_darling: bool = false, |
| ... | ... | @@ -1764,33 +1768,49 @@ pub fn dumpBadGetPathHelp( |
| 1764 | 1768 | }); |
| 1765 | 1769 | |
| 1766 | 1770 | const tty_config = std.io.tty.detectConfig(stderr); |
| 1767 | tty_config.setColor(w, .red) catch {}; | |
| 1768 | try stderr.writeAll(" The step was created by this stack trace:\n"); | |
| 1769 | tty_config.setColor(w, .reset) catch {}; | |
| 1770 | ||
| 1771 | const debug_info = std.debug.getSelfDebugInfo() catch |err| { | |
| 1772 | try w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}); | |
| 1773 | return; | |
| 1774 | }; | |
| 1775 | const ally = debug_info.allocator; | |
| 1776 | std.debug.writeStackTrace(s.getStackTrace(), w, ally, debug_info, tty_config) catch |err| { | |
| 1777 | try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}); | |
| 1778 | return; | |
| 1779 | }; | |
| 1780 | if (asking_step) |as| { | |
| 1771 | if (s.getStackTrace()) |stack_trace| { | |
| 1781 | 1772 | tty_config.setColor(w, .red) catch {}; |
| 1782 | try stderr.writeAll(" The step that is missing a dependency on the above step was created by this stack trace:\n"); | |
| 1773 | try stderr.writeAll(" The step was created by this stack trace:\n"); | |
| 1783 | 1774 | tty_config.setColor(w, .reset) catch {}; |
| 1784 | 1775 | |
| 1785 | std.debug.writeStackTrace(as.getStackTrace(), w, ally, debug_info, tty_config) catch |err| { | |
| 1776 | const debug_info = std.debug.getSelfDebugInfo() catch |err| { | |
| 1777 | try w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}); | |
| 1778 | return; | |
| 1779 | }; | |
| 1780 | const ally = debug_info.allocator; | |
| 1781 | ||
| 1782 | std.debug.writeStackTrace(stack_trace, w, ally, debug_info, tty_config) catch |err| { | |
| 1786 | 1783 | try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}); |
| 1787 | 1784 | return; |
| 1788 | 1785 | }; |
| 1786 | if (asking_step) |as| { | |
| 1787 | tty_config.setColor(w, .red) catch {}; | |
| 1788 | try stderr.writer().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name}); | |
| 1789 | tty_config.setColor(w, .reset) catch {}; | |
| 1790 | ||
| 1791 | if (as.getStackTrace()) |as_stack_trace| { | |
| 1792 | std.debug.writeStackTrace(as_stack_trace, w, ally, debug_info, tty_config) catch |err| { | |
| 1793 | try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}); | |
| 1794 | return; | |
| 1795 | }; | |
| 1796 | } else { | |
| 1797 | const field = "debug_stack_frames_count"; | |
| 1798 | comptime assert(@hasField(Build, field)); | |
| 1799 | tty_config.setColor(w, .yellow) catch {}; | |
| 1800 | try stderr.writer().print("no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{}); | |
| 1801 | tty_config.setColor(w, .reset) catch {}; | |
| 1802 | } | |
| 1803 | } | |
| 1804 | tty_config.setColor(w, .red) catch {}; | |
| 1805 | try stderr.writeAll(" Hope that helps. Proceeding to panic.\n"); | |
| 1806 | tty_config.setColor(w, .reset) catch {}; | |
| 1807 | } else { | |
| 1808 | const field = "debug_stack_frames_count"; | |
| 1809 | comptime assert(@hasField(Build, field)); | |
| 1810 | tty_config.setColor(w, .yellow) catch {}; | |
| 1811 | try stderr.writer().print("no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{}); | |
| 1812 | tty_config.setColor(w, .reset) catch {}; | |
| 1789 | 1813 | } |
| 1790 | ||
| 1791 | tty_config.setColor(w, .red) catch {}; | |
| 1792 | try stderr.writeAll(" Hope that helps. Proceeding to panic.\n"); | |
| 1793 | tty_config.setColor(w, .reset) catch {}; | |
| 1794 | 1814 | } |
| 1795 | 1815 | |
| 1796 | 1816 | /// Allocates a new string for assigning a value to a named macro. |
lib/std/Build/Step.zig+30-22| ... | ... | @@ -39,7 +39,7 @@ test_results: TestResults, |
| 39 | 39 | |
| 40 | 40 | /// The return address associated with creation of this step that can be useful |
| 41 | 41 | /// to print along with debugging messages. |
| 42 | debug_stack_trace: [n_debug_stack_frames]usize, | |
| 42 | debug_stack_trace: []usize, | |
| 43 | 43 | |
| 44 | 44 | pub const TestResults = struct { |
| 45 | 45 | fail_count: u32 = 0, |
| ... | ... | @@ -58,8 +58,6 @@ pub const TestResults = struct { |
| 58 | 58 | |
| 59 | 59 | pub const MakeFn = *const fn (self: *Step, prog_node: *std.Progress.Node) anyerror!void; |
| 60 | 60 | |
| 61 | const n_debug_stack_frames = 4; | |
| 62 | ||
| 63 | 61 | pub const State = enum { |
| 64 | 62 | precheck_unstarted, |
| 65 | 63 | precheck_started, |
| ... | ... | @@ -140,14 +138,6 @@ pub const StepOptions = struct { |
| 140 | 138 | pub fn init(options: StepOptions) Step { |
| 141 | 139 | const arena = options.owner.allocator; |
| 142 | 140 | |
| 143 | var addresses = [1]usize{0} ** n_debug_stack_frames; | |
| 144 | const first_ret_addr = options.first_ret_addr orelse @returnAddress(); | |
| 145 | var stack_trace = std.builtin.StackTrace{ | |
| 146 | .instruction_addresses = &addresses, | |
| 147 | .index = 0, | |
| 148 | }; | |
| 149 | std.debug.captureStackTrace(first_ret_addr, &stack_trace); | |
| 150 | ||
| 151 | 141 | return .{ |
| 152 | 142 | .id = options.id, |
| 153 | 143 | .name = arena.dupe(u8, options.name) catch @panic("OOM"), |
| ... | ... | @@ -157,7 +147,17 @@ pub fn init(options: StepOptions) Step { |
| 157 | 147 | .dependants = .{}, |
| 158 | 148 | .state = .precheck_unstarted, |
| 159 | 149 | .max_rss = options.max_rss, |
| 160 | .debug_stack_trace = addresses, | |
| 150 | .debug_stack_trace = blk: { | |
| 151 | const addresses = arena.alloc(usize, options.owner.debug_stack_frames_count) catch @panic("OOM"); | |
| 152 | @memset(addresses, 0); | |
| 153 | const first_ret_addr = options.first_ret_addr orelse @returnAddress(); | |
| 154 | var stack_trace = std.builtin.StackTrace{ | |
| 155 | .instruction_addresses = addresses, | |
| 156 | .index = 0, | |
| 157 | }; | |
| 158 | std.debug.captureStackTrace(first_ret_addr, &stack_trace); | |
| 159 | break :blk addresses; | |
| 160 | }, | |
| 161 | 161 | .result_error_msgs = .{}, |
| 162 | 162 | .result_error_bundle = std.zig.ErrorBundle.empty, |
| 163 | 163 | .result_cached = false, |
| ... | ... | @@ -199,14 +199,14 @@ pub fn dependOn(self: *Step, other: *Step) void { |
| 199 | 199 | self.dependencies.append(other) catch @panic("OOM"); |
| 200 | 200 | } |
| 201 | 201 | |
| 202 | pub fn getStackTrace(s: *Step) std.builtin.StackTrace { | |
| 203 | const stack_addresses = &s.debug_stack_trace; | |
| 202 | pub fn getStackTrace(s: *Step) ?std.builtin.StackTrace { | |
| 204 | 203 | var len: usize = 0; |
| 205 | while (len < n_debug_stack_frames and stack_addresses[len] != 0) { | |
| 204 | while (len < s.debug_stack_trace.len and s.debug_stack_trace[len] != 0) { | |
| 206 | 205 | len += 1; |
| 207 | 206 | } |
| 208 | return .{ | |
| 209 | .instruction_addresses = stack_addresses, | |
| 207 | ||
| 208 | return if (len == 0) null else .{ | |
| 209 | .instruction_addresses = s.debug_stack_trace, | |
| 210 | 210 | .index = len, |
| 211 | 211 | }; |
| 212 | 212 | } |
| ... | ... | @@ -245,11 +245,19 @@ pub fn dump(step: *Step) void { |
| 245 | 245 | return; |
| 246 | 246 | }; |
| 247 | 247 | const ally = debug_info.allocator; |
| 248 | w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {}; | |
| 249 | std.debug.writeStackTrace(step.getStackTrace(), w, ally, debug_info, tty_config) catch |err| { | |
| 250 | stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {}; | |
| 251 | return; | |
| 252 | }; | |
| 248 | if (step.getStackTrace()) |stack_trace| { | |
| 249 | w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {}; | |
| 250 | std.debug.writeStackTrace(stack_trace, w, ally, debug_info, tty_config) catch |err| { | |
| 251 | stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {}; | |
| 252 | return; | |
| 253 | }; | |
| 254 | } else { | |
| 255 | const field = "debug_stack_frames_count"; | |
| 256 | comptime assert(@hasField(Build, field)); | |
| 257 | tty_config.setColor(w, .yellow) catch {}; | |
| 258 | w.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {}; | |
| 259 | tty_config.setColor(w, .reset) catch {}; | |
| 260 | } | |
| 253 | 261 | } |
| 254 | 262 | |
| 255 | 263 | const Step = @This(); |