| ... | ... | @@ -63,9 +63,9 @@ protocol_server_mutex: Io.Mutex, |
| 63 | 63 | web_server: ?*AvoidableWebServer, |
| 64 | 64 | /// Allocated into `gpa`. |
| 65 | 65 | memory_blocked_steps: std.ArrayList(Configuration.Step.Index), |
| 66 | | /// Allocated into `gpa`. |
| 66 | /// Allocated into `gpa` during `prepare`. |
| 67 | 67 | initial_steps: std.array_hash_map.Auto(Configuration.Step.Index, void), |
| 68 | | /// Allocated into `gpa`. |
| 68 | /// Allocated into `gpa` during `prepare`. |
| 69 | 69 | step_stack: std.array_hash_map.Auto(Configuration.Step.Index, void), |
| 70 | 70 | pkg_config: PkgConfig, |
| 71 | 71 | |
| ... | ... | @@ -163,7 +163,6 @@ pub fn main(init: process.Init.Minimal) !void { |
| 163 | 163 | |
| 164 | 164 | var arena_instance: std.heap.ArenaAllocator = .init(std.heap.page_allocator); |
| 165 | 165 | defer arena_instance.deinit(); |
| 166 | | defer if (debugMakerLeaks()) log.debug("used {Bi} of arena", .{arena_instance.queryCapacity()}); |
| 167 | 166 | const arena = arena_instance.allocator(); |
| 168 | 167 | |
| 169 | 168 | const args = try init.args.toSlice(arena); |
| ... | ... | @@ -445,8 +444,6 @@ pub fn main(init: process.Init.Minimal) !void { |
| 445 | 444 | } else if (mem.cutPrefix(u8, arg, "--debug-rt=")) |rest| { |
| 446 | 445 | graph.debug_compiler_runtime_libs = stringToEnum(std.lang.Optimize, rest) orelse |
| 447 | 446 | fatal("unrecognized optimization mode: {s}", .{rest}); |
| 448 | | } else if (is_debug_mode and mem.eql(u8, arg, "--debug-maker-leaks")) { |
| 449 | | debug_maker_leaks = true; |
| 450 | 447 | } else if (mem.eql(u8, arg, "--libc-runtimes") or mem.eql(u8, arg, "--glibc-runtimes")) { |
| 451 | 448 | // --glibc-runtimes was the old name of the flag; kept for compatibility for now. |
| 452 | 449 | graph.libc_runtimes_dir = nextArgOrFatal(args, &arg_i); |
| ... | ... | @@ -682,9 +679,8 @@ pub fn main(init: process.Init.Minimal) !void { |
| 682 | 679 | } else null; |
| 683 | 680 | |
| 684 | 681 | var stdin_buffer: [256]u8 = undefined; |
| 685 | | var stdout_buffer: [256]u8 = undefined; |
| 686 | 682 | var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer); |
| 687 | | var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); |
| 683 | const stdout_writer = initStdoutWriter(io); |
| 688 | 684 | |
| 689 | 685 | var protocol_server_allocation: AvoidableServer = undefined; |
| 690 | 686 | const protocol_server: ?*AvoidableServer = if (listen) s: { |
| ... | ... | @@ -694,9 +690,9 @@ pub fn main(init: process.Init.Minimal) !void { |
| 694 | 690 | if (step_names.items.len > 0) fatal("build steps must be provided over the protocol instead of using CLI arguments", .{}); |
| 695 | 691 | protocol_server_allocation = .{ |
| 696 | 692 | .in = &stdin_reader.interface, |
| 697 | | .out = &stdout_writer.interface, |
| 693 | .out = stdout_writer, |
| 698 | 694 | }; |
| 699 | | try serveBSPHandshake(&protocol_server_allocation); |
| 695 | try serveBspHandshake(&protocol_server_allocation); |
| 700 | 696 | break :s &protocol_server_allocation; |
| 701 | 697 | } else null; |
| 702 | 698 | |
| ... | ... | @@ -764,10 +760,8 @@ pub fn main(init: process.Init.Minimal) !void { |
| 764 | 760 | .include = install_include_path, |
| 765 | 761 | }, |
| 766 | 762 | |
| 767 | | // Extra step at the end which is the autogenerated placeholder |
| 768 | | // step which indicates that we need to reconfigure. |
| 769 | | .steps = try arena.alloc(Step, scanned_config.configuration.steps.len + 1), |
| 770 | | .generated_files = try arena.alloc(Path, scanned_config.configuration.generated_files_len), |
| 763 | .steps = &.{}, |
| 764 | .generated_files = &.{}, |
| 771 | 765 | .run_args = run_args, |
| 772 | 766 | |
| 773 | 767 | .available_rss = max_rss, |
| ... | ... | @@ -794,11 +788,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 794 | 788 | else |
| 795 | 789 | .failures, |
| 796 | 790 | }; |
| 797 | | defer { |
| 798 | | maker.memory_blocked_steps.deinit(gpa); |
| 799 | | maker.initial_steps.deinit(gpa); |
| 800 | | maker.step_stack.deinit(gpa); |
| 801 | | } |
| 791 | defer maker.deinit(); |
| 802 | 792 | |
| 803 | 793 | if (maker.available_rss == 0) { |
| 804 | 794 | maker.available_rss = process.totalSystemMemory() catch std.math.maxInt(u64); |
| ... | ... | @@ -820,6 +810,11 @@ pub fn main(init: process.Init.Minimal) !void { |
| 820 | 810 | var select: Io.Select(Event) = .init(io, &select_buffer); |
| 821 | 811 | defer select.cancelDiscard(); |
| 822 | 812 | |
| 813 | // File watching cannot be canceled without blocking |
| 814 | // https://codeberg.org/ziglang/zig/issues/31693 |
| 815 | var is_fs_watching = false; |
| 816 | defer if (is_fs_watching) @panic("(zig build system) TODO file watching cannot be canceled without blocking"); |
| 817 | |
| 823 | 818 | try select.concurrent(.message, Server.receiveMessage, .{s}); |
| 824 | 819 | |
| 825 | 820 | var in_debounce = false; |
| ... | ... | @@ -828,10 +823,13 @@ pub fn main(init: process.Init.Minimal) !void { |
| 828 | 823 | const header: Client.Message.Header = try payload; |
| 829 | 824 | switch (header.tag) { |
| 830 | 825 | .exit => { |
| 831 | | cleanExit(io, &scanned_config); |
| 832 | | process.exit(0); |
| 826 | // exit early until file watching supports cancelation without blocking |
| 827 | if (is_fs_watching) std.process.exit(0); |
| 828 | return cleanExit(io, &scanned_config); |
| 833 | 829 | }, |
| 834 | 830 | .bsp_build_steps => { |
| 831 | if (is_fs_watching) @panic("(zig build system) TODO file watching cannot be canceled without blocking"); |
| 832 | |
| 835 | 833 | // Cancel existing file watching |
| 836 | 834 | select.cancelDiscard(); |
| 837 | 835 | in_debounce = false; |
| ... | ... | @@ -865,6 +863,10 @@ pub fn main(init: process.Init.Minimal) !void { |
| 865 | 863 | &watch.?, |
| 866 | 864 | if (in_debounce) .{ .ms = debounce_interval_ms } else .none, |
| 867 | 865 | }); |
| 866 | is_fs_watching = true; |
| 867 | } else if (watch) |*w| { |
| 868 | w.deinit(); |
| 869 | watch = null; |
| 868 | 870 | } |
| 869 | 871 | |
| 870 | 872 | continue :loop try select.await(); |
| ... | ... | @@ -873,6 +875,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 873 | 875 | } |
| 874 | 876 | }, |
| 875 | 877 | .fs_event => |payload| { |
| 878 | is_fs_watching = false; |
| 876 | 879 | if (!Watch.have_impl) unreachable; |
| 877 | 880 | switch (payload catch |err| switch (err) { |
| 878 | 881 | error.MustReconfigure => { |
| ... | ... | @@ -894,6 +897,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 894 | 897 | &watch.?, |
| 895 | 898 | if (in_debounce) .{ .ms = debounce_interval_ms } else .none, |
| 896 | 899 | }); |
| 900 | is_fs_watching = true; |
| 897 | 901 | continue :loop try select.await(); |
| 898 | 902 | }, |
| 899 | 903 | } |
| ... | ... | @@ -917,7 +921,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 917 | 921 | if (!Watch.have_impl) fatal("--watch not yet implemented for {t}", .{native_os}); |
| 918 | 922 | break :w try .init(&maker); |
| 919 | 923 | }; |
| 920 | | defer w.deinit(); |
| 924 | defer if (watch_flag) w.deinit(); |
| 921 | 925 | |
| 922 | 926 | if (web_server) |ws| try ws.updateConfiguration(&maker); |
| 923 | 927 | |
| ... | ... | @@ -2333,6 +2337,11 @@ fn prepare( |
| 2333 | 2337 | const step_stack = &maker.step_stack; |
| 2334 | 2338 | const c = &maker.scanned_config.configuration; |
| 2335 | 2339 | |
| 2340 | // Extra step at the end which is the autogenerated placeholder |
| 2341 | // step which indicates that we need to reconfigure. |
| 2342 | maker.steps = try arena.alloc(Step, c.steps.len + 1); |
| 2343 | maker.generated_files = try arena.alloc(Path, c.generated_files_len); |
| 2344 | |
| 2336 | 2345 | // The last element is a reserved special pseudostep which contains the |
| 2337 | 2346 | // watch inputs for the configurer executable. |
| 2338 | 2347 | for (maker.steps[0 .. maker.steps.len - 1], 0..) |*step, step_index_usize| { |
| ... | ... | @@ -2652,8 +2661,7 @@ fn makeSteps( |
| 2652 | 2661 | break :code 2; // failure; do not print build command |
| 2653 | 2662 | }; |
| 2654 | 2663 | if (code == 0) { |
| 2655 | | removePoisonedConfiguration(io, maker.scanned_config); |
| 2656 | | if (debugMakerLeaks()) return deinit(maker); |
| 2664 | return cleanExit(io, maker.scanned_config); |
| 2657 | 2665 | } |
| 2658 | 2666 | cleanup_task.await(io); // There is a defer above but an exit below. |
| 2659 | 2667 | _ = io.lockStderr(&.{}, graph.stderr_mode) catch {}; |
| ... | ... | @@ -2662,12 +2670,10 @@ fn makeSteps( |
| 2662 | 2670 | |
| 2663 | 2671 | fn deinit(maker: *Maker) void { |
| 2664 | 2672 | const gpa = maker.gpa; |
| 2665 | | for (maker.steps) |*step| { |
| 2666 | | step.clearResultStderr(gpa); |
| 2667 | | step.clearFailedCommand(gpa); |
| 2668 | | step.clearErrorBundle(gpa); |
| 2669 | | step.inputs.deinit(gpa); |
| 2670 | | } |
| 2673 | for (maker.steps) |*step| step.deinit(gpa); |
| 2674 | maker.memory_blocked_steps.deinit(gpa); |
| 2675 | maker.initial_steps.deinit(gpa); |
| 2676 | maker.step_stack.deinit(gpa); |
| 2671 | 2677 | } |
| 2672 | 2678 | |
| 2673 | 2679 | fn stepReady( |
| ... | ... | @@ -2800,9 +2806,10 @@ fn makeStep( |
| 2800 | 2806 | } |
| 2801 | 2807 | |
| 2802 | 2808 | // No matter the result, we want to display error/warning messages. |
| 2803 | | if (make_step.result_error_bundle.errorMessageCount() > 0 or |
| 2804 | | make_step.result_error_msgs.items.len > 0 or |
| 2805 | | make_step.result_stderr.len > 0) |
| 2809 | if (maker.protocol_server == null and |
| 2810 | (make_step.result_error_bundle.errorMessageCount() > 0 or |
| 2811 | make_step.result_error_msgs.items.len > 0 or |
| 2812 | make_step.result_stderr.len > 0)) |
| 2806 | 2813 | { |
| 2807 | 2814 | const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode); |
| 2808 | 2815 | defer io.unlockStderr(); |
| ... | ... | @@ -3360,7 +3367,7 @@ fn cleanTmpFiles(maker: *Maker, steps: []const Configuration.Step.Index) void { |
| 3360 | 3367 | } |
| 3361 | 3368 | } |
| 3362 | 3369 | |
| 3363 | | fn serveBSPHandshake(s: *const std.zig.Server) !void { |
| 3370 | fn serveBspHandshake(s: *const std.zig.Server) !void { |
| 3364 | 3371 | const handshake_header: Server.Message.Handshake = .{ |
| 3365 | 3372 | .version = Server.build_system_version, |
| 3366 | 3373 | .flags = .{ |
| ... | ... | @@ -3744,11 +3751,6 @@ fn removePoisonedConfiguration(io: Io, scanned_config: *const ScannedConfig) voi |
| 3744 | 3751 | } |
| 3745 | 3752 | } |
| 3746 | 3753 | |
| 3747 | | inline fn debugMakerLeaks() bool { |
| 3748 | | if (!is_debug_mode) return false; |
| 3749 | | return debug_maker_leaks; |
| 3750 | | } |
| 3751 | | |
| 3752 | 3754 | const BuildRoot = struct { |
| 3753 | 3755 | directory: Cache.Directory, |
| 3754 | 3756 | close_directory: bool, |