| ... | ... | @@ -60,6 +60,8 @@ web_server: ?*AvoidableWebServer, |
| 60 | 60 | /// Allocated into `gpa`. |
| 61 | 61 | memory_blocked_steps: std.ArrayList(Configuration.Step.Index), |
| 62 | 62 | /// Allocated into `gpa`. |
| 63 | initial_steps: std.array_hash_map.Auto(Configuration.Step.Index, void), |
| 64 | /// Allocated into `gpa`. |
| 63 | 65 | step_stack: std.array_hash_map.Auto(Configuration.Step.Index, void), |
| 64 | 66 | pkg_config: PkgConfig, |
| 65 | 67 | |
| ... | ... | @@ -762,6 +764,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 762 | 764 | .protocol_server = protocol_server, |
| 763 | 765 | .protocol_server_mutex = .init, |
| 764 | 766 | .memory_blocked_steps = .empty, |
| 767 | .initial_steps = .empty, |
| 765 | 768 | .step_stack = .empty, |
| 766 | 769 | .pkg_config = .{ .debug = debug_pkg_config }, |
| 767 | 770 | |
| ... | ... | @@ -776,6 +779,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 776 | 779 | }; |
| 777 | 780 | defer { |
| 778 | 781 | maker.memory_blocked_steps.deinit(gpa); |
| 782 | maker.initial_steps.deinit(gpa); |
| 779 | 783 | maker.step_stack.deinit(gpa); |
| 780 | 784 | } |
| 781 | 785 | |
| ... | ... | @@ -809,6 +813,41 @@ pub fn main(init: process.Init.Minimal) !void { |
| 809 | 813 | cleanExit(io, &scanned_config); |
| 810 | 814 | process.exit(0); |
| 811 | 815 | }, |
| 816 | .bsp_build_steps => { |
| 817 | // Cancel existing file watching |
| 818 | select.cancelDiscard(); |
| 819 | in_debounce = false; |
| 820 | |
| 821 | const body = try s.in.takeStruct(Client.Message.BuildSteps, .little); |
| 822 | const steps = try s.in.readSliceEndianAlloc(gpa, Configuration.Step.Index, body.step_count, .little); |
| 823 | defer gpa.free(steps); |
| 824 | if (body.flags.watch and !Watch.have_impl) fatal("file watching is unavailable", .{}); |
| 825 | |
| 826 | try select.concurrent(.message, Server.receiveMessage, .{s}); |
| 827 | |
| 828 | maker.watch = body.flags.watch; |
| 829 | maker.prepare(steps) catch |err| switch (err) { |
| 830 | error.DependencyLoopDetected, error.InsufficientMemory => { |
| 831 | // TODO handle DependencyLoopDetected as error.FailedButCacheIntact |
| 832 | // and handle InsufficientMemory as error.AlreadyReported |
| 833 | _ = io.lockStderr(&.{}, graph.stderr_mode) catch {}; |
| 834 | process.exit(1); |
| 835 | }, |
| 836 | else => |e| return e, |
| 837 | }; |
| 838 | |
| 839 | try maker.makeSteps(main_progress_node, null); |
| 840 | |
| 841 | if (body.flags.watch) { |
| 842 | if (!Watch.have_impl) unreachable; |
| 843 | if (w == null) w = try .init(&maker); |
| 844 | |
| 845 | try w.?.update(maker.step_stack.keys()); |
| 846 | try select.concurrent(.fs_event, Watch.wait, .{ &w.?, if (in_debounce) .{ .ms = debounce_interval_ms } else .none }); |
| 847 | } |
| 848 | |
| 849 | continue :loop try select.await(); |
| 850 | }, |
| 812 | 851 | else => fatal("unsupported message: {t}", .{header.tag}), |
| 813 | 852 | } |
| 814 | 853 | }, |
| ... | ... | @@ -818,7 +857,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 818 | 857 | .timeout => { |
| 819 | 858 | assert(in_debounce); |
| 820 | 859 | markFailedStepsDirty(&maker); |
| 821 | | if (true) @panic("TODO run steps that were previous specified over the build system protocol"); |
| 860 | try maker.makeSteps(main_progress_node, null); |
| 822 | 861 | in_debounce = false; |
| 823 | 862 | }, |
| 824 | 863 | .dirty => in_debounce = true, |
| ... | ... | @@ -830,7 +869,10 @@ pub fn main(init: process.Init.Minimal) !void { |
| 830 | 869 | } |
| 831 | 870 | } |
| 832 | 871 | |
| 833 | | maker.prepare(step_names.items) catch |err| switch (err) { |
| 872 | const initial_steps = try maker.resolveTopLevelSteps(step_names.items); |
| 873 | defer gpa.free(initial_steps); |
| 874 | |
| 875 | maker.prepare(initial_steps) catch |err| switch (err) { |
| 834 | 876 | error.DependencyLoopDetected, error.InsufficientMemory => { |
| 835 | 877 | // TODO handle DependencyLoopDetected as error.FailedButCacheIntact |
| 836 | 878 | // and handle InsufficientMemory as error.AlreadyReported |
| ... | ... | @@ -857,7 +899,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 857 | 899 | }) { |
| 858 | 900 | if (web_server) |ws| ws.startBuild(); |
| 859 | 901 | |
| 860 | | try maker.makeStepNames(step_names.items, main_progress_node, fuzz); |
| 902 | try maker.makeSteps(main_progress_node, fuzz); |
| 861 | 903 | |
| 862 | 904 | if (web_server) |ws| { |
| 863 | 905 | if (fuzz) |mode| if (mode != .forever) fatal( |
| ... | ... | @@ -2104,11 +2146,37 @@ pub fn stepByIndex(maker: *const Maker, i: Configuration.Step.Index) *Step { |
| 2104 | 2146 | return &maker.steps[@backingInt(i)]; |
| 2105 | 2147 | } |
| 2106 | 2148 | |
| 2107 | | fn prepare(maker: *Maker, step_names: []const []const u8) !void { |
| 2149 | fn resolveTopLevelSteps(maker: *Maker, step_names: []const []const u8) ![]const Configuration.Step.Index { |
| 2150 | const gpa = maker.gpa; |
| 2151 | const c = &maker.scanned_config.configuration; |
| 2152 | |
| 2153 | if (step_names.len == 0) { |
| 2154 | return try gpa.dupe(Configuration.Step.Index, &.{c.default_step}); |
| 2155 | } |
| 2156 | |
| 2157 | var result: std.array_hash_map.Auto(Configuration.Step.Index, void) = .empty; |
| 2158 | defer result.deinit(gpa); |
| 2159 | |
| 2160 | try result.ensureTotalCapacity(gpa, step_names.len); |
| 2161 | |
| 2162 | for (0..step_names.len) |i| { |
| 2163 | const step_name = step_names[step_names.len - i - 1]; |
| 2164 | const s = maker.scanned_config.top_level_steps.get(step_name) orelse { |
| 2165 | log.info("to list available steps: zig build -l", .{}); |
| 2166 | fatal("no such step: {s}", .{step_name}); |
| 2167 | }; |
| 2168 | result.putAssumeCapacity(s, {}); |
| 2169 | } |
| 2170 | |
| 2171 | return try gpa.dupe(Configuration.Step.Index, result.keys()); |
| 2172 | } |
| 2173 | |
| 2174 | fn prepare(maker: *Maker, step_indices: []const Configuration.Step.Index) !void { |
| 2108 | 2175 | const gpa = maker.gpa; |
| 2109 | 2176 | const graph = maker.graph; |
| 2110 | 2177 | const arena = graph.arena; |
| 2111 | 2178 | const seed: u32 = graph.random_seed; |
| 2179 | const initial_steps = &maker.initial_steps; |
| 2112 | 2180 | const step_stack = &maker.step_stack; |
| 2113 | 2181 | const c = &maker.scanned_config.configuration; |
| 2114 | 2182 | |
| ... | ... | @@ -2117,18 +2185,15 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void { |
| 2117 | 2185 | step.* = .{ .extended = .init(step_index.ptr(c).flags(c).tag) }; |
| 2118 | 2186 | } |
| 2119 | 2187 | |
| 2120 | | if (step_names.len == 0) { |
| 2121 | | try step_stack.put(gpa, c.default_step, {}); |
| 2122 | | } else { |
| 2123 | | try step_stack.ensureUnusedCapacity(gpa, step_names.len); |
| 2124 | | for (0..step_names.len) |i| { |
| 2125 | | const step_name = step_names[step_names.len - i - 1]; |
| 2126 | | const s = maker.scanned_config.top_level_steps.get(step_name) orelse { |
| 2127 | | log.info("to list available steps: zig build -l", .{}); |
| 2128 | | fatal("no such step: {s}", .{step_name}); |
| 2129 | | }; |
| 2130 | | step_stack.putAssumeCapacity(s, {}); |
| 2131 | | } |
| 2188 | try initial_steps.ensureUnusedCapacity(gpa, step_indices.len); |
| 2189 | try step_stack.ensureUnusedCapacity(gpa, step_indices.len); |
| 2190 | |
| 2191 | initial_steps.clearRetainingCapacity(); |
| 2192 | step_stack.clearRetainingCapacity(); |
| 2193 | |
| 2194 | for (step_indices) |step| { |
| 2195 | initial_steps.putAssumeCapacity(step, {}); |
| 2196 | step_stack.putAssumeCapacity(step, {}); |
| 2132 | 2197 | } |
| 2133 | 2198 | |
| 2134 | 2199 | const starting_steps = try arena.dupe(Configuration.Step.Index, step_stack.keys()); |
| ... | ... | @@ -2177,9 +2242,8 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void { |
| 2177 | 2242 | } |
| 2178 | 2243 | } |
| 2179 | 2244 | |
| 2180 | | fn makeStepNames( |
| 2245 | fn makeSteps( |
| 2181 | 2246 | maker: *Maker, |
| 2182 | | step_names: []const []const u8, |
| 2183 | 2247 | parent_progress_node: std.Progress.Node, |
| 2184 | 2248 | fuzz: ?Fuzz.Mode, |
| 2185 | 2249 | ) !void { |
| ... | ... | @@ -2367,7 +2431,7 @@ fn makeStepNames( |
| 2367 | 2431 | defer step_stack_copy.deinit(gpa); |
| 2368 | 2432 | |
| 2369 | 2433 | var print_node: PrintNode = .{ .parent = null }; |
| 2370 | | if (step_names.len == 0) { |
| 2434 | if (maker.initial_steps.count() == 0) { |
| 2371 | 2435 | print_node.last = true; |
| 2372 | 2436 | printTreeStep(maker, c.default_step, t, &print_node, &step_stack_copy) catch |err| switch (err) { |
| 2373 | 2437 | error.Canceled => |e| return e, |
| ... | ... | @@ -2375,10 +2439,10 @@ fn makeStepNames( |
| 2375 | 2439 | }; |
| 2376 | 2440 | } else { |
| 2377 | 2441 | const last_index = if (maker.summary == .all) top_level_steps.count() else blk: { |
| 2378 | | var i: usize = step_names.len; |
| 2442 | var i: usize = maker.initial_steps.count(); |
| 2379 | 2443 | while (i > 0) { |
| 2380 | 2444 | i -= 1; |
| 2381 | | const step_index = top_level_steps.get(step_names[i]).?; |
| 2445 | const step_index = maker.initial_steps.keys()[i]; |
| 2382 | 2446 | const step = maker.stepByIndex(step_index); |
| 2383 | 2447 | const found = switch (maker.summary) { |
| 2384 | 2448 | .all, .line, .none => unreachable, |
| ... | ... | @@ -2389,8 +2453,7 @@ fn makeStepNames( |
| 2389 | 2453 | } |
| 2390 | 2454 | break :blk top_level_steps.count(); |
| 2391 | 2455 | }; |
| 2392 | | for (step_names, 0..) |step_name, i| { |
| 2393 | | const step_index = top_level_steps.get(step_name).?; |
| 2456 | for (maker.initial_steps.keys(), 0..) |step_index, i| { |
| 2394 | 2457 | print_node.last = i + 1 == last_index; |
| 2395 | 2458 | printTreeStep(maker, step_index, t, &print_node, &step_stack_copy) catch |err| switch (err) { |
| 2396 | 2459 | error.Canceled => |e| return e, |
| ... | ... | @@ -2401,7 +2464,7 @@ fn makeStepNames( |
| 2401 | 2464 | w.writeByte('\n') catch {}; |
| 2402 | 2465 | } |
| 2403 | 2466 | |
| 2404 | | if (maker.watch or maker.web_server != null) return; |
| 2467 | if (maker.watch or maker.web_server != null or maker.protocol_server != null) return; |
| 2405 | 2468 | |
| 2406 | 2469 | const code: u8 = code: { |
| 2407 | 2470 | if (failure_count == 0) break :code 0; // success |