authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-27 05:08:24-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-27 18:06:08+01:00
logb490412cd28e4bc76de9dfe39ac1d99435a86814
tree68ac20fbe62261e8c522353299afe8d7b657b4f9
parent523cfabcdff65c9547299b3a4f721d2052c163ee

build runner: fail, not warn when insufficient memory

Users can proceed by telling the build system how much memory to assume the system has. I have improved the failure message to communicate this. Partially reverts 87f8f47ba508b684d03c13b850cac3fb72efac26 Even if we wanted to unrevert this reverted commit, it's not sufficient to merely downgrade the failure to a warning, because the main scheduling logic will fail to schedule steps that have a max_rss exceeding the detected system value, causing some steps to never get executed, eventually tripping an assert. Such a change would need to also override the max_rss value to be equal to the greatest value across all steps. closes #31510

1 files changed, 10 insertions(+), 5 deletions(-)

lib/compiler/build_runner.zig+10-5
......@@ -532,7 +532,7 @@ pub fn main(init: process.Init.Minimal) !void {
532532 }
533533
534534 prepare(arena, builder, targets.items, &run, graph.random_seed) catch |err| switch (err) {
535 error.DependencyLoopDetected => {
535 error.DependencyLoopDetected, error.InsufficientMemory => {
536536 // Perhaps in the future there could be an Advanced Options flag
537537 // such as --debug-build-runner-leaks which would make this code
538538 // return instead of calling exit.
......@@ -696,8 +696,8 @@ fn prepare(
696696 for (0..step_names.len) |i| {
697697 const step_name = step_names[step_names.len - i - 1];
698698 const s = b.top_level_steps.get(step_name) orelse {
699 std.debug.print("no step named '{s}'\n access the help menu with 'zig build -h'\n", .{step_name});
700 process.exit(1);
699 std.log.info("access the help menu with \"zig build -h\"", .{});
700 fatal("no step named '{s}'", .{step_name});
701701 };
702702 step_stack.putAssumeCapacity(&s.step, {});
703703 }
......@@ -716,8 +716,10 @@ fn prepare(
716716 {
717717 // Check that we have enough memory to complete the build.
718718 var any_problems = false;
719 var max_needed: usize = 0;
719720 for (step_stack.keys()) |s| {
720721 if (s.max_rss == 0) continue;
722 max_needed = @max(max_needed, s.max_rss);
721723 if (s.max_rss > run.available_rss) {
722724 if (run.skip_oom_steps) {
723725 s.state = .skipped_oom;
......@@ -725,7 +727,7 @@ fn prepare(
725727 dependant.pending_deps -= 1;
726728 }
727729 } else {
728 std.debug.print("{s}{s}: this step declares an upper bound of {d} bytes of memory, exceeding the available {d} bytes of memory\n", .{
730 std.log.err("{s}{s}: this step declares an upper bound of {d} bytes of memory, exceeding the available {d} bytes of memory", .{
729731 s.owner.dep_prefix, s.name, s.max_rss, run.available_rss,
730732 });
731733 any_problems = true;
......@@ -734,8 +736,11 @@ fn prepare(
734736 }
735737 if (any_problems) {
736738 if (run.max_rss_is_default) {
737 std.debug.print("note: use --maxrss to override the default", .{});
739 std.log.info("use --maxrss {d} to proceed, risking system memory exhaustion", .{
740 max_needed,
741 });
738742 }
743 return error.InsufficientMemory;
739744 }
740745 }
741746}