| author | |
| committer | |
| log | 6b7ce1fa22b301ac06d3bfa0a8938546966f684c |
| tree | 88d5a9c33855fa67da2c0f1ab2ab1f70ab724fd2 |
| parent | b3d162d6bfe82d84d55edd58016347a420732fe2 |
10 files changed, 630 insertions(+), 453 deletions(-)
lib/compiler/Maker.zig+64-53| ... | @@ -419,7 +419,7 @@ pub fn main(init: process.Init.Minimal) !void { | ... | @@ -419,7 +419,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 419 | var top_level_steps: std.StringArrayHashMapUnmanaged(Configuration.Step.Index) = .empty; | 419 | var top_level_steps: std.StringArrayHashMapUnmanaged(Configuration.Step.Index) = .empty; |
| 420 | for (configuration.steps, 0..) |*conf_step, step_index_usize| { | 420 | for (configuration.steps, 0..) |*conf_step, step_index_usize| { |
| 421 | const step_index: Configuration.Step.Index = @enumFromInt(step_index_usize); | 421 | const step_index: Configuration.Step.Index = @enumFromInt(step_index_usize); |
| 422 | const flags: Configuration.Step.Flags = @bitCast(configuration.extra[conf_step.extra_index]); | 422 | const flags = conf_step.flags(&configuration); |
| 423 | if (flags.tag == .top_level) { | 423 | if (flags.tag == .top_level) { |
| 424 | const name = step_index.ptr(&configuration).name.slice(&configuration); | 424 | const name = step_index.ptr(&configuration).name.slice(&configuration); |
| 425 | try top_level_steps.put(arena, name, step_index); | 425 | try top_level_steps.put(arena, name, step_index); |
| ... | @@ -538,7 +538,7 @@ pub fn main(init: process.Init.Minimal) !void { | ... | @@ -538,7 +538,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 538 | var w: Watch = w: { | 538 | var w: Watch = w: { |
| 539 | if (!watch) break :w undefined; | 539 | if (!watch) break :w undefined; |
| 540 | if (!Watch.have_impl) fatal("--watch not yet implemented for {t}", .{builtin.os.tag}); | 540 | if (!Watch.have_impl) fatal("--watch not yet implemented for {t}", .{builtin.os.tag}); |
| 541 | break :w try .init(graph.cache.cwd, &scanned_config.configuration, maker.steps); | 541 | break :w try .init(&maker); |
| 542 | }; | 542 | }; |
| 543 | 543 | ||
| 544 | const now = Io.Clock.Timestamp.now(io, .awake); | 544 | const now = Io.Clock.Timestamp.now(io, .awake); |
| ... | @@ -546,14 +546,10 @@ pub fn main(init: process.Init.Minimal) !void { | ... | @@ -546,14 +546,10 @@ pub fn main(init: process.Init.Minimal) !void { |
| 546 | maker.web_server = if (webui_listen) |listen_address| ws: { | 546 | maker.web_server = if (webui_listen) |listen_address| ws: { |
| 547 | if (builtin.single_threaded) unreachable; // `fatal` above | 547 | if (builtin.single_threaded) unreachable; // `fatal` above |
| 548 | break :ws .init(.{ | 548 | break :ws .init(.{ |
| 549 | .gpa = gpa, | 549 | .maker = &maker, |
| 550 | .graph = &graph, | ||
| 551 | .all_steps = maker.step_stack.keys(), | ||
| 552 | .root_prog_node = main_progress_node, | 550 | .root_prog_node = main_progress_node, |
| 553 | .watch = watch, | ||
| 554 | .listen_address = listen_address, | 551 | .listen_address = listen_address, |
| 555 | .base_timestamp = now, | 552 | .base_timestamp = now, |
| 556 | .configuration = &scanned_config.configuration, | ||
| 557 | }); | 553 | }); |
| 558 | } else null; | 554 | } else null; |
| 559 | 555 | ||
| ... | @@ -564,7 +560,9 @@ pub fn main(init: process.Init.Minimal) !void { | ... | @@ -564,7 +560,9 @@ pub fn main(init: process.Init.Minimal) !void { |
| 564 | rebuild: while (true) : (if (maker.error_style.clearOnUpdate()) { | 560 | rebuild: while (true) : (if (maker.error_style.clearOnUpdate()) { |
| 565 | const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode); | 561 | const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode); |
| 566 | defer io.unlockStderr(); | 562 | defer io.unlockStderr(); |
| 567 | try stderr.file_writer.interface.writeAll("\x1B[2J\x1B[3J\x1B[H"); | 563 | stderr.file_writer.interface.writeAll("\x1B[2J\x1B[3J\x1B[H") catch |err| switch (err) { |
| 564 | error.WriteFailed => return stderr.file_writer.err.?, | ||
| 565 | }; | ||
| 568 | }) { | 566 | }) { |
| 569 | if (maker.web_server) |*ws| ws.startBuild(); | 567 | if (maker.web_server) |*ws| ws.startBuild(); |
| 570 | 568 | ||
| ... | @@ -608,15 +606,15 @@ pub fn main(init: process.Init.Minimal) !void { | ... | @@ -608,15 +606,15 @@ pub fn main(init: process.Init.Minimal) !void { |
| 608 | // recursive dependants. | 606 | // recursive dependants. |
| 609 | var caption_buf: [std.Progress.Node.max_name_len]u8 = undefined; | 607 | var caption_buf: [std.Progress.Node.max_name_len]u8 = undefined; |
| 610 | const caption = std.fmt.bufPrint(&caption_buf, "watching {d} directories, {d} processes", .{ | 608 | const caption = std.fmt.bufPrint(&caption_buf, "watching {d} directories, {d} processes", .{ |
| 611 | w.dir_count, countSubProcesses(maker.steps, maker.step_stack.keys()), | 609 | w.dir_count, countSubProcesses(&maker), |
| 612 | }) catch &caption_buf; | 610 | }) catch &caption_buf; |
| 613 | var debouncing_node = main_progress_node.start(caption, 0); | 611 | var debouncing_node = main_progress_node.start(caption, 0); |
| 614 | var in_debounce = false; | 612 | var in_debounce = false; |
| 615 | while (true) switch (try w.wait(gpa, io, if (in_debounce) .{ .ms = debounce_interval_ms } else .none)) { | 613 | while (true) switch (try w.wait(if (in_debounce) .{ .ms = debounce_interval_ms } else .none)) { |
| 616 | .timeout => { | 614 | .timeout => { |
| 617 | assert(in_debounce); | 615 | assert(in_debounce); |
| 618 | debouncing_node.end(); | 616 | debouncing_node.end(); |
| 619 | markFailedStepsDirty(gpa, maker.steps, maker.step_stack.keys()); | 617 | markFailedStepsDirty(&maker); |
| 620 | continue :rebuild; | 618 | continue :rebuild; |
| 621 | }, | 619 | }, |
| 622 | .dirty => if (!in_debounce) { | 620 | .dirty => if (!in_debounce) { |
| ... | @@ -629,18 +627,20 @@ pub fn main(init: process.Init.Minimal) !void { | ... | @@ -629,18 +627,20 @@ pub fn main(init: process.Init.Minimal) !void { |
| 629 | } | 627 | } |
| 630 | } | 628 | } |
| 631 | 629 | ||
| 632 | fn markFailedStepsDirty(gpa: Allocator, make_steps: []Step, all_steps: []const Configuration.Step.Index) void { | 630 | fn markFailedStepsDirty(maker: *Maker) void { |
| 631 | const all_steps = maker.step_stack.keys(); | ||
| 632 | |||
| 633 | for (all_steps) |step_index| { | 633 | for (all_steps) |step_index| { |
| 634 | const step = &make_steps[@intFromEnum(step_index)]; | 634 | const step = maker.stepByIndex(step_index); |
| 635 | switch (step.state) { | 635 | switch (step.state) { |
| 636 | .dependency_failure, .failure, .skipped => _ = step.invalidateResult(gpa), | 636 | .dependency_failure, .failure, .skipped => _ = maker.invalidateResult(step), |
| 637 | else => continue, | 637 | else => continue, |
| 638 | } | 638 | } |
| 639 | } | 639 | } |
| 640 | // Now that all dirty steps have been found, the remaining steps that | 640 | // Now that all dirty steps have been found, the remaining steps that |
| 641 | // succeeded from last run shall be marked "cached". | 641 | // succeeded from last run shall be marked "cached". |
| 642 | for (all_steps) |step_index| { | 642 | for (all_steps) |step_index| { |
| 643 | const step = &make_steps[@intFromEnum(step_index)]; | 643 | const step = maker.stepByIndex(step_index); |
| 644 | switch (step.state) { | 644 | switch (step.state) { |
| 645 | .success => step.result_cached = true, | 645 | .success => step.result_cached = true, |
| 646 | else => continue, | 646 | else => continue, |
| ... | @@ -648,10 +648,11 @@ fn markFailedStepsDirty(gpa: Allocator, make_steps: []Step, all_steps: []const C | ... | @@ -648,10 +648,11 @@ fn markFailedStepsDirty(gpa: Allocator, make_steps: []Step, all_steps: []const C |
| 648 | } | 648 | } |
| 649 | } | 649 | } |
| 650 | 650 | ||
| 651 | fn countSubProcesses(make_steps: []Step, all_steps: []const Configuration.Step.Index) usize { | 651 | fn countSubProcesses(maker: *Maker) usize { |
| 652 | const all_steps = maker.step_stack.keys(); | ||
| 652 | var count: usize = 0; | 653 | var count: usize = 0; |
| 653 | for (all_steps) |step_index| { | 654 | for (all_steps) |step_index| { |
| 654 | const s = &make_steps[@intFromEnum(step_index)]; | 655 | const s = maker.stepByIndex(step_index); |
| 655 | count += @intFromBool(s.getZigProcess() != null); | 656 | count += @intFromBool(s.getZigProcess() != null); |
| 656 | } | 657 | } |
| 657 | return count; | 658 | return count; |
| ... | @@ -664,7 +665,7 @@ const InstallPaths = struct { | ... | @@ -664,7 +665,7 @@ const InstallPaths = struct { |
| 664 | include: Path, | 665 | include: Path, |
| 665 | }; | 666 | }; |
| 666 | 667 | ||
| 667 | fn stepByIndex(maker: *const Maker, i: Configuration.Step.Index) *Step { | 668 | pub fn stepByIndex(maker: *const Maker, i: Configuration.Step.Index) *Step { |
| 668 | return &maker.steps[@intFromEnum(i)]; | 669 | return &maker.steps[@intFromEnum(i)]; |
| 669 | } | 670 | } |
| 670 | 671 | ||
| ... | @@ -676,7 +677,10 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void { | ... | @@ -676,7 +677,10 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void { |
| 676 | const step_stack = &maker.step_stack; | 677 | const step_stack = &maker.step_stack; |
| 677 | const c = &maker.scanned_config.configuration; | 678 | const c = &maker.scanned_config.configuration; |
| 678 | 679 | ||
| 679 | @memset(maker.steps, .{}); | 680 | for (maker.steps, 0..) |*step, step_index_usize| { |
| 681 | const step_index: Configuration.Step.Index = @enumFromInt(step_index_usize); | ||
| 682 | step.* = .{ .extended = .init(step_index.ptr(c).flags(c).tag) }; | ||
| 683 | } | ||
| 680 | 684 | ||
| 681 | if (step_names.len == 0) { | 685 | if (step_names.len == 0) { |
| 682 | try step_stack.put(gpa, c.default_step, {}); | 686 | try step_stack.put(gpa, c.default_step, {}); |
| ... | @@ -699,7 +703,7 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void { | ... | @@ -699,7 +703,7 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void { |
| 699 | rand.shuffle(Configuration.Step.Index, starting_steps); | 703 | rand.shuffle(Configuration.Step.Index, starting_steps); |
| 700 | 704 | ||
| 701 | for (starting_steps) |s| { | 705 | for (starting_steps) |s| { |
| 702 | try constructGraphAndCheckForDependencyLoop(gpa, c, maker.steps, s, &maker.step_stack, rand); | 706 | try constructGraphAndCheckForDependencyLoop(maker, s, &maker.step_stack, rand); |
| 703 | } | 707 | } |
| 704 | 708 | ||
| 705 | { | 709 | { |
| ... | @@ -847,13 +851,8 @@ fn makeStepNames( | ... | @@ -847,13 +851,8 @@ fn makeStepNames( |
| 847 | } | 851 | } |
| 848 | 852 | ||
| 849 | assert(mode == .limit); | 853 | assert(mode == .limit); |
| 850 | var f = Fuzz.init( | 854 | var f = Fuzz.init(maker, step_stack.keys(), parent_prog_node, mode) catch |err| |
| 851 | gpa, | 855 | fatal("failed to start fuzzer: {t}", .{err}); |
| 852 | io, | ||
| 853 | step_stack.keys(), | ||
| 854 | parent_prog_node, | ||
| 855 | mode, | ||
| 856 | ) catch |err| fatal("failed to start fuzzer: {t}", .{err}); | ||
| 857 | defer f.deinit(); | 856 | defer f.deinit(); |
| 858 | 857 | ||
| 859 | f.start(); | 858 | f.start(); |
| ... | @@ -1048,13 +1047,7 @@ fn makeStep( | ... | @@ -1048,13 +1047,7 @@ fn makeStep( |
| 1048 | 1047 | ||
| 1049 | .success, .skipped => {}, | 1048 | .success, .skipped => {}, |
| 1050 | } | 1049 | } |
| 1051 | } else if (make_step.make(.{ | 1050 | } else if (Step.make(step_index, maker, step_prog_node)) state: { |
| 1052 | .progress_node = step_prog_node, | ||
| 1053 | .watch = maker.watch, | ||
| 1054 | .web_server = if (maker.web_server) |*ws| ws else null, | ||
| 1055 | .unit_test_timeout_ns = maker.unit_test_timeout_ns, | ||
| 1056 | .gpa = gpa, | ||
| 1057 | })) state: { | ||
| 1058 | break :state .success; | 1051 | break :state .success; |
| 1059 | } else |err| switch (err) { | 1052 | } else |err| switch (err) { |
| 1060 | error.MakeFailed => .failure, | 1053 | error.MakeFailed => .failure, |
| ... | @@ -1091,7 +1084,7 @@ fn makeStep( | ... | @@ -1091,7 +1084,7 @@ fn makeStep( |
| 1091 | { | 1084 | { |
| 1092 | const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode); | 1085 | const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode); |
| 1093 | defer io.unlockStderr(); | 1086 | defer io.unlockStderr(); |
| 1094 | printErrorMessages(gpa, c, maker.steps, step_index, .{}, stderr.terminal(), maker.error_style, maker.multiline_errors) catch |err| switch (err) { | 1087 | printErrorMessages(maker, step_index, .{}, stderr.terminal(), maker.error_style, maker.multiline_errors) catch |err| switch (err) { |
| 1095 | error.Canceled => |e| return e, | 1088 | error.Canceled => |e| return e, |
| 1096 | error.WriteFailed => switch (stderr.file_writer.err.?) { | 1089 | error.WriteFailed => switch (stderr.file_writer.err.?) { |
| 1097 | error.Canceled => |e| return e, | 1090 | error.Canceled => |e| return e, |
| ... | @@ -1136,7 +1129,7 @@ fn makeStep( | ... | @@ -1136,7 +1129,7 @@ fn makeStep( |
| 1136 | } | 1129 | } |
| 1137 | 1130 | ||
| 1138 | fn printTreeStep( | 1131 | fn printTreeStep( |
| 1139 | maker: *const Maker, | 1132 | maker: *Maker, |
| 1140 | step_index: Configuration.Step.Index, | 1133 | step_index: Configuration.Step.Index, |
| 1141 | stderr: Io.Terminal, | 1134 | stderr: Io.Terminal, |
| 1142 | parent_node: *PrintNode, | 1135 | parent_node: *PrintNode, |
| ... | @@ -1211,7 +1204,7 @@ fn printTreeStep( | ... | @@ -1211,7 +1204,7 @@ fn printTreeStep( |
| 1211 | } | 1204 | } |
| 1212 | } | 1205 | } |
| 1213 | 1206 | ||
| 1214 | fn printStepStatus(maker: *const Maker, step_index: Configuration.Step.Index, stderr: Io.Terminal) !void { | 1207 | fn printStepStatus(maker: *Maker, step_index: Configuration.Step.Index, stderr: Io.Terminal) !void { |
| 1215 | const s = maker.stepByIndex(step_index); | 1208 | const s = maker.stepByIndex(step_index); |
| 1216 | const writer = stderr.writer; | 1209 | const writer = stderr.writer; |
| 1217 | switch (s.state) { | 1210 | switch (s.state) { |
| ... | @@ -1293,20 +1286,20 @@ fn printStepStatus(maker: *const Maker, step_index: Configuration.Step.Index, st | ... | @@ -1293,20 +1286,20 @@ fn printStepStatus(maker: *const Maker, step_index: Configuration.Step.Index, st |
| 1293 | try stderr.setColor(.reset); | 1286 | try stderr.setColor(.reset); |
| 1294 | }, | 1287 | }, |
| 1295 | .failure => { | 1288 | .failure => { |
| 1296 | try printStepFailure(maker.steps, step_index, stderr, false); | 1289 | try printStepFailure(maker, step_index, stderr, false); |
| 1297 | try stderr.setColor(.reset); | 1290 | try stderr.setColor(.reset); |
| 1298 | }, | 1291 | }, |
| 1299 | } | 1292 | } |
| 1300 | } | 1293 | } |
| 1301 | 1294 | ||
| 1302 | fn printStepFailure( | 1295 | fn printStepFailure( |
| 1303 | make_steps: []Step, | 1296 | maker: *Maker, |
| 1304 | step_index: Configuration.Step.Index, | 1297 | step_index: Configuration.Step.Index, |
| 1305 | stderr: Io.Terminal, | 1298 | stderr: Io.Terminal, |
| 1306 | dim: bool, | 1299 | dim: bool, |
| 1307 | ) !void { | 1300 | ) !void { |
| 1308 | const w = stderr.writer; | 1301 | const w = stderr.writer; |
| 1309 | const s = &make_steps[@intFromEnum(step_index)]; | 1302 | const s = maker.stepByIndex(step_index); |
| 1310 | if (s.result_error_bundle.errorMessageCount() > 0) { | 1303 | if (s.result_error_bundle.errorMessageCount() > 0) { |
| 1311 | try stderr.setColor(.red); | 1304 | try stderr.setColor(.red); |
| 1312 | try w.print(" {d} errors\n", .{ | 1305 | try w.print(" {d} errors\n", .{ |
| ... | @@ -1428,14 +1421,14 @@ fn printChildNodePrefix(stderr: Io.Terminal) !void { | ... | @@ -1428,14 +1421,14 @@ fn printChildNodePrefix(stderr: Io.Terminal) !void { |
| 1428 | /// when it finishes executing in `makeStep`, it spawns next steps to run in | 1421 | /// when it finishes executing in `makeStep`, it spawns next steps to run in |
| 1429 | /// random order | 1422 | /// random order |
| 1430 | fn constructGraphAndCheckForDependencyLoop( | 1423 | fn constructGraphAndCheckForDependencyLoop( |
| 1431 | gpa: Allocator, | 1424 | maker: *Maker, |
| 1432 | c: *const Configuration, | ||
| 1433 | steps: []Step, | ||
| 1434 | step_index: Configuration.Step.Index, | 1425 | step_index: Configuration.Step.Index, |
| 1435 | step_stack: *std.AutoArrayHashMapUnmanaged(Configuration.Step.Index, void), | 1426 | step_stack: *std.AutoArrayHashMapUnmanaged(Configuration.Step.Index, void), |
| 1436 | rand: std.Random, | 1427 | rand: std.Random, |
| 1437 | ) error{ DependencyLoopDetected, OutOfMemory }!void { | 1428 | ) error{ DependencyLoopDetected, OutOfMemory }!void { |
| 1438 | const make_step: *Step = &steps[@intFromEnum(step_index)]; | 1429 | const c = &maker.scanned_config.configuration; |
| 1430 | const gpa = maker.gpa; | ||
| 1431 | const make_step = maker.stepByIndex(step_index); | ||
| 1439 | switch (make_step.state) { | 1432 | switch (make_step.state) { |
| 1440 | .precheck_started => { | 1433 | .precheck_started => { |
| 1441 | log.err("dependency loop detected: {s}", .{step_index.ptr(c).name.slice(c)}); | 1434 | log.err("dependency loop detected: {s}", .{step_index.ptr(c).name.slice(c)}); |
| ... | @@ -1456,10 +1449,10 @@ fn constructGraphAndCheckForDependencyLoop( | ... | @@ -1456,10 +1449,10 @@ fn constructGraphAndCheckForDependencyLoop( |
| 1456 | rand.shuffle(Configuration.Step.Index, deps); | 1449 | rand.shuffle(Configuration.Step.Index, deps); |
| 1457 | 1450 | ||
| 1458 | for (deps) |dep| { | 1451 | for (deps) |dep| { |
| 1459 | const dep_step: *Step = &steps[@intFromEnum(dep)]; | 1452 | const dep_step = maker.stepByIndex(dep); |
| 1460 | try step_stack.put(gpa, dep, {}); | 1453 | try step_stack.put(gpa, dep, {}); |
| 1461 | try dep_step.dependants.append(gpa, step_index); | 1454 | try dep_step.dependants.append(gpa, step_index); |
| 1462 | constructGraphAndCheckForDependencyLoop(gpa, c, steps, dep, step_stack, rand) catch |err| switch (err) { | 1455 | constructGraphAndCheckForDependencyLoop(maker, dep, step_stack, rand) catch |err| switch (err) { |
| 1463 | error.DependencyLoopDetected => { | 1456 | error.DependencyLoopDetected => { |
| 1464 | log.info("needed by: {s}", .{step_index.ptr(c).name.slice(c)}); | 1457 | log.info("needed by: {s}", .{step_index.ptr(c).name.slice(c)}); |
| 1465 | return err; | 1458 | return err; |
| ... | @@ -1482,16 +1475,34 @@ fn constructGraphAndCheckForDependencyLoop( | ... | @@ -1482,16 +1475,34 @@ fn constructGraphAndCheckForDependencyLoop( |
| 1482 | } | 1475 | } |
| 1483 | } | 1476 | } |
| 1484 | 1477 | ||
| 1478 | /// When file watching, prepares the step for being re-evaluated. Returns | ||
| 1479 | /// `true` if the step was newly invalidated, `false` if it was already | ||
| 1480 | /// invalidated. | ||
| 1481 | pub fn invalidateResult(maker: *Maker, step: *Step) bool { | ||
| 1482 | if (step.state == .precheck_done) return false; | ||
| 1483 | const gpa = maker.gpa; | ||
| 1484 | assert(step.pending_deps == 0); | ||
| 1485 | step.state = .precheck_done; | ||
| 1486 | step.reset(gpa); | ||
| 1487 | for (step.dependants.items) |dependant_index| { | ||
| 1488 | const dependant = maker.stepByIndex(dependant_index); | ||
| 1489 | _ = invalidateResult(maker, dependant); | ||
| 1490 | dependant.pending_deps += 1; | ||
| 1491 | } | ||
| 1492 | return true; | ||
| 1493 | } | ||
| 1494 | |||
| 1485 | pub fn printErrorMessages( | 1495 | pub fn printErrorMessages( |
| 1486 | gpa: Allocator, | 1496 | maker: *Maker, |
| 1487 | c: *const Configuration, | ||
| 1488 | make_steps: []Step, | ||
| 1489 | failing_step_index: Configuration.Step.Index, | 1497 | failing_step_index: Configuration.Step.Index, |
| 1490 | options: std.zig.ErrorBundle.RenderOptions, | 1498 | options: std.zig.ErrorBundle.RenderOptions, |
| 1491 | stderr: Io.Terminal, | 1499 | stderr: Io.Terminal, |
| 1492 | error_style: ErrorStyle, | 1500 | error_style: ErrorStyle, |
| 1493 | multiline_errors: MultilineErrors, | 1501 | multiline_errors: MultilineErrors, |
| 1494 | ) !void { | 1502 | ) !void { |
| 1503 | const c = &maker.scanned_config.configuration; | ||
| 1504 | const gpa = maker.gpa; | ||
| 1505 | log.err("TODO also report if result_oom flag is set", .{}); | ||
| 1495 | const writer = stderr.writer; | 1506 | const writer = stderr.writer; |
| 1496 | if (error_style.verboseContext()) { | 1507 | if (error_style.verboseContext()) { |
| 1497 | // Provide context for where these error messages are coming from by | 1508 | // Provide context for where these error messages are coming from by |
| ... | @@ -1500,7 +1511,7 @@ pub fn printErrorMessages( | ... | @@ -1500,7 +1511,7 @@ pub fn printErrorMessages( |
| 1500 | defer step_stack.deinit(gpa); | 1511 | defer step_stack.deinit(gpa); |
| 1501 | try step_stack.append(gpa, failing_step_index); | 1512 | try step_stack.append(gpa, failing_step_index); |
| 1502 | while (true) { | 1513 | while (true) { |
| 1503 | const last_step = &make_steps[@intFromEnum(step_stack.items[step_stack.items.len - 1])]; | 1514 | const last_step = maker.stepByIndex(step_stack.items[step_stack.items.len - 1]); |
| 1504 | if (last_step.dependants.items.len == 0) break; | 1515 | if (last_step.dependants.items.len == 0) break; |
| 1505 | try step_stack.append(gpa, last_step.dependants.items[0]); | 1516 | try step_stack.append(gpa, last_step.dependants.items[0]); |
| 1506 | } | 1517 | } |
| ... | @@ -1517,7 +1528,7 @@ pub fn printErrorMessages( | ... | @@ -1517,7 +1528,7 @@ pub fn printErrorMessages( |
| 1517 | try writer.writeAll(step_index.ptr(c).name.slice(c)); | 1528 | try writer.writeAll(step_index.ptr(c).name.slice(c)); |
| 1518 | 1529 | ||
| 1519 | if (step_index == failing_step_index) { | 1530 | if (step_index == failing_step_index) { |
| 1520 | try printStepFailure(make_steps, step_index, stderr, true); | 1531 | try printStepFailure(maker, step_index, stderr, true); |
| 1521 | } else { | 1532 | } else { |
| 1522 | try writer.writeAll("\n"); | 1533 | try writer.writeAll("\n"); |
| 1523 | } | 1534 | } |
| ... | @@ -1527,11 +1538,11 @@ pub fn printErrorMessages( | ... | @@ -1527,11 +1538,11 @@ pub fn printErrorMessages( |
| 1527 | // Just print the failing step itself. | 1538 | // Just print the failing step itself. |
| 1528 | try stderr.setColor(.dim); | 1539 | try stderr.setColor(.dim); |
| 1529 | try writer.writeAll(failing_step_index.ptr(c).name.slice(c)); | 1540 | try writer.writeAll(failing_step_index.ptr(c).name.slice(c)); |
| 1530 | try printStepFailure(make_steps, failing_step_index, stderr, true); | 1541 | try printStepFailure(maker, failing_step_index, stderr, true); |
| 1531 | try stderr.setColor(.reset); | 1542 | try stderr.setColor(.reset); |
| 1532 | } | 1543 | } |
| 1533 | 1544 | ||
| 1534 | const failing_step = &make_steps[@intFromEnum(failing_step_index)]; | 1545 | const failing_step = maker.stepByIndex(failing_step_index); |
| 1535 | 1546 | ||
| 1536 | if (failing_step.result_stderr.len > 0) { | 1547 | if (failing_step.result_stderr.len > 0) { |
| 1537 | try writer.writeAll(failing_step.result_stderr); | 1548 | try writer.writeAll(failing_step.result_stderr); |
lib/compiler/Maker/Fuzz.zig+39-19| ... | @@ -15,8 +15,7 @@ const log = std.log; | ... | @@ -15,8 +15,7 @@ const log = std.log; |
| 15 | const Maker = @import("../Maker.zig"); | 15 | const Maker = @import("../Maker.zig"); |
| 16 | const WebServer = @import("WebServer.zig"); | 16 | const WebServer = @import("WebServer.zig"); |
| 17 | 17 | ||
| 18 | gpa: Allocator, | 18 | maker: *Maker, |
| 19 | io: Io, | ||
| 20 | mode: Mode, | 19 | mode: Mode, |
| 21 | 20 | ||
| 22 | /// Allocated into `gpa`. | 21 | /// Allocated into `gpa`. |
| ... | @@ -76,12 +75,15 @@ const CoverageMap = struct { | ... | @@ -76,12 +75,15 @@ const CoverageMap = struct { |
| 76 | }; | 75 | }; |
| 77 | 76 | ||
| 78 | pub fn init( | 77 | pub fn init( |
| 79 | gpa: Allocator, | 78 | maker: *Maker, |
| 80 | io: Io, | ||
| 81 | all_steps: []const Configuration.Step.Index, | 79 | all_steps: []const Configuration.Step.Index, |
| 82 | root_prog_node: std.Progress.Node, | 80 | root_prog_node: std.Progress.Node, |
| 83 | mode: Mode, | 81 | mode: Mode, |
| 84 | ) error{ OutOfMemory, Canceled }!Fuzz { | 82 | ) error{ OutOfMemory, Canceled }!Fuzz { |
| 83 | const graph = maker.graph; | ||
| 84 | const gpa = graph.cache.gpa; | ||
| 85 | const io = graph.io; | ||
| 86 | |||
| 85 | const run_steps: []const Configuration.Step.Index = steps: { | 87 | const run_steps: []const Configuration.Step.Index = steps: { |
| 86 | var steps: std.ArrayList(Configuration.Step.Index) = .empty; | 88 | var steps: std.ArrayList(Configuration.Step.Index) = .empty; |
| 87 | defer steps.deinit(gpa); | 89 | defer steps.deinit(gpa); |
| ... | @@ -115,8 +117,7 @@ pub fn init( | ... | @@ -115,8 +117,7 @@ pub fn init( |
| 115 | } | 117 | } |
| 116 | 118 | ||
| 117 | return .{ | 119 | return .{ |
| 118 | .gpa = gpa, | 120 | .maker = maker, |
| 119 | .io = io, | ||
| 120 | .mode = mode, | 121 | .mode = mode, |
| 121 | .run_steps = run_steps, | 122 | .run_steps = run_steps, |
| 122 | .group = .init, | 123 | .group = .init, |
| ... | @@ -131,7 +132,10 @@ pub fn init( | ... | @@ -131,7 +132,10 @@ pub fn init( |
| 131 | } | 132 | } |
| 132 | 133 | ||
| 133 | pub fn start(fuzz: *Fuzz) void { | 134 | pub fn start(fuzz: *Fuzz) void { |
| 134 | const io = fuzz.io; | 135 | const maker = fuzz.maker; |
| 136 | const graph = maker.graph; | ||
| 137 | const io = graph.io; | ||
| 138 | |||
| 135 | fuzz.prog_node = fuzz.root_prog_node.start("Fuzzing", 0); | 139 | fuzz.prog_node = fuzz.root_prog_node.start("Fuzzing", 0); |
| 136 | 140 | ||
| 137 | if (fuzz.mode == .forever) { | 141 | if (fuzz.mode == .forever) { |
| ... | @@ -149,10 +153,14 @@ pub fn start(fuzz: *Fuzz) void { | ... | @@ -149,10 +153,14 @@ pub fn start(fuzz: *Fuzz) void { |
| 149 | } | 153 | } |
| 150 | 154 | ||
| 151 | pub fn deinit(fuzz: *Fuzz) void { | 155 | pub fn deinit(fuzz: *Fuzz) void { |
| 152 | const io = fuzz.io; | 156 | const maker = fuzz.maker; |
| 157 | const graph = maker.graph; | ||
| 158 | const io = graph.io; | ||
| 159 | const gpa = maker.gpa; | ||
| 160 | |||
| 153 | fuzz.group.cancel(io); | 161 | fuzz.group.cancel(io); |
| 154 | fuzz.prog_node.end(); | 162 | fuzz.prog_node.end(); |
| 155 | fuzz.gpa.free(fuzz.run_steps); | 163 | gpa.free(fuzz.run_steps); |
| 156 | } | 164 | } |
| 157 | 165 | ||
| 158 | fn rebuildTestsWorkerRun(run: Configuration.Step.Index, gpa: Allocator, parent_prog_node: std.Progress.Node) void { | 166 | fn rebuildTestsWorkerRun(run: Configuration.Step.Index, gpa: Allocator, parent_prog_node: std.Progress.Node) void { |
| ... | @@ -215,19 +223,20 @@ fn fuzzWorkerRun(fuzz: *Fuzz, run: Configuration.Step.Index) void { | ... | @@ -215,19 +223,20 @@ fn fuzzWorkerRun(fuzz: *Fuzz, run: Configuration.Step.Index) void { |
| 215 | pub fn serveSourcesTar(fuzz: *Fuzz, req: *std.http.Server.Request) !void { | 223 | pub fn serveSourcesTar(fuzz: *Fuzz, req: *std.http.Server.Request) !void { |
| 216 | if (true) @panic("TODO"); | 224 | if (true) @panic("TODO"); |
| 217 | assert(fuzz.mode == .forever); | 225 | assert(fuzz.mode == .forever); |
| 226 | const gpa = fuzz.maker.gpa; | ||
| 218 | 227 | ||
| 219 | var arena_state: std.heap.ArenaAllocator = .init(fuzz.gpa); | 228 | var arena_state: std.heap.ArenaAllocator = .init(gpa); |
| 220 | defer arena_state.deinit(); | 229 | defer arena_state.deinit(); |
| 221 | const arena = arena_state.allocator(); | 230 | const arena = arena_state.allocator(); |
| 222 | 231 | ||
| 223 | const DedupTable = std.ArrayHashMapUnmanaged(Build.Cache.Path, void, Build.Cache.Path.TableAdapter, false); | 232 | const DedupTable = std.ArrayHashMapUnmanaged(Build.Cache.Path, void, Build.Cache.Path.TableAdapter, false); |
| 224 | var dedup_table: DedupTable = .empty; | 233 | var dedup_table: DedupTable = .empty; |
| 225 | defer dedup_table.deinit(fuzz.gpa); | 234 | defer dedup_table.deinit(gpa); |
| 226 | 235 | ||
| 227 | for (fuzz.run_steps) |run_step| { | 236 | for (fuzz.run_steps) |run_step| { |
| 228 | const compile_inputs = run_step.producer.?.step.inputs.table; | 237 | const compile_inputs = run_step.producer.?.step.inputs.table; |
| 229 | for (compile_inputs.keys(), compile_inputs.values()) |dir_path, *file_list| { | 238 | for (compile_inputs.keys(), compile_inputs.values()) |dir_path, *file_list| { |
| 230 | try dedup_table.ensureUnusedCapacity(fuzz.gpa, file_list.items.len); | 239 | try dedup_table.ensureUnusedCapacity(gpa, file_list.items.len); |
| 231 | for (file_list.items) |sub_path| { | 240 | for (file_list.items) |sub_path| { |
| 232 | if (!std.mem.endsWith(u8, sub_path, ".zig")) continue; | 241 | if (!std.mem.endsWith(u8, sub_path, ".zig")) continue; |
| 233 | const joined_path = try dir_path.join(arena, sub_path); | 242 | const joined_path = try dir_path.join(arena, sub_path); |
| ... | @@ -266,7 +275,9 @@ pub fn sendUpdate( | ... | @@ -266,7 +275,9 @@ pub fn sendUpdate( |
| 266 | socket: *std.http.Server.WebSocket, | 275 | socket: *std.http.Server.WebSocket, |
| 267 | prev: *Previous, | 276 | prev: *Previous, |
| 268 | ) !void { | 277 | ) !void { |
| 269 | const io = fuzz.io; | 278 | const maker = fuzz.maker; |
| 279 | const graph = maker.graph; | ||
| 280 | const io = graph.io; | ||
| 270 | 281 | ||
| 271 | try fuzz.coverage_mutex.lock(io); | 282 | try fuzz.coverage_mutex.lock(io); |
| 272 | defer fuzz.coverage_mutex.unlock(io); | 283 | defer fuzz.coverage_mutex.unlock(io); |
| ... | @@ -337,7 +348,9 @@ fn coverageRun(fuzz: *Fuzz) void { | ... | @@ -337,7 +348,9 @@ fn coverageRun(fuzz: *Fuzz) void { |
| 337 | } | 348 | } |
| 338 | 349 | ||
| 339 | fn coverageRunCancelable(fuzz: *Fuzz) Io.Cancelable!void { | 350 | fn coverageRunCancelable(fuzz: *Fuzz) Io.Cancelable!void { |
| 340 | const io = fuzz.io; | 351 | const maker = fuzz.maker; |
| 352 | const graph = maker.graph; | ||
| 353 | const io = graph.io; | ||
| 341 | 354 | ||
| 342 | try fuzz.queue_mutex.lock(io); | 355 | try fuzz.queue_mutex.lock(io); |
| 343 | defer fuzz.queue_mutex.unlock(io); | 356 | defer fuzz.queue_mutex.unlock(io); |
| ... | @@ -363,8 +376,10 @@ fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage | ... | @@ -363,8 +376,10 @@ fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage |
| 363 | if (true) @panic("TODO"); | 376 | if (true) @panic("TODO"); |
| 364 | assert(fuzz.mode == .forever); | 377 | assert(fuzz.mode == .forever); |
| 365 | const ws = fuzz.mode.forever.ws; | 378 | const ws = fuzz.mode.forever.ws; |
| 366 | const gpa = fuzz.gpa; | 379 | const maker = fuzz.maker; |
| 367 | const io = fuzz.io; | 380 | const graph = maker.graph; |
| 381 | const io = graph.io; | ||
| 382 | const gpa = maker.gpa; | ||
| 368 | 383 | ||
| 369 | try fuzz.coverage_mutex.lock(io); | 384 | try fuzz.coverage_mutex.lock(io); |
| 370 | defer fuzz.coverage_mutex.unlock(io); | 385 | defer fuzz.coverage_mutex.unlock(io); |
| ... | @@ -470,7 +485,10 @@ fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage | ... | @@ -470,7 +485,10 @@ fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage |
| 470 | } | 485 | } |
| 471 | 486 | ||
| 472 | fn addEntryPoint(fuzz: *Fuzz, coverage_id: u64, addr: u64) error{ AlreadyReported, OutOfMemory, Canceled }!void { | 487 | fn addEntryPoint(fuzz: *Fuzz, coverage_id: u64, addr: u64) error{ AlreadyReported, OutOfMemory, Canceled }!void { |
| 473 | const io = fuzz.io; | 488 | const maker = fuzz.maker; |
| 489 | const graph = maker.graph; | ||
| 490 | const io = graph.io; | ||
| 491 | const gpa = maker.gpa; | ||
| 474 | 492 | ||
| 475 | try fuzz.coverage_mutex.lock(io); | 493 | try fuzz.coverage_mutex.lock(io); |
| 476 | defer fuzz.coverage_mutex.unlock(io); | 494 | defer fuzz.coverage_mutex.unlock(io); |
| ... | @@ -516,13 +534,15 @@ fn addEntryPoint(fuzz: *Fuzz, coverage_id: u64, addr: u64) error{ AlreadyReporte | ... | @@ -516,13 +534,15 @@ fn addEntryPoint(fuzz: *Fuzz, coverage_id: u64, addr: u64) error{ AlreadyReporte |
| 516 | }); | 534 | }); |
| 517 | } | 535 | } |
| 518 | } | 536 | } |
| 519 | try coverage_map.entry_points.append(fuzz.gpa, @intCast(index)); | 537 | try coverage_map.entry_points.append(gpa, @intCast(index)); |
| 520 | } | 538 | } |
| 521 | 539 | ||
| 522 | pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void { | 540 | pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void { |
| 523 | if (true) @panic("TODO"); | 541 | if (true) @panic("TODO"); |
| 524 | assert(fuzz.mode == .limit); | 542 | assert(fuzz.mode == .limit); |
| 525 | const io = fuzz.io; | 543 | const maker = fuzz.maker; |
| 544 | const graph = maker.graph; | ||
| 545 | const io = graph.io; | ||
| 526 | 546 | ||
| 527 | try fuzz.group.await(io); | 547 | try fuzz.group.await(io); |
| 528 | fuzz.group = .init; | 548 | fuzz.group = .init; |
lib/compiler/Maker/Step.zig+124-49| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | //! The state that maker needs in order to process a step. | 1 | //! The *mutable* state that `Maker` needs in order to process one node from |
| 2 | //! the build graph. | ||
| 2 | const Step = @This(); | 3 | const Step = @This(); |
| 3 | 4 | ||
| 4 | const builtin = @import("builtin"); | 5 | const builtin = @import("builtin"); |
| ... | @@ -14,14 +15,20 @@ const Configuration = std.Build.Configuration; | ... | @@ -14,14 +15,20 @@ const Configuration = std.Build.Configuration; |
| 14 | const assert = std.debug.assert; | 15 | const assert = std.debug.assert; |
| 15 | 16 | ||
| 16 | const WebServer = @import("WebServer.zig"); | 17 | const WebServer = @import("WebServer.zig"); |
| 18 | const Maker = @import("../Maker.zig"); | ||
| 17 | 19 | ||
| 18 | pub const Compile = void; // @import("Step/Compile.zig"); | 20 | const Compile = @import("Step/Compile.zig"); |
| 19 | pub const Run = void; // @import("Step/Run.zig"); | 21 | const Run = @import("Step/Run.zig"); |
| 20 | 22 | ||
| 21 | /// Avoid false sharing. | 23 | /// Avoid false sharing. |
| 22 | _: void align(std.atomic.cache_line) = {}, | 24 | _: void align(std.atomic.cache_line) = {}, |
| 23 | 25 | ||
| 26 | /// Extra data for specific types of steps. | ||
| 27 | extended: Extended, | ||
| 28 | |||
| 29 | /// This field is atomically accessed multi-threaded. | ||
| 24 | state: State = .precheck_unstarted, | 30 | state: State = .precheck_unstarted, |
| 31 | |||
| 25 | dependants: std.ArrayList(Configuration.Step.Index) = .empty, | 32 | dependants: std.ArrayList(Configuration.Step.Index) = .empty, |
| 26 | /// Collects the set of files that retrigger this step to run. | 33 | /// Collects the set of files that retrigger this step to run. |
| 27 | /// | 34 | /// |
| ... | @@ -38,6 +45,8 @@ result_error_msgs: std.ArrayList([]const u8) = .empty, | ... | @@ -38,6 +45,8 @@ result_error_msgs: std.ArrayList([]const u8) = .empty, |
| 38 | result_error_bundle: std.zig.ErrorBundle = .empty, | 45 | result_error_bundle: std.zig.ErrorBundle = .empty, |
| 39 | result_stderr: []const u8 = "", | 46 | result_stderr: []const u8 = "", |
| 40 | result_cached: bool = false, | 47 | result_cached: bool = false, |
| 48 | /// Indicates error information is missing due to allocation failure. | ||
| 49 | result_oom: bool = false, | ||
| 41 | result_duration_ns: ?u64 = null, | 50 | result_duration_ns: ?u64 = null, |
| 42 | /// 0 means unavailable or not reported. | 51 | /// 0 means unavailable or not reported. |
| 43 | result_peak_rss: usize = 0, | 52 | result_peak_rss: usize = 0, |
| ... | @@ -46,6 +55,70 @@ result_peak_rss: usize = 0, | ... | @@ -46,6 +55,70 @@ result_peak_rss: usize = 0, |
| 46 | result_failed_command: ?[]const u8 = null, | 55 | result_failed_command: ?[]const u8 = null, |
| 47 | test_results: TestResults = .{}, | 56 | test_results: TestResults = .{}, |
| 48 | 57 | ||
| 58 | comptime { | ||
| 59 | // Common cache line size is 128. This check prevents accidentally crossing | ||
| 60 | // an additional cache line. In the future it might be nice to try to fit | ||
| 61 | // this struct in 128 bytes or less. | ||
| 62 | assert(@sizeOf(@This()) <= 128 * 3); | ||
| 63 | } | ||
| 64 | |||
| 65 | pub const Extended = union(enum) { | ||
| 66 | check_file: Todo, | ||
| 67 | check_object: Todo, | ||
| 68 | compile: Compile, | ||
| 69 | config_header: Todo, | ||
| 70 | fail: Todo, | ||
| 71 | fmt: Todo, | ||
| 72 | install_artifact: Todo, | ||
| 73 | install_dir: Todo, | ||
| 74 | install_file: Todo, | ||
| 75 | objcopy: Todo, | ||
| 76 | options: Todo, | ||
| 77 | remove_dir: Todo, | ||
| 78 | run: Run, | ||
| 79 | top_level: Todo, | ||
| 80 | translate_c: Todo, | ||
| 81 | update_source_files: Todo, | ||
| 82 | write_file: Todo, | ||
| 83 | |||
| 84 | pub fn init(tag: Configuration.Step.Tag) Extended { | ||
| 85 | return switch (tag) { | ||
| 86 | .check_file => .{ .check_file = .{} }, | ||
| 87 | .check_object => .{ .check_object = .{} }, | ||
| 88 | .compile => .{ .compile = .{} }, | ||
| 89 | .config_header => .{ .config_header = .{} }, | ||
| 90 | .fail => .{ .fail = .{} }, | ||
| 91 | .fmt => .{ .fmt = .{} }, | ||
| 92 | .install_artifact => .{ .install_artifact = .{} }, | ||
| 93 | .install_dir => .{ .install_dir = .{} }, | ||
| 94 | .install_file => .{ .install_file = .{} }, | ||
| 95 | .objcopy => .{ .objcopy = .{} }, | ||
| 96 | .options => .{ .options = .{} }, | ||
| 97 | .remove_dir => .{ .remove_dir = .{} }, | ||
| 98 | .run => .{ .run = .{} }, | ||
| 99 | .top_level => .{ .top_level = .{} }, | ||
| 100 | .translate_c => .{ .translate_c = .{} }, | ||
| 101 | .update_source_files => .{ .update_source_files = .{} }, | ||
| 102 | .write_file => .{ .write_file = .{} }, | ||
| 103 | }; | ||
| 104 | } | ||
| 105 | |||
| 106 | pub const Todo = struct { | ||
| 107 | pub fn make( | ||
| 108 | todo: *Todo, | ||
| 109 | step_index: Configuration.Step.Index, | ||
| 110 | maker: *Maker, | ||
| 111 | progress_node: std.Progress.Node, | ||
| 112 | ) Step.ExtendedMakeError!void { | ||
| 113 | _ = todo; | ||
| 114 | _ = step_index; | ||
| 115 | _ = maker; | ||
| 116 | _ = progress_node; | ||
| 117 | @panic("TODO implement another step type"); | ||
| 118 | } | ||
| 119 | }; | ||
| 120 | }; | ||
| 121 | |||
| 49 | pub const State = enum { | 122 | pub const State = enum { |
| 50 | precheck_unstarted, | 123 | precheck_unstarted, |
| 51 | precheck_started, | 124 | precheck_started, |
| ... | @@ -128,43 +201,51 @@ pub const TestResults = struct { | ... | @@ -128,43 +201,51 @@ pub const TestResults = struct { |
| 128 | } | 201 | } |
| 129 | }; | 202 | }; |
| 130 | 203 | ||
| 131 | pub const MakeOptions = struct { | 204 | pub const MakeError = error{ |
| 132 | progress_node: std.Progress.Node, | 205 | /// Indicates the error is already reported. |
| 133 | watch: bool, | 206 | MakeFailed, |
| 134 | web_server: ?*WebServer, | 207 | MakeSkipped, |
| 135 | /// If set, this is a timeout to enforce on all individual unit tests, in nanoseconds. | ||
| 136 | unit_test_timeout_ns: ?u64, | ||
| 137 | /// Not to be confused with `Build.allocator`, which is an alias of `Build.graph.arena`. | ||
| 138 | gpa: Allocator, | ||
| 139 | }; | 208 | }; |
| 140 | 209 | ||
| 141 | pub const MakeFn = *const fn (step: *Step, options: MakeOptions) anyerror!void; | 210 | pub const ExtendedMakeError = MakeError || Allocator.Error; |
| 142 | 211 | ||
| 143 | /// If the Step's `make` function reports `error.MakeFailed`, it indicates they | 212 | pub fn make( |
| 144 | /// have already reported the error. Otherwise, we add a simple error report | 213 | step_index: Configuration.Step.Index, |
| 145 | /// here. | 214 | maker: *Maker, |
| 146 | pub fn make(s: *Step, options: MakeOptions) error{ MakeFailed, MakeSkipped }!void { | 215 | progress_node: std.Progress.Node, |
| 147 | if (true) @panic("TODO Step.make"); | 216 | ) MakeError!void { |
| 148 | const arena = s.owner.allocator; | 217 | const graph = maker.graph; |
| 149 | const graph = s.owner.graph; | 218 | const process_arena = graph.arena; // TODO don't leak into the process arena |
| 150 | const io = graph.io; | 219 | const io = graph.io; |
| 220 | const c = &maker.scanned_config.configuration; | ||
| 221 | const conf_step = step_index.ptr(c); | ||
| 222 | const s = maker.stepByIndex(step_index); | ||
| 151 | 223 | ||
| 152 | var start_ts: ?Io.Timestamp = t: { | 224 | var start_ts: ?Io.Timestamp = t: { |
| 153 | if (!graph.time_report) break :t null; | 225 | if (!graph.time_report) break :t null; |
| 154 | if (s.id == .compile) break :t null; | 226 | const flags = conf_step.flags(c); |
| 155 | if (s.id == .run and s.cast(Run).?.stdio == .zig_test) break :t null; | 227 | switch (flags.tag) { |
| 228 | .compile => break :t null, | ||
| 229 | .run => { | ||
| 230 | const run_flags: Configuration.Step.Run.Flags = @bitCast(flags); | ||
| 231 | if (run_flags.stdio == .zig_test) break :t null; | ||
| 232 | }, | ||
| 233 | else => {}, | ||
| 234 | } | ||
| 156 | break :t Io.Clock.awake.now(io); | 235 | break :t Io.Clock.awake.now(io); |
| 157 | }; | 236 | }; |
| 158 | const make_result = s.makeFn(s, options); | 237 | const make_result = switch (s.extended) { |
| 238 | inline else => |*extended| extended.make(step_index, maker, progress_node), | ||
| 239 | }; | ||
| 159 | if (start_ts) |*ts| { | 240 | if (start_ts) |*ts| { |
| 160 | const duration = ts.untilNow(io, .awake); | 241 | const duration = ts.untilNow(io, .awake); |
| 161 | options.web_server.?.updateTimeReportGeneric(s, duration); | 242 | maker.web_server.?.updateTimeReportGeneric(step_index, duration); |
| 162 | } | 243 | } |
| 163 | 244 | ||
| 164 | make_result catch |err| switch (err) { | 245 | make_result catch |err| switch (err) { |
| 165 | error.MakeFailed, error.MakeSkipped => |e| return e, | 246 | error.MakeFailed, error.MakeSkipped => |e| return e, |
| 166 | else => { | 247 | error.OutOfMemory => { |
| 167 | s.result_error_msgs.append(arena, @errorName(err)) catch @panic("OOM"); | 248 | s.result_oom = true; |
| 168 | return error.MakeFailed; | 249 | return error.MakeFailed; |
| 169 | }, | 250 | }, |
| 170 | }; | 251 | }; |
| ... | @@ -173,30 +254,19 @@ pub fn make(s: *Step, options: MakeOptions) error{ MakeFailed, MakeSkipped }!voi | ... | @@ -173,30 +254,19 @@ pub fn make(s: *Step, options: MakeOptions) error{ MakeFailed, MakeSkipped }!voi |
| 173 | return error.MakeFailed; | 254 | return error.MakeFailed; |
| 174 | } | 255 | } |
| 175 | 256 | ||
| 176 | if (s.max_rss != 0 and s.result_peak_rss > s.max_rss) { | 257 | const max_rss = conf_step.max_rss.toBytes(); |
| 177 | const msg = std.fmt.allocPrint(arena, "memory usage peaked at {0B:.2} ({0d} bytes), exceeding the declared upper bound of {1B:.2} ({1d} bytes)", .{ | 258 | if (max_rss != 0 and s.result_peak_rss > max_rss) { |
| 178 | s.result_peak_rss, s.max_rss, | 259 | if (std.fmt.allocPrint( |
| 179 | }) catch @panic("OOM"); | 260 | process_arena, |
| 180 | s.result_error_msgs.append(arena, msg) catch @panic("OOM"); | 261 | "memory usage peaked at {0B:.2} ({0d} bytes), exceeding the declared upper bound of {1B:.2} ({1d} bytes)", |
| 262 | .{ s.result_peak_rss, max_rss }, | ||
| 263 | )) |msg| { | ||
| 264 | s.oomWrap(s.result_error_msgs.append(process_arena, msg)); | ||
| 265 | } else |_| s.result_oom = true; | ||
| 181 | } | 266 | } |
| 182 | } | 267 | } |
| 183 | 268 | ||
| 184 | /// Implementation detail of file watching. Prepares the step for being re-evaluated. | 269 | /// Prepares the step for being re-evaluated. |
| 185 | /// Returns `true` if the step was newly invalidated, `false` if it was already invalidated. | ||
| 186 | pub fn invalidateResult(step: *Step, gpa: Allocator) bool { | ||
| 187 | if (true) @panic("TODO Step.invalidateResult"); | ||
| 188 | if (step.state == .precheck_done) return false; | ||
| 189 | assert(step.pending_deps == 0); | ||
| 190 | step.state = .precheck_done; | ||
| 191 | step.reset(gpa); | ||
| 192 | for (step.dependants.items) |dependant| { | ||
| 193 | _ = dependant.invalidateResult(gpa); | ||
| 194 | dependant.pending_deps += 1; | ||
| 195 | } | ||
| 196 | return true; | ||
| 197 | } | ||
| 198 | |||
| 199 | /// Implementation detail of file watching and forced rebuilds. Prepares the step for being re-evaluated. | ||
| 200 | pub fn reset(step: *Step, gpa: Allocator) void { | 270 | pub fn reset(step: *Step, gpa: Allocator) void { |
| 201 | assert(step.state == .precheck_done); | 271 | assert(step.state == .precheck_done); |
| 202 | 272 | ||
| ... | @@ -547,9 +617,8 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*WebSer | ... | @@ -547,9 +617,8 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*WebSer |
| 547 | } | 617 | } |
| 548 | 618 | ||
| 549 | pub fn getZigProcess(s: *Step) ?*ZigProcess { | 619 | pub fn getZigProcess(s: *Step) ?*ZigProcess { |
| 550 | if (true) @panic("TODO getZigProcess"); | 620 | return switch (s.extended) { |
| 551 | return switch (s.id) { | 621 | .compile => |*compile| compile.zig_process, |
| 552 | .compile => s.cast(Compile).?.zig_process, | ||
| 553 | else => null, | 622 | else => null, |
| 554 | }; | 623 | }; |
| 555 | } | 624 | } |
| ... | @@ -838,3 +907,9 @@ pub fn allocPrintCmd( | ... | @@ -838,3 +907,9 @@ pub fn allocPrintCmd( |
| 838 | } | 907 | } |
| 839 | return aw.toOwnedSlice(); | 908 | return aw.toOwnedSlice(); |
| 840 | } | 909 | } |
| 910 | |||
| 911 | fn oomWrap(s: *Step, result: error{OutOfMemory}!void) void { | ||
| 912 | result catch { | ||
| 913 | s.result_oom = true; | ||
| 914 | }; | ||
| 915 | } |
lib/compiler/Maker/Step/Compile.zig+123-42| ... | @@ -1,19 +1,40 @@ | ... | @@ -1,19 +1,40 @@ |
| 1 | const Compile = @This(); | ||
| 2 | |||
| 3 | const std = @import("std"); | ||
| 4 | const Allocator = std.mem.Allocator; | ||
| 5 | const Configuration = std.Build.Configuration; | ||
| 6 | const Dir = std.Io.Dir; | ||
| 7 | const Path = std.Build.Cache.Path; | ||
| 8 | const Module = std.Build.Configuration.Module; | ||
| 9 | const Io = std.Io; | ||
| 10 | const Sha256 = std.crypto.hash.sha2.Sha256; | ||
| 11 | const assert = std.debug.assert; | ||
| 12 | const mem = std.mem; | ||
| 13 | |||
| 14 | const Step = @import("../Step.zig"); | ||
| 15 | const Maker = @import("../../Maker.zig"); | ||
| 16 | |||
| 1 | /// Populated during the make phase when there is a long-lived compiler process. | 17 | /// Populated during the make phase when there is a long-lived compiler process. |
| 2 | /// Managed by the build runner, not user build script. | 18 | /// Managed by the build runner, not user build script. |
| 3 | zig_process: ?*Step.ZigProcess, | 19 | zig_process: ?*Step.ZigProcess = null, |
| 4 | 20 | ||
| 5 | fn make(step: *Step, options: Step.MakeOptions) !void { | 21 | pub fn make( |
| 6 | const b = step.owner; | 22 | compile: *Compile, |
| 7 | const compile: *Compile = @fieldParentPtr("step", step); | 23 | step_index: Configuration.Step.Index, |
| 8 | 24 | maker: *Maker, | |
| 9 | const zig_args = try getZigArgs(compile, false); | 25 | progress_node: std.Progress.Node, |
| 26 | ) Step.ExtendedMakeError!void { | ||
| 27 | if (true) @panic("TODO implement compile.make()"); | ||
| 28 | const graph = maker.graph; | ||
| 29 | const step = maker.stepByIndex(step_index); | ||
| 30 | const zig_args = try getZigArgs(compile, maker, false); | ||
| 31 | const process_arena = graph.arena; // TODO don't leak into the process_arena | ||
| 10 | 32 | ||
| 11 | const maybe_output_dir = step.evalZigProcess( | 33 | const maybe_output_dir = step.evalZigProcess( |
| 12 | zig_args, | 34 | zig_args, |
| 13 | options.progress_node, | 35 | progress_node, |
| 14 | (b.graph.incremental == true) and (options.watch or options.web_server != null), | 36 | (graph.incremental == true) and (maker.watch or maker.web_server != null), |
| 15 | options.web_server, | 37 | maker, |
| 16 | options.gpa, | ||
| 17 | ) catch |err| switch (err) { | 38 | ) catch |err| switch (err) { |
| 18 | error.NeedCompileErrorCheck => { | 39 | error.NeedCompileErrorCheck => { |
| 19 | assert(compile.expect_errors != null); | 40 | assert(compile.expect_errors != null); |
| ... | @@ -26,7 +47,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -26,7 +47,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 26 | // Update generated files | 47 | // Update generated files |
| 27 | if (maybe_output_dir) |output_dir| { | 48 | if (maybe_output_dir) |output_dir| { |
| 28 | if (compile.emit_directory) |lp| { | 49 | if (compile.emit_directory) |lp| { |
| 29 | lp.path = b.fmt("{f}", .{output_dir}); | 50 | lp.path = try std.fmt.allocPrint(process_arena, "{f}", .{output_dir}); |
| 30 | } | 51 | } |
| 31 | 52 | ||
| 32 | // zig fmt: off | 53 | // zig fmt: off |
| ... | @@ -49,22 +70,23 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -49,22 +70,23 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 49 | { | 70 | { |
| 50 | try doAtomicSymLinks( | 71 | try doAtomicSymLinks( |
| 51 | step, | 72 | step, |
| 52 | compile.getEmittedBin().getPath2(b, step), | 73 | compile.getEmittedBin().getPath2(step.owner, step), |
| 53 | compile.major_only_filename.?, | 74 | compile.major_only_filename.?, |
| 54 | compile.name_only_filename.?, | 75 | compile.name_only_filename.?, |
| 55 | ); | 76 | ); |
| 56 | } | 77 | } |
| 57 | } | 78 | } |
| 58 | 79 | ||
| 59 | fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | 80 | fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 { |
| 60 | const step = &compile.step; | 81 | const step = &compile.step; |
| 61 | const b = step.owner; | 82 | const b = step.owner; |
| 62 | const arena = b.allocator; | 83 | const graph = maker.graph; |
| 84 | const arena = graph.arena; // TODO don't leak into the process arena | ||
| 63 | 85 | ||
| 64 | var zig_args = std.array_list.Managed([]const u8).init(arena); | 86 | var zig_args = std.array_list.Managed([]const u8).init(arena); |
| 65 | defer zig_args.deinit(); | 87 | defer zig_args.deinit(); |
| 66 | 88 | ||
| 67 | try zig_args.append(b.graph.zig_exe); | 89 | try zig_args.append(graph.zig_exe); |
| 68 | 90 | ||
| 69 | const cmd = switch (compile.kind) { | 91 | const cmd = switch (compile.kind) { |
| 70 | .lib => "build-lib", | 92 | .lib => "build-lib", |
| ... | @@ -78,7 +100,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -78,7 +100,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 78 | if (b.reference_trace) |some| { | 100 | if (b.reference_trace) |some| { |
| 79 | try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some})); | 101 | try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some})); |
| 80 | } | 102 | } |
| 81 | try addFlag(&zig_args, "allow-so-scripts", compile.allow_so_scripts orelse b.graph.allow_so_scripts); | 103 | try addFlag(&zig_args, "allow-so-scripts", compile.allow_so_scripts orelse graph.allow_so_scripts); |
| 82 | 104 | ||
| 83 | try addFlag(&zig_args, "llvm", compile.use_llvm); | 105 | try addFlag(&zig_args, "llvm", compile.use_llvm); |
| 84 | try addFlag(&zig_args, "lld", compile.use_lld); | 106 | try addFlag(&zig_args, "lld", compile.use_lld); |
| ... | @@ -118,7 +140,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -118,7 +140,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 118 | // module, along with any arguments that need to be passed to the | 140 | // module, along with any arguments that need to be passed to the |
| 119 | // compiler for each module individually. | 141 | // compiler for each module individually. |
| 120 | var seen_system_libs: std.StringHashMapUnmanaged([]const []const u8) = .empty; | 142 | var seen_system_libs: std.StringHashMapUnmanaged([]const []const u8) = .empty; |
| 121 | var frameworks: std.StringArrayHashMapUnmanaged(Module.LinkFrameworkOptions) = .empty; | 143 | var frameworks: std.StringArrayHashMapUnmanaged(Module.FrameworkFlags) = .empty; |
| 122 | 144 | ||
| 123 | var prev_has_cflags = false; | 145 | var prev_has_cflags = false; |
| 124 | var prev_has_rcflags = false; | 146 | var prev_has_rcflags = false; |
| ... | @@ -130,7 +152,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -130,7 +152,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 130 | 152 | ||
| 131 | // Fully recursive iteration including dynamic libraries to detect | 153 | // Fully recursive iteration including dynamic libraries to detect |
| 132 | // libc and libc++ linkage. | 154 | // libc and libc++ linkage. |
| 133 | for (compile.getCompileDependencies(true)) |some_compile| { | 155 | for (getCompileDependencies(true)) |some_compile| { |
| 134 | for (some_compile.root_module.getGraph().modules) |mod| { | 156 | for (some_compile.root_module.getGraph().modules) |mod| { |
| 135 | if (mod.link_libc == true) compile.is_linking_libc = true; | 157 | if (mod.link_libc == true) compile.is_linking_libc = true; |
| 136 | if (mod.link_libcpp == true) compile.is_linking_libcpp = true; | 158 | if (mod.link_libcpp == true) compile.is_linking_libcpp = true; |
| ... | @@ -141,7 +163,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -141,7 +163,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 141 | 163 | ||
| 142 | // For this loop, don't chase dynamic libraries because their link | 164 | // For this loop, don't chase dynamic libraries because their link |
| 143 | // objects are already linked. | 165 | // objects are already linked. |
| 144 | for (compile.getCompileDependencies(false)) |dep_compile| { | 166 | for (getCompileDependencies(false)) |dep_compile| { |
| 145 | for (dep_compile.root_module.getGraph().modules) |mod| { | 167 | for (dep_compile.root_module.getGraph().modules) |mod| { |
| 146 | // While walking transitive dependencies, if a given link object is | 168 | // While walking transitive dependencies, if a given link object is |
| 147 | // already included in a library, it should not redundantly be | 169 | // already included in a library, it should not redundantly be |
| ... | @@ -207,7 +229,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -207,7 +229,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 207 | switch (system_lib.use_pkg_config) { | 229 | switch (system_lib.use_pkg_config) { |
| 208 | .no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })), | 230 | .no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })), |
| 209 | .yes, .force => { | 231 | .yes, .force => { |
| 210 | if (compile.runPkgConfig(system_lib.name)) |result| { | 232 | if (compile.runPkgConfig(maker, system_lib.name)) |result| { |
| 211 | try zig_args.appendSlice(result.cflags); | 233 | try zig_args.appendSlice(result.cflags); |
| 212 | try zig_args.appendSlice(result.libs); | 234 | try zig_args.appendSlice(result.libs); |
| 213 | try seen_system_libs.put(arena, system_lib.name, result.cflags); | 235 | try seen_system_libs.put(arena, system_lib.name, result.cflags); |
| ... | @@ -227,7 +249,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -227,7 +249,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 227 | })); | 249 | })); |
| 228 | }, | 250 | }, |
| 229 | .force => { | 251 | .force => { |
| 230 | panic("pkg-config failed for library {s}", .{system_lib.name}); | 252 | return step.fail("pkg-config failed for library {s}", .{system_lib.name}); |
| 231 | }, | 253 | }, |
| 232 | .no => unreachable, | 254 | .no => unreachable, |
| 233 | }, | 255 | }, |
| ... | @@ -272,7 +294,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -272,7 +294,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 272 | if (other.linkage == .dynamic and | 294 | if (other.linkage == .dynamic and |
| 273 | compile.rootModuleTarget().os.tag != .windows) | 295 | compile.rootModuleTarget().os.tag != .windows) |
| 274 | { | 296 | { |
| 275 | if (fs.path.dirname(full_path_lib)) |dirname| { | 297 | if (Dir.path.dirname(full_path_lib)) |dirname| { |
| 276 | try zig_args.append("-rpath"); | 298 | try zig_args.append("-rpath"); |
| 277 | try zig_args.append(dirname); | 299 | try zig_args.append(dirname); |
| 278 | } | 300 | } |
| ... | @@ -479,7 +501,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -479,7 +501,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 479 | if (b.verbose_link or compile.verbose_link) try zig_args.append("--verbose-link"); | 501 | if (b.verbose_link or compile.verbose_link) try zig_args.append("--verbose-link"); |
| 480 | if (b.verbose_cc or compile.verbose_cc) try zig_args.append("--verbose-cc"); | 502 | if (b.verbose_cc or compile.verbose_cc) try zig_args.append("--verbose-cc"); |
| 481 | if (b.verbose_llvm_cpu_features) try zig_args.append("--verbose-llvm-cpu-features"); | 503 | if (b.verbose_llvm_cpu_features) try zig_args.append("--verbose-llvm-cpu-features"); |
| 482 | if (b.graph.time_report) try zig_args.append("--time-report"); | 504 | if (graph.time_report) try zig_args.append("--time-report"); |
| 483 | 505 | ||
| 484 | if (compile.generated_asm != null) try zig_args.append("-femit-asm"); | 506 | if (compile.generated_asm != null) try zig_args.append("-femit-asm"); |
| 485 | if (compile.generated_bin == null) try zig_args.append("-fno-emit-bin"); | 507 | if (compile.generated_bin == null) try zig_args.append("-fno-emit-bin"); |
| ... | @@ -555,9 +577,9 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -555,9 +577,9 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 555 | try zig_args.append(b.cache_root.path orelse "."); | 577 | try zig_args.append(b.cache_root.path orelse "."); |
| 556 | 578 | ||
| 557 | try zig_args.append("--global-cache-dir"); | 579 | try zig_args.append("--global-cache-dir"); |
| 558 | try zig_args.append(b.graph.global_cache_root.path orelse "."); | 580 | try zig_args.append(graph.global_cache_root.path orelse "."); |
| 559 | 581 | ||
| 560 | if (b.graph.debug_compiler_runtime_libs) |mode| | 582 | if (graph.debug_compiler_runtime_libs) |mode| |
| 561 | try zig_args.append(b.fmt("--debug-rt={t}", .{mode})); | 583 | try zig_args.append(b.fmt("--debug-rt={t}", .{mode})); |
| 562 | 584 | ||
| 563 | try zig_args.append("--name"); | 585 | try zig_args.append("--name"); |
| ... | @@ -681,7 +703,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -681,7 +703,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 681 | 703 | ||
| 682 | // -I and -L arguments that appear after the last --mod argument apply to all modules. | 704 | // -I and -L arguments that appear after the last --mod argument apply to all modules. |
| 683 | const cwd: Io.Dir = .cwd(); | 705 | const cwd: Io.Dir = .cwd(); |
| 684 | const io = b.graph.io; | 706 | const io = graph.io; |
| 685 | 707 | ||
| 686 | for (b.search_prefixes.items) |search_prefix| { | 708 | for (b.search_prefixes.items) |search_prefix| { |
| 687 | var prefix_dir = cwd.openDir(io, search_prefix, .{}) catch |err| { | 709 | var prefix_dir = cwd.openDir(io, search_prefix, .{}) catch |err| { |
| ... | @@ -734,8 +756,8 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -734,8 +756,8 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 734 | 756 | ||
| 735 | const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir| | 757 | const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir| |
| 736 | dir.getPath2(b, step) | 758 | dir.getPath2(b, step) |
| 737 | else if (b.graph.zig_lib_directory.path) |_| | 759 | else if (graph.zig_lib_directory.path) |_| |
| 738 | b.fmt("{f}", .{b.graph.zig_lib_directory}) | 760 | b.fmt("{f}", .{graph.zig_lib_directory}) |
| 739 | else | 761 | else |
| 740 | null; | 762 | null; |
| 741 | 763 | ||
| ... | @@ -769,7 +791,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -769,7 +791,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 769 | "--error-limit", b.fmt("{d}", .{err_limit}), | 791 | "--error-limit", b.fmt("{d}", .{err_limit}), |
| 770 | }); | 792 | }); |
| 771 | 793 | ||
| 772 | try addFlag(&zig_args, "incremental", b.graph.incremental); | 794 | try addFlag(&zig_args, "incremental", graph.incremental); |
| 773 | 795 | ||
| 774 | try zig_args.append("--listen=-"); | 796 | try zig_args.append("--listen=-"); |
| 775 | 797 | ||
| ... | @@ -814,7 +836,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -814,7 +836,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 814 | var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined; | 836 | var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined; |
| 815 | _ = try std.fmt.bufPrint(&args_hex_hash, "{x}", .{&args_hash}); | 837 | _ = try std.fmt.bufPrint(&args_hex_hash, "{x}", .{&args_hash}); |
| 816 | 838 | ||
| 817 | const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash; | 839 | const args_file = "args" ++ Dir.path.sep_str ++ args_hex_hash; |
| 818 | if (b.cache_root.handle.access(io, args_file, .{})) |_| { | 840 | if (b.cache_root.handle.access(io, args_file, .{})) |_| { |
| 819 | // The args file is already present from a previous run. | 841 | // The args file is already present from a previous run. |
| 820 | } else |err| switch (err) { | 842 | } else |err| switch (err) { |
| ... | @@ -859,7 +881,9 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -859,7 +881,9 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 859 | return try zig_args.toOwnedSlice(); | 881 | return try zig_args.toOwnedSlice(); |
| 860 | } | 882 | } |
| 861 | 883 | ||
| 862 | pub fn rebuildInFuzzMode(c: *Compile, gpa: Allocator, progress_node: std.Progress.Node) !Path { | 884 | pub fn rebuildInFuzzMode(c: *Compile, maker: *Maker, progress_node: std.Progress.Node) !Path { |
| 885 | const gpa = maker.graph.gpa; | ||
| 886 | |||
| 863 | c.step.result_error_msgs.clearRetainingCapacity(); | 887 | c.step.result_error_msgs.clearRetainingCapacity(); |
| 864 | c.step.result_stderr = ""; | 888 | c.step.result_stderr = ""; |
| 865 | 889 | ||
| ... | @@ -871,21 +895,23 @@ pub fn rebuildInFuzzMode(c: *Compile, gpa: Allocator, progress_node: std.Progres | ... | @@ -871,21 +895,23 @@ pub fn rebuildInFuzzMode(c: *Compile, gpa: Allocator, progress_node: std.Progres |
| 871 | c.step.result_failed_command = null; | 895 | c.step.result_failed_command = null; |
| 872 | } | 896 | } |
| 873 | 897 | ||
| 874 | const zig_args = try getZigArgs(c, true); | 898 | const zig_args = try getZigArgs(c, maker, true); |
| 875 | const maybe_output_bin_path = try c.step.evalZigProcess(zig_args, progress_node, false, null, gpa); | 899 | const maybe_output_bin_path = try c.step.evalZigProcess(zig_args, progress_node, false, null, gpa); |
| 876 | return maybe_output_bin_path.?; | 900 | return maybe_output_bin_path.?; |
| 877 | } | 901 | } |
| 878 | 902 | ||
| 879 | pub fn doAtomicSymLinks( | 903 | pub fn doAtomicSymLinks( |
| 880 | step: *Step, | 904 | step: *Step, |
| 905 | maker: *Maker, | ||
| 881 | output_path: []const u8, | 906 | output_path: []const u8, |
| 882 | filename_major_only: []const u8, | 907 | filename_major_only: []const u8, |
| 883 | filename_name_only: []const u8, | 908 | filename_name_only: []const u8, |
| 884 | ) !void { | 909 | ) !void { |
| 885 | const b = step.owner; | 910 | const b = step.owner; |
| 886 | const io = b.graph.io; | 911 | const graph = maker.graph; |
| 887 | const out_dir = fs.path.dirname(output_path) orelse "."; | 912 | const io = graph.io; |
| 888 | const out_basename = fs.path.basename(output_path); | 913 | const out_dir = Dir.path.dirname(output_path) orelse "."; |
| 914 | const out_basename = Dir.path.basename(output_path); | ||
| 889 | // sym link for libfoo.so.1 to libfoo.so.1.2.3 | 915 | // sym link for libfoo.so.1 to libfoo.so.1.2.3 |
| 890 | const major_only_path = b.pathJoin(&.{ out_dir, filename_major_only }); | 916 | const major_only_path = b.pathJoin(&.{ out_dir, filename_major_only }); |
| 891 | const cwd: Io.Dir = .cwd(); | 917 | const cwd: Io.Dir = .cwd(); |
| ... | @@ -903,10 +929,24 @@ pub fn doAtomicSymLinks( | ... | @@ -903,10 +929,24 @@ pub fn doAtomicSymLinks( |
| 903 | }; | 929 | }; |
| 904 | } | 930 | } |
| 905 | 931 | ||
| 906 | fn execPkgConfigList(b: *std.Build, out_code: *u8) (PkgConfigError || RunError)![]const PkgConfigPkg { | 932 | pub const PkgConfigError = error{ |
| 907 | const pkg_config_exe = b.graph.environ_map.get("PKG_CONFIG") orelse "pkg-config"; | 933 | PkgConfigCrashed, |
| 908 | const stdout = try b.runAllowFail(&[_][]const u8{ pkg_config_exe, "--list-all" }, out_code, .ignore); | 934 | PkgConfigFailed, |
| 909 | var list = std.array_list.Managed(PkgConfigPkg).init(b.allocator); | 935 | PkgConfigNotInstalled, |
| 936 | PkgConfigInvalidOutput, | ||
| 937 | }; | ||
| 938 | |||
| 939 | pub const PkgConfigPkg = struct { | ||
| 940 | name: []const u8, | ||
| 941 | desc: []const u8, | ||
| 942 | }; | ||
| 943 | |||
| 944 | fn execPkgConfigList(maker: *Maker, out_code: *u8) (PkgConfigError || Maker.RunError)![]const PkgConfigPkg { | ||
| 945 | const graph = maker.graph; | ||
| 946 | const process_arena = graph.arena; // TODO don't leak into process arena | ||
| 947 | const pkg_config_exe = graph.environ_map.get("PKG_CONFIG") orelse "pkg-config"; | ||
| 948 | const stdout = try maker.runAllowFail(&[_][]const u8{ pkg_config_exe, "--list-all" }, out_code, .ignore); | ||
| 949 | var list = std.array_list.Managed(PkgConfigPkg).init(process_arena); | ||
| 910 | errdefer list.deinit(); | 950 | errdefer list.deinit(); |
| 911 | var line_it = mem.tokenizeAny(u8, stdout, "\r\n"); | 951 | var line_it = mem.tokenizeAny(u8, stdout, "\r\n"); |
| 912 | while (line_it.next()) |line| { | 952 | while (line_it.next()) |line| { |
| ... | @@ -960,7 +1000,8 @@ const PkgConfigResult = struct { | ... | @@ -960,7 +1000,8 @@ const PkgConfigResult = struct { |
| 960 | 1000 | ||
| 961 | /// Run pkg-config for the given library name and parse the output, returning the arguments | 1001 | /// Run pkg-config for the given library name and parse the output, returning the arguments |
| 962 | /// that should be passed to zig to link the given library. | 1002 | /// that should be passed to zig to link the given library. |
| 963 | fn runPkgConfig(compile: *Compile, lib_name: []const u8) !PkgConfigResult { | 1003 | fn runPkgConfig(compile: *Compile, maker: *Maker, lib_name: []const u8) !PkgConfigResult { |
| 1004 | const graph = maker.graph; | ||
| 964 | const wl_rpath_prefix = "-Wl,-rpath,"; | 1005 | const wl_rpath_prefix = "-Wl,-rpath,"; |
| 965 | 1006 | ||
| 966 | const b = compile.step.owner; | 1007 | const b = compile.step.owner; |
| ... | @@ -1013,7 +1054,7 @@ fn runPkgConfig(compile: *Compile, lib_name: []const u8) !PkgConfigResult { | ... | @@ -1013,7 +1054,7 @@ fn runPkgConfig(compile: *Compile, lib_name: []const u8) !PkgConfigResult { |
| 1013 | }; | 1054 | }; |
| 1014 | 1055 | ||
| 1015 | var code: u8 = undefined; | 1056 | var code: u8 = undefined; |
| 1016 | const pkg_config_exe = b.graph.environ_map.get("PKG_CONFIG") orelse "pkg-config"; | 1057 | const pkg_config_exe = graph.environ_map.get("PKG_CONFIG") orelse "pkg-config"; |
| 1017 | const stdout = if (b.runAllowFail(&[_][]const u8{ | 1058 | const stdout = if (b.runAllowFail(&[_][]const u8{ |
| 1018 | pkg_config_exe, | 1059 | pkg_config_exe, |
| 1019 | pkg_name, | 1060 | pkg_name, |
| ... | @@ -1198,3 +1239,43 @@ fn moduleNeedsCliArg(mod: *const Module) bool { | ... | @@ -1198,3 +1239,43 @@ fn moduleNeedsCliArg(mod: *const Module) bool { |
| 1198 | } else false; | 1239 | } else false; |
| 1199 | } | 1240 | } |
| 1200 | 1241 | ||
| 1242 | const CliNamedModules = struct { | ||
| 1243 | modules: std.AutoArrayHashMapUnmanaged(*Module, void), | ||
| 1244 | names: std.StringArrayHashMapUnmanaged(void), | ||
| 1245 | |||
| 1246 | /// Traverse the whole dependency graph and give every module a unique | ||
| 1247 | /// name, ideally one named after what it's called somewhere in the graph. | ||
| 1248 | /// It will help here to have both a mapping from module to name and a set | ||
| 1249 | /// of all the currently-used names. | ||
| 1250 | fn init(arena: Allocator, root_module: *Module) Allocator.Error!CliNamedModules { | ||
| 1251 | var compile: CliNamedModules = .{ | ||
| 1252 | .modules = .{}, | ||
| 1253 | .names = .{}, | ||
| 1254 | }; | ||
| 1255 | const graph = root_module.getGraph(); | ||
| 1256 | { | ||
| 1257 | assert(graph.modules[0] == root_module); | ||
| 1258 | try compile.modules.put(arena, root_module, {}); | ||
| 1259 | try compile.names.put(arena, "root", {}); | ||
| 1260 | } | ||
| 1261 | for (graph.modules[1..], graph.names[1..]) |mod, orig_name| { | ||
| 1262 | var name = orig_name; | ||
| 1263 | var n: usize = 0; | ||
| 1264 | while (true) { | ||
| 1265 | const gop = try compile.names.getOrPut(arena, name); | ||
| 1266 | if (!gop.found_existing) { | ||
| 1267 | try compile.modules.putNoClobber(arena, mod, {}); | ||
| 1268 | break; | ||
| 1269 | } | ||
| 1270 | name = try std.fmt.allocPrint(arena, "{s}{d}", .{ orig_name, n }); | ||
| 1271 | n += 1; | ||
| 1272 | } | ||
| 1273 | } | ||
| 1274 | return compile; | ||
| 1275 | } | ||
| 1276 | }; | ||
| 1277 | |||
| 1278 | fn getCompileDependencies(chase_dynamic: bool) void { | ||
| 1279 | _ = chase_dynamic; | ||
| 1280 | @panic("TODO"); | ||
| 1281 | } |
lib/compiler/Maker/Step/Run.zig+126-117| ... | @@ -3,38 +3,46 @@ const Run = @This(); | ... | @@ -3,38 +3,46 @@ const Run = @This(); |
| 3 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 4 | 4 | ||
| 5 | const std = @import("std"); | 5 | const std = @import("std"); |
| 6 | const Io = std.Io; | 6 | const Cache = std.Build.Cache; |
| 7 | const Configuration = std.Build.Configuration; | ||
| 7 | const Dir = std.Io.Dir; | 8 | const Dir = std.Io.Dir; |
| 8 | const mem = std.mem; | ||
| 9 | const process = std.process; | ||
| 10 | const EnvMap = std.process.Environ.Map; | 9 | const EnvMap = std.process.Environ.Map; |
| 11 | const assert = std.debug.assert; | 10 | const Io = std.Io; |
| 12 | const Cache = std.Build.Cache; | ||
| 13 | const Path = std.Build.Cache.Path; | 11 | const Path = std.Build.Cache.Path; |
| 12 | const assert = std.debug.assert; | ||
| 13 | const mem = std.mem; | ||
| 14 | const process = std.process; | ||
| 14 | 15 | ||
| 15 | const Step = @import("../Step.zig"); | 16 | const Step = @import("../Step.zig"); |
| 17 | const Maker = @import("../../Maker.zig"); | ||
| 16 | 18 | ||
| 17 | /// If this is a Zig unit test binary, this tracks the names of the unit | 19 | /// If this is a Zig unit test binary, this tracks the names of the unit |
| 18 | /// tests that are also fuzz tests. Indexes cannot be used as they may | 20 | /// tests that are also fuzz tests. Indexes cannot be used as they may |
| 19 | /// change between reruns. | 21 | /// change between reruns. |
| 20 | fuzz_tests: std.ArrayList([]const u8), | 22 | fuzz_tests: std.ArrayList([]const u8) = .empty, |
| 21 | cached_test_metadata: ?CachedTestMetadata = null, | 23 | cached_test_metadata: ?CachedTestMetadata = null, |
| 22 | 24 | ||
| 23 | /// Populated during the fuzz phase if this run step corresponds to a unit test | 25 | /// Populated during the fuzz phase if this run step corresponds to a unit test |
| 24 | /// executable that contains fuzz tests. | 26 | /// executable that contains fuzz tests. |
| 25 | rebuilt_executable: ?Path, | 27 | rebuilt_executable: ?Path = null, |
| 26 | 28 | ||
| 27 | fn make(step: *Step, options: Step.MakeOptions) !void { | 29 | pub fn make( |
| 28 | const b = step.owner; | 30 | run: *Run, |
| 29 | const io = b.graph.io; | 31 | step_index: Configuration.Step.Index, |
| 30 | const arena = b.allocator; | 32 | maker: *Maker, |
| 31 | const run: *Run = @fieldParentPtr("step", step); | 33 | progress_node: std.Progress.Node, |
| 34 | ) Step.ExtendedMakeError!void { | ||
| 35 | if (true) @panic("TODO implement run.make()"); | ||
| 36 | const graph = maker.graph; | ||
| 37 | const step = maker.stepByIndex(step_index); | ||
| 38 | const io = graph.io; | ||
| 39 | const arena = graph.arena; // TODO don't leak into the process arena | ||
| 32 | const has_side_effects = run.hasSideEffects(); | 40 | const has_side_effects = run.hasSideEffects(); |
| 33 | 41 | ||
| 34 | var argv_list = std.array_list.Managed([]const u8).init(arena); | 42 | var argv_list = std.array_list.Managed([]const u8).init(arena); |
| 35 | var output_placeholders = std.array_list.Managed(IndexedOutput).init(arena); | 43 | var output_placeholders = std.array_list.Managed(IndexedOutput).init(arena); |
| 36 | 44 | ||
| 37 | var man = b.graph.cache.obtain(); | 45 | var man = graph.cache.obtain(); |
| 38 | defer man.deinit(); | 46 | defer man.deinit(); |
| 39 | 47 | ||
| 40 | if (run.environ_map) |environ_map| { | 48 | if (run.environ_map) |environ_map| { |
| ... | @@ -54,19 +62,19 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -54,19 +62,19 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 54 | man.hash.addBytes(bytes); | 62 | man.hash.addBytes(bytes); |
| 55 | }, | 63 | }, |
| 56 | .lazy_path => |file| { | 64 | .lazy_path => |file| { |
| 57 | const file_path = file.lazy_path.getPath3(b, step); | 65 | const file_path = file.lazy_path.getPath3(graph, step); |
| 58 | try argv_list.append(b.fmt("{s}{s}", .{ file.prefix, run.convertPathArg(file_path) })); | 66 | try argv_list.append(graph.fmt("{s}{s}", .{ file.prefix, run.convertPathArg(maker, file_path) })); |
| 59 | man.hash.addBytes(file.prefix); | 67 | man.hash.addBytes(file.prefix); |
| 60 | _ = try man.addFilePath(file_path, null); | 68 | _ = try man.addFilePath(file_path, null); |
| 61 | }, | 69 | }, |
| 62 | .decorated_directory => |dd| { | 70 | .decorated_directory => |dd| { |
| 63 | const file_path = dd.lazy_path.getPath3(b, step); | 71 | const file_path = dd.lazy_path.getPath3(graph, step); |
| 64 | const resolved_arg = b.fmt("{s}{s}{s}", .{ dd.prefix, run.convertPathArg(file_path), dd.suffix }); | 72 | const resolved_arg = graph.fmt("{s}{s}{s}", .{ dd.prefix, run.convertPathArg(maker, file_path), dd.suffix }); |
| 65 | try argv_list.append(resolved_arg); | 73 | try argv_list.append(resolved_arg); |
| 66 | man.hash.addBytes(resolved_arg); | 74 | man.hash.addBytes(resolved_arg); |
| 67 | }, | 75 | }, |
| 68 | .file_content => |file_plp| { | 76 | .file_content => |file_plp| { |
| 69 | const file_path = file_plp.lazy_path.getPath3(b, step); | 77 | const file_path = file_plp.lazy_path.getPath3(graph, step); |
| 70 | 78 | ||
| 71 | var result: std.Io.Writer.Allocating = .init(arena); | 79 | var result: std.Io.Writer.Allocating = .init(arena); |
| 72 | errdefer result.deinit(); | 80 | errdefer result.deinit(); |
| ... | @@ -99,13 +107,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -99,13 +107,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 99 | 107 | ||
| 100 | if (artifact.rootModuleTarget().os.tag == .windows) { | 108 | if (artifact.rootModuleTarget().os.tag == .windows) { |
| 101 | // On Windows we don't have rpaths so we have to add .dll search paths to PATH | 109 | // On Windows we don't have rpaths so we have to add .dll search paths to PATH |
| 102 | run.addPathForDynLibs(artifact); | 110 | addPathForDynLibs(artifact); |
| 103 | } | 111 | } |
| 104 | const file_path = artifact.installed_path orelse artifact.generated_bin.?.path.?; | 112 | const file_path = artifact.installed_path orelse artifact.generated_bin.?.path.?; |
| 105 | 113 | ||
| 106 | try argv_list.append(b.fmt("{s}{s}", .{ | 114 | try argv_list.append(graph.fmt("{s}{s}", .{ |
| 107 | pa.prefix, | 115 | pa.prefix, |
| 108 | run.convertPathArg(.{ .root_dir = .cwd(), .sub_path = file_path }), | 116 | run.convertPathArg(maker, .{ .root_dir = .cwd(), .sub_path = file_path }), |
| 109 | })); | 117 | })); |
| 110 | 118 | ||
| 111 | _ = try man.addFile(file_path, null); | 119 | _ = try man.addFile(file_path, null); |
| ... | @@ -131,7 +139,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -131,7 +139,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 131 | man.hash.addBytes(bytes); | 139 | man.hash.addBytes(bytes); |
| 132 | }, | 140 | }, |
| 133 | .lazy_path => |lazy_path| { | 141 | .lazy_path => |lazy_path| { |
| 134 | const file_path = lazy_path.getPath2(b, step); | 142 | const file_path = lazy_path.getPath2(graph, step); |
| 135 | _ = try man.addFile(file_path, null); | 143 | _ = try man.addFile(file_path, null); |
| 136 | }, | 144 | }, |
| 137 | .none => {}, | 145 | .none => {}, |
| ... | @@ -147,14 +155,15 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -147,14 +155,15 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 147 | man.hash.add(captured.trim_whitespace); | 155 | man.hash.add(captured.trim_whitespace); |
| 148 | } | 156 | } |
| 149 | 157 | ||
| 150 | hashStdIo(&man.hash, run.stdio); | 158 | std.log.err("TODO hashStdIo", .{}); |
| 159 | //hashStdIo(&man.hash, run.stdio); | ||
| 151 | 160 | ||
| 152 | for (run.file_inputs.items) |lazy_path| { | 161 | for (run.file_inputs.items) |lazy_path| { |
| 153 | _ = try man.addFile(lazy_path.getPath2(b, step), null); | 162 | _ = try man.addFile(lazy_path.getPath2(graph, step), null); |
| 154 | } | 163 | } |
| 155 | 164 | ||
| 156 | if (run.cwd) |cwd| { | 165 | if (run.cwd) |cwd| { |
| 157 | const cwd_path = cwd.getPath3(b, step); | 166 | const cwd_path = cwd.getPath3(graph, step); |
| 158 | _ = man.hash.addBytes(try cwd_path.toString(arena)); | 167 | _ = man.hash.addBytes(try cwd_path.toString(arena)); |
| 159 | } | 168 | } |
| 160 | 169 | ||
| ... | @@ -165,9 +174,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -165,9 +174,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 165 | try populateGeneratedPaths( | 174 | try populateGeneratedPaths( |
| 166 | arena, | 175 | arena, |
| 167 | output_placeholders.items, | 176 | output_placeholders.items, |
| 168 | run.captured_stdout, | 177 | graph.cache_root, |
| 169 | run.captured_stderr, | ||
| 170 | b.cache_root, | ||
| 171 | &digest, | 178 | &digest, |
| 172 | ); | 179 | ); |
| 173 | 180 | ||
| ... | @@ -185,36 +192,34 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -185,36 +192,34 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 185 | try populateGeneratedPaths( | 192 | try populateGeneratedPaths( |
| 186 | arena, | 193 | arena, |
| 187 | output_placeholders.items, | 194 | output_placeholders.items, |
| 188 | run.captured_stdout, | 195 | graph.cache_root, |
| 189 | run.captured_stderr, | ||
| 190 | b.cache_root, | ||
| 191 | &digest, | 196 | &digest, |
| 192 | ); | 197 | ); |
| 193 | 198 | ||
| 194 | const output_dir_path = "o" ++ Dir.path.sep_str ++ &digest; | 199 | const output_dir_path = "o" ++ Dir.path.sep_str ++ &digest; |
| 195 | for (output_placeholders.items) |placeholder| { | 200 | for (output_placeholders.items) |placeholder| { |
| 196 | const output_sub_path = b.pathJoin(&.{ output_dir_path, placeholder.output.basename }); | 201 | const output_sub_path = graph.pathJoin(&.{ output_dir_path, placeholder.output.basename }); |
| 197 | const output_sub_dir_path = switch (placeholder.tag) { | 202 | const output_sub_dir_path = switch (placeholder.tag) { |
| 198 | .output_file => Dir.path.dirname(output_sub_path).?, | 203 | .output_file => Dir.path.dirname(output_sub_path).?, |
| 199 | .output_directory => output_sub_path, | 204 | .output_directory => output_sub_path, |
| 200 | else => unreachable, | 205 | else => unreachable, |
| 201 | }; | 206 | }; |
| 202 | b.cache_root.handle.createDirPath(io, output_sub_dir_path) catch |err| { | 207 | graph.cache_root.handle.createDirPath(io, output_sub_dir_path) catch |err| { |
| 203 | return step.fail("unable to make path '{f}{s}': {s}", .{ | 208 | return step.fail("unable to make path '{f}{s}': {t}", .{ |
| 204 | b.cache_root, output_sub_dir_path, @errorName(err), | 209 | graph.cache_root, output_sub_dir_path, err, |
| 205 | }); | 210 | }); |
| 206 | }; | 211 | }; |
| 207 | const arg_output_path = run.convertPathArg(.{ | 212 | const arg_output_path = run.convertPathArg(maker, .{ |
| 208 | .root_dir = .cwd(), | 213 | .root_dir = .cwd(), |
| 209 | .sub_path = placeholder.output.generated_file.getPath(), | 214 | .sub_path = placeholder.output.generated_file.getPath(), |
| 210 | }); | 215 | }); |
| 211 | argv_list.items[placeholder.index] = if (placeholder.output.prefix.len == 0) | 216 | argv_list.items[placeholder.index] = if (placeholder.output.prefix.len == 0) |
| 212 | arg_output_path | 217 | arg_output_path |
| 213 | else | 218 | else |
| 214 | b.fmt("{s}{s}", .{ placeholder.output.prefix, arg_output_path }); | 219 | graph.fmt("{s}{s}", .{ placeholder.output.prefix, arg_output_path }); |
| 215 | } | 220 | } |
| 216 | 221 | ||
| 217 | try runCommand(run, argv_list.items, has_side_effects, output_dir_path, options, null); | 222 | try runCommand(run, maker, progress_node, argv_list.items, has_side_effects, output_dir_path, null); |
| 218 | if (!has_side_effects) try step.writeManifestAndWatch(&man); | 223 | if (!has_side_effects) try step.writeManifestAndWatch(&man); |
| 219 | return; | 224 | return; |
| 220 | }; | 225 | }; |
| ... | @@ -226,32 +231,32 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -226,32 +231,32 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 226 | 231 | ||
| 227 | for (output_placeholders.items) |placeholder| { | 232 | for (output_placeholders.items) |placeholder| { |
| 228 | const output_components = .{ tmp_dir_path, placeholder.output.basename }; | 233 | const output_components = .{ tmp_dir_path, placeholder.output.basename }; |
| 229 | const output_sub_path = b.pathJoin(&output_components); | 234 | const output_sub_path = graph.pathJoin(&output_components); |
| 230 | const output_sub_dir_path = switch (placeholder.tag) { | 235 | const output_sub_dir_path = switch (placeholder.tag) { |
| 231 | .output_file => Dir.path.dirname(output_sub_path).?, | 236 | .output_file => Dir.path.dirname(output_sub_path).?, |
| 232 | .output_directory => output_sub_path, | 237 | .output_directory => output_sub_path, |
| 233 | else => unreachable, | 238 | else => unreachable, |
| 234 | }; | 239 | }; |
| 235 | b.cache_root.handle.createDirPath(io, output_sub_dir_path) catch |err| { | 240 | graph.cache_root.handle.createDirPath(io, output_sub_dir_path) catch |err| { |
| 236 | return step.fail("unable to make path '{f}{s}': {s}", .{ | 241 | return step.fail("unable to make path '{f}{s}': {t}", .{ |
| 237 | b.cache_root, output_sub_dir_path, @errorName(err), | 242 | graph.cache_root, output_sub_dir_path, err, |
| 238 | }); | 243 | }); |
| 239 | }; | 244 | }; |
| 240 | const raw_output_path: Cache.Path = .{ | 245 | const raw_output_path: Path = .{ |
| 241 | .root_dir = b.cache_root, | 246 | .root_dir = graph.cache_root, |
| 242 | .sub_path = b.pathJoin(&output_components), | 247 | .sub_path = graph.pathJoin(&output_components), |
| 243 | }; | 248 | }; |
| 244 | placeholder.output.generated_file.path = raw_output_path.toString(b.graph.arena) catch @panic("OOM"); | 249 | placeholder.output.generated_file.path = raw_output_path.toString(arena) catch @panic("OOM"); |
| 245 | argv_list.items[placeholder.index] = b.fmt("{s}{s}", .{ | 250 | argv_list.items[placeholder.index] = graph.fmt("{s}{s}", .{ |
| 246 | placeholder.output.prefix, | 251 | placeholder.output.prefix, |
| 247 | run.convertPathArg(raw_output_path), | 252 | run.convertPathArg(maker, raw_output_path), |
| 248 | }); | 253 | }); |
| 249 | } | 254 | } |
| 250 | 255 | ||
| 251 | try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, options, null); | 256 | try runCommand(run, maker, progress_node, argv_list.items, has_side_effects, tmp_dir_path, null); |
| 252 | 257 | ||
| 253 | const dep_file_dir = Dir.cwd(); | 258 | const dep_file_dir = Dir.cwd(); |
| 254 | const dep_file_basename = dep_output_file.generated_file.getPath2(b, step); | 259 | const dep_file_basename = dep_output_file.generated_file.getPath2(graph, step); |
| 255 | if (has_side_effects) | 260 | if (has_side_effects) |
| 256 | try man.addDepFile(dep_file_dir, dep_file_basename) | 261 | try man.addDepFile(dep_file_dir, dep_file_basename) |
| 257 | else | 262 | else |
| ... | @@ -269,21 +274,21 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -269,21 +274,21 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 269 | if (any_output) { | 274 | if (any_output) { |
| 270 | const o_sub_path = "o" ++ Dir.path.sep_str ++ &digest; | 275 | const o_sub_path = "o" ++ Dir.path.sep_str ++ &digest; |
| 271 | 276 | ||
| 272 | b.cache_root.handle.rename(tmp_dir_path, b.cache_root.handle, o_sub_path, io) catch |err| switch (err) { | 277 | graph.cache_root.handle.rename(tmp_dir_path, graph.cache_root.handle, o_sub_path, io) catch |err| switch (err) { |
| 273 | Dir.RenameError.DirNotEmpty => { | 278 | Dir.RenameError.DirNotEmpty => { |
| 274 | b.cache_root.handle.deleteTree(io, o_sub_path) catch |del_err| { | 279 | graph.cache_root.handle.deleteTree(io, o_sub_path) catch |del_err| { |
| 275 | return step.fail("unable to remove dir '{f}'{s}: {t}", .{ | 280 | return step.fail("unable to remove dir '{f}'{s}: {t}", .{ |
| 276 | b.cache_root, tmp_dir_path, del_err, | 281 | graph.cache_root, tmp_dir_path, del_err, |
| 277 | }); | 282 | }); |
| 278 | }; | 283 | }; |
| 279 | b.cache_root.handle.rename(tmp_dir_path, b.cache_root.handle, o_sub_path, io) catch |retry_err| { | 284 | graph.cache_root.handle.rename(tmp_dir_path, graph.cache_root.handle, o_sub_path, io) catch |retry_err| { |
| 280 | return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {t}", .{ | 285 | return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {t}", .{ |
| 281 | b.cache_root, tmp_dir_path, b.cache_root, o_sub_path, retry_err, | 286 | graph.cache_root, tmp_dir_path, graph.cache_root, o_sub_path, retry_err, |
| 282 | }); | 287 | }); |
| 283 | }; | 288 | }; |
| 284 | }, | 289 | }, |
| 285 | else => return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {t}", .{ | 290 | else => return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {t}", .{ |
| 286 | b.cache_root, tmp_dir_path, b.cache_root, o_sub_path, err, | 291 | graph.cache_root, tmp_dir_path, graph.cache_root, o_sub_path, err, |
| 287 | }), | 292 | }), |
| 288 | }; | 293 | }; |
| 289 | } | 294 | } |
| ... | @@ -293,9 +298,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -293,9 +298,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 293 | try populateGeneratedPaths( | 298 | try populateGeneratedPaths( |
| 294 | arena, | 299 | arena, |
| 295 | output_placeholders.items, | 300 | output_placeholders.items, |
| 296 | run.captured_stdout, | 301 | graph.cache_root, |
| 297 | run.captured_stderr, | ||
| 298 | b.cache_root, | ||
| 299 | &digest, | 302 | &digest, |
| 300 | ); | 303 | ); |
| 301 | } | 304 | } |
| ... | @@ -347,7 +350,6 @@ fn waitZigTest( | ... | @@ -347,7 +350,6 @@ fn waitZigTest( |
| 347 | // start and it acknowledging the test starting, we terminate the child and raise an error. This | 350 | // start and it acknowledging the test starting, we terminate the child and raise an error. This |
| 348 | // *should* never happen, but could in theory be caused by some very unlucky IB in a test. | 351 | // *should* never happen, but could in theory be caused by some very unlucky IB in a test. |
| 349 | const response_timeout: Io.Clock.Duration = t: { | 352 | const response_timeout: Io.Clock.Duration = t: { |
| 350 | if (fuzz_context != null) break :t null; // don't timeout fuzz tests | ||
| 351 | const ns = @max(options.unit_test_timeout_ns orelse 0, 60 * std.time.ns_per_s); | 353 | const ns = @max(options.unit_test_timeout_ns orelse 0, 60 * std.time.ns_per_s); |
| 352 | break :t .{ .clock = .awake, .raw = .fromNanoseconds(ns) }; | 354 | break :t .{ .clock = .awake, .raw = .fromNanoseconds(ns) }; |
| 353 | }; | 355 | }; |
| ... | @@ -773,8 +775,8 @@ const FuzzTestRunner = struct { | ... | @@ -773,8 +775,8 @@ const FuzzTestRunner = struct { |
| 773 | try f.pending_broadcasts.ensureUnusedCapacity(gpa, size); | 775 | try f.pending_broadcasts.ensureUnusedCapacity(gpa, size); |
| 774 | f.pending_broadcasts.appendSliceAssumeCapacity(body); | 776 | f.pending_broadcasts.appendSliceAssumeCapacity(body); |
| 775 | f.pending_broadcasts.appendSliceAssumeCapacity(@ptrCast(&footer)); | 777 | f.pending_broadcasts.appendSliceAssumeCapacity(@ptrCast(&footer)); |
| 776 | } | 778 | } |
| 777 | }, | 779 | }, |
| 778 | else => {}, // ignore other messages | 780 | else => {}, // ignore other messages |
| 779 | } | 781 | } |
| 780 | 782 | ||
| ... | @@ -863,7 +865,7 @@ const FuzzTestRunner = struct { | ... | @@ -863,7 +865,7 @@ const FuzzTestRunner = struct { |
| 863 | if (f.coverage_id == null) return; | 865 | if (f.coverage_id == null) return; |
| 864 | 866 | ||
| 865 | // Search for the input file corresponding to the instance | 867 | // Search for the input file corresponding to the instance |
| 866 | const InputHeader = Build.abi.fuzz.MmapInputHeader; | 868 | const InputHeader = std.Build.abi.fuzz.MmapInputHeader; |
| 867 | var in_r_buf: [@sizeOf(InputHeader)]u8 = undefined; | 869 | var in_r_buf: [@sizeOf(InputHeader)]u8 = undefined; |
| 868 | var in_r: Io.File.Reader = undefined; | 870 | var in_r: Io.File.Reader = undefined; |
| 869 | var in_f: Io.File = undefined; | 871 | var in_f: Io.File = undefined; |
| ... | @@ -1299,11 +1301,11 @@ fn sendRunFuzzTestMessage( | ... | @@ -1299,11 +1301,11 @@ fn sendRunFuzzTestMessage( |
| 1299 | } | 1301 | } |
| 1300 | } | 1302 | } |
| 1301 | 1303 | ||
| 1302 | fn evalGeneric(run: *Run, spawn_options: process.SpawnOptions) !EvalGenericResult { | 1304 | fn evalGeneric(run: *Run, maker: *Maker, spawn_options: process.SpawnOptions) !EvalGenericResult { |
| 1303 | const b = run.step.owner; | 1305 | const graph = maker.graph; |
| 1304 | const io = b.graph.io; | 1306 | const io = graph.io; |
| 1305 | const arena = b.allocator; | 1307 | const arena = graph.allocator; // TODO don't leak into the process arena |
| 1306 | const gpa = b.allocator; | 1308 | const gpa = maker.gpa; |
| 1307 | 1309 | ||
| 1308 | var child = try process.spawn(io, spawn_options); | 1310 | var child = try process.spawn(io, spawn_options); |
| 1309 | defer child.kill(io); | 1311 | defer child.kill(io); |
| ... | @@ -1317,7 +1319,7 @@ fn evalGeneric(run: *Run, spawn_options: process.SpawnOptions) !EvalGenericResul | ... | @@ -1317,7 +1319,7 @@ fn evalGeneric(run: *Run, spawn_options: process.SpawnOptions) !EvalGenericResul |
| 1317 | child.stdin = null; | 1319 | child.stdin = null; |
| 1318 | }, | 1320 | }, |
| 1319 | .lazy_path => |lazy_path| { | 1321 | .lazy_path => |lazy_path| { |
| 1320 | const path = lazy_path.getPath3(b, &run.step); | 1322 | const path = lazy_path.getPath3(graph, &run.step); |
| 1321 | const file = path.root_dir.handle.openFile(io, path.subPathOrDot(), .{}) catch |err| { | 1323 | const file = path.root_dir.handle.openFile(io, path.subPathOrDot(), .{}) catch |err| { |
| 1322 | return run.step.fail("unable to open stdin file: {t}", .{err}); | 1324 | return run.step.fail("unable to open stdin file: {t}", .{err}); |
| 1323 | }; | 1325 | }; |
| ... | @@ -1417,18 +1419,22 @@ fn evalGeneric(run: *Run, spawn_options: process.SpawnOptions) !EvalGenericResul | ... | @@ -1417,18 +1419,22 @@ fn evalGeneric(run: *Run, spawn_options: process.SpawnOptions) !EvalGenericResul |
| 1417 | 1419 | ||
| 1418 | const IndexedOutput = struct { | 1420 | const IndexedOutput = struct { |
| 1419 | index: usize, | 1421 | index: usize, |
| 1420 | tag: @typeInfo(Arg).@"union".tag_type.?, | 1422 | tag: Configuration.Step.Run.Arg.Tag, |
| 1421 | output: *Output, | 1423 | output: *Output, |
| 1422 | }; | 1424 | }; |
| 1423 | 1425 | ||
| 1426 | const Output = void; // TODO | ||
| 1427 | |||
| 1424 | pub fn rerunInFuzzMode( | 1428 | pub fn rerunInFuzzMode( |
| 1425 | run: *Run, | 1429 | run: *Run, |
| 1426 | fuzz: *std.Build.Fuzz, | 1430 | fuzz: *std.Build.Fuzz, |
| 1427 | prog_node: std.Progress.Node, | 1431 | prog_node: std.Progress.Node, |
| 1428 | ) !void { | 1432 | ) !void { |
| 1433 | const maker = fuzz.maker; | ||
| 1434 | const graph = maker.graph; | ||
| 1429 | const step = &run.step; | 1435 | const step = &run.step; |
| 1430 | const b = step.owner; | 1436 | const b = step.owner; |
| 1431 | const io = b.graph.io; | 1437 | const io = graph.io; |
| 1432 | const arena = b.allocator; | 1438 | const arena = b.allocator; |
| 1433 | var argv_list: std.ArrayList([]const u8) = .empty; | 1439 | var argv_list: std.ArrayList([]const u8) = .empty; |
| 1434 | for (run.argv.items) |arg| { | 1440 | for (run.argv.items) |arg| { |
| ... | @@ -1438,11 +1444,11 @@ pub fn rerunInFuzzMode( | ... | @@ -1438,11 +1444,11 @@ pub fn rerunInFuzzMode( |
| 1438 | }, | 1444 | }, |
| 1439 | .lazy_path => |file| { | 1445 | .lazy_path => |file| { |
| 1440 | const file_path = file.lazy_path.getPath3(b, step); | 1446 | const file_path = file.lazy_path.getPath3(b, step); |
| 1441 | try argv_list.append(arena, b.fmt("{s}{s}", .{ file.prefix, run.convertPathArg(file_path) })); | 1447 | try argv_list.append(arena, b.fmt("{s}{s}", .{ file.prefix, run.convertPathArg(maker, file_path) })); |
| 1442 | }, | 1448 | }, |
| 1443 | .decorated_directory => |dd| { | 1449 | .decorated_directory => |dd| { |
| 1444 | const file_path = dd.lazy_path.getPath3(b, step); | 1450 | const file_path = dd.lazy_path.getPath3(b, step); |
| 1445 | try argv_list.append(arena, b.fmt("{s}{s}{s}", .{ dd.prefix, run.convertPathArg(file_path), dd.suffix })); | 1451 | try argv_list.append(arena, b.fmt("{s}{s}{s}", .{ dd.prefix, run.convertPathArg(maker, file_path), dd.suffix })); |
| 1446 | }, | 1452 | }, |
| 1447 | .file_content => |file_plp| { | 1453 | .file_content => |file_plp| { |
| 1448 | const file_path = file_plp.lazy_path.getPath3(b, step); | 1454 | const file_path = file_plp.lazy_path.getPath3(b, step); |
| ... | @@ -1471,7 +1477,7 @@ pub fn rerunInFuzzMode( | ... | @@ -1471,7 +1477,7 @@ pub fn rerunInFuzzMode( |
| 1471 | }; | 1477 | }; |
| 1472 | try argv_list.append(arena, b.fmt("{s}{s}", .{ | 1478 | try argv_list.append(arena, b.fmt("{s}{s}", .{ |
| 1473 | pa.prefix, | 1479 | pa.prefix, |
| 1474 | run.convertPathArg(.{ .root_dir = .cwd(), .sub_path = file_path }), | 1480 | run.convertPathArg(maker, .{ .root_dir = .cwd(), .sub_path = file_path }), |
| 1475 | })); | 1481 | })); |
| 1476 | }, | 1482 | }, |
| 1477 | .output_file, .output_directory => unreachable, | 1483 | .output_file, .output_directory => unreachable, |
| ... | @@ -1487,17 +1493,13 @@ pub fn rerunInFuzzMode( | ... | @@ -1487,17 +1493,13 @@ pub fn rerunInFuzzMode( |
| 1487 | var rand_int: u64 = undefined; | 1493 | var rand_int: u64 = undefined; |
| 1488 | io.random(@ptrCast(&rand_int)); | 1494 | io.random(@ptrCast(&rand_int)); |
| 1489 | const tmp_dir_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int); | 1495 | const tmp_dir_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int); |
| 1490 | try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, .{ | 1496 | try runCommand(run, maker, prog_node, argv_list.items, has_side_effects, tmp_dir_path, .{ |
| 1491 | .progress_node = prog_node, | ||
| 1492 | .watch = undefined, // not used by `runCommand` | ||
| 1493 | .web_server = null, // only needed for time reports | ||
| 1494 | .unit_test_timeout_ns = null, // don't time out fuzz tests for now | ||
| 1495 | .gpa = fuzz.gpa, | ||
| 1496 | }, .{ | ||
| 1497 | .fuzz = fuzz, | 1497 | .fuzz = fuzz, |
| 1498 | }); | 1498 | }); |
| 1499 | } | 1499 | } |
| 1500 | 1500 | ||
| 1501 | const CapturedStdIo = void; // TODO get it from Configuration | ||
| 1502 | |||
| 1501 | fn populateGeneratedPaths( | 1503 | fn populateGeneratedPaths( |
| 1502 | arena: std.mem.Allocator, | 1504 | arena: std.mem.Allocator, |
| 1503 | output_placeholders: []const IndexedOutput, | 1505 | output_placeholders: []const IndexedOutput, |
| ... | @@ -1545,17 +1547,19 @@ const FuzzContext = struct { | ... | @@ -1545,17 +1547,19 @@ const FuzzContext = struct { |
| 1545 | 1547 | ||
| 1546 | fn runCommand( | 1548 | fn runCommand( |
| 1547 | run: *Run, | 1549 | run: *Run, |
| 1550 | maker: *Maker, | ||
| 1551 | progress_node: std.Progress.Node, | ||
| 1548 | argv: []const []const u8, | 1552 | argv: []const []const u8, |
| 1549 | has_side_effects: bool, | 1553 | has_side_effects: bool, |
| 1550 | output_dir_path: []const u8, | 1554 | output_dir_path: []const u8, |
| 1551 | options: Step.MakeOptions, | ||
| 1552 | fuzz_context: ?FuzzContext, | 1555 | fuzz_context: ?FuzzContext, |
| 1553 | ) !void { | 1556 | ) !void { |
| 1557 | const graph = maker.graph; | ||
| 1558 | const arena = graph.arena; // TODO don't leak into process arena | ||
| 1559 | const gpa = maker.gpa; | ||
| 1554 | const step = &run.step; | 1560 | const step = &run.step; |
| 1555 | const b = step.owner; | 1561 | const b = step.owner; |
| 1556 | const arena = b.allocator; | 1562 | const io = graph.io; |
| 1557 | const gpa = options.gpa; | ||
| 1558 | const io = b.graph.io; | ||
| 1559 | 1563 | ||
| 1560 | const cwd: process.Child.Cwd = if (run.cwd) |lazy_cwd| .{ .path = lazy_cwd.getPath2(b, step) } else .inherit; | 1564 | const cwd: process.Child.Cwd = if (run.cwd) |lazy_cwd| .{ .path = lazy_cwd.getPath2(b, step) } else .inherit; |
| 1561 | 1565 | ||
| ... | @@ -1571,12 +1575,12 @@ fn runCommand( | ... | @@ -1571,12 +1575,12 @@ fn runCommand( |
| 1571 | defer interp_argv.deinit(); | 1575 | defer interp_argv.deinit(); |
| 1572 | 1576 | ||
| 1573 | var environ_map: EnvMap = env: { | 1577 | var environ_map: EnvMap = env: { |
| 1574 | const orig = run.environ_map orelse &b.graph.environ_map; | 1578 | const orig = run.environ_map orelse &graph.environ_map; |
| 1575 | break :env try orig.clone(gpa); | 1579 | break :env try orig.clone(gpa); |
| 1576 | }; | 1580 | }; |
| 1577 | defer environ_map.deinit(); | 1581 | defer environ_map.deinit(); |
| 1578 | 1582 | ||
| 1579 | const opt_generic_result = spawnChildAndCollect(run, argv, &environ_map, has_side_effects, options, fuzz_context) catch |err| term: { | 1583 | const opt_generic_result = spawnChildAndCollect(run, maker, progress_node, argv, &environ_map, has_side_effects, fuzz_context) catch |err| term: { |
| 1580 | // InvalidExe: cpu arch mismatch | 1584 | // InvalidExe: cpu arch mismatch |
| 1581 | // FileNotFound: can happen with a wrong dynamic linker path | 1585 | // FileNotFound: can happen with a wrong dynamic linker path |
| 1582 | if (err == error.InvalidExe or err == error.FileNotFound) interpret: { | 1586 | if (err == error.InvalidExe or err == error.FileNotFound) interpret: { |
| ... | @@ -1597,7 +1601,7 @@ fn runCommand( | ... | @@ -1597,7 +1601,7 @@ fn runCommand( |
| 1597 | const need_cross_libc = exe.is_linking_libc and | 1601 | const need_cross_libc = exe.is_linking_libc and |
| 1598 | (root_target.isGnuLibC() or (root_target.isMuslLibC() and exe.linkage == .dynamic)); | 1602 | (root_target.isGnuLibC() or (root_target.isMuslLibC() and exe.linkage == .dynamic)); |
| 1599 | const other_target = exe.root_module.resolved_target.?.result; | 1603 | const other_target = exe.root_module.resolved_target.?.result; |
| 1600 | switch (std.zig.system.getExternalExecutor(io, &b.graph.host.result, &other_target, .{ | 1604 | switch (std.zig.system.getExternalExecutor(io, &graph.host.result, &other_target, .{ |
| 1601 | .qemu_fixes_dl = need_cross_libc and b.libc_runtimes_dir != null, | 1605 | .qemu_fixes_dl = need_cross_libc and b.libc_runtimes_dir != null, |
| 1602 | .link_libc = exe.is_linking_libc, | 1606 | .link_libc = exe.is_linking_libc, |
| 1603 | })) { | 1607 | })) { |
| ... | @@ -1669,7 +1673,7 @@ fn runCommand( | ... | @@ -1669,7 +1673,7 @@ fn runCommand( |
| 1669 | .bad_dl => |foreign_dl| { | 1673 | .bad_dl => |foreign_dl| { |
| 1670 | if (allow_skip) return error.MakeSkipped; | 1674 | if (allow_skip) return error.MakeSkipped; |
| 1671 | 1675 | ||
| 1672 | const host_dl = b.graph.host.result.dynamic_linker.get() orelse "(none)"; | 1676 | const host_dl = graph.host.result.dynamic_linker.get() orelse "(none)"; |
| 1673 | 1677 | ||
| 1674 | return step.fail( | 1678 | return step.fail( |
| 1675 | \\the host system is unable to execute binaries from the target | 1679 | \\the host system is unable to execute binaries from the target |
| ... | @@ -1681,7 +1685,7 @@ fn runCommand( | ... | @@ -1681,7 +1685,7 @@ fn runCommand( |
| 1681 | .bad_os_or_cpu => { | 1685 | .bad_os_or_cpu => { |
| 1682 | if (allow_skip) return error.MakeSkipped; | 1686 | if (allow_skip) return error.MakeSkipped; |
| 1683 | 1687 | ||
| 1684 | const host_name = try b.graph.host.result.zigTriple(b.allocator); | 1688 | const host_name = try graph.host.result.zigTriple(b.allocator); |
| 1685 | const foreign_name = try root_target.zigTriple(b.allocator); | 1689 | const foreign_name = try root_target.zigTriple(b.allocator); |
| 1686 | 1690 | ||
| 1687 | return step.fail("the host system ({s}) is unable to execute binaries from the target ({s})", .{ | 1691 | return step.fail("the host system ({s}) is unable to execute binaries from the target ({s})", .{ |
| ... | @@ -1692,14 +1696,14 @@ fn runCommand( | ... | @@ -1692,14 +1696,14 @@ fn runCommand( |
| 1692 | 1696 | ||
| 1693 | if (root_target.os.tag == .windows) { | 1697 | if (root_target.os.tag == .windows) { |
| 1694 | // On Windows we don't have rpaths so we have to add .dll search paths to PATH | 1698 | // On Windows we don't have rpaths so we have to add .dll search paths to PATH |
| 1695 | run.addPathForDynLibs(exe); | 1699 | addPathForDynLibs(exe); |
| 1696 | } | 1700 | } |
| 1697 | 1701 | ||
| 1698 | gpa.free(step.result_failed_command.?); | 1702 | gpa.free(step.result_failed_command.?); |
| 1699 | step.result_failed_command = null; | 1703 | step.result_failed_command = null; |
| 1700 | try Step.handleVerbose2(step.owner, cwd, run.environ_map, interp_argv.items); | 1704 | try Step.handleVerbose2(step.owner, cwd, run.environ_map, interp_argv.items); |
| 1701 | 1705 | ||
| 1702 | break :term spawnChildAndCollect(run, interp_argv.items, &environ_map, has_side_effects, options, fuzz_context) catch |e| { | 1706 | break :term spawnChildAndCollect(run, maker, progress_node, interp_argv.items, &environ_map, has_side_effects, fuzz_context) catch |e| { |
| 1703 | if (!run.failing_to_execute_foreign_is_an_error) return error.MakeSkipped; | 1707 | if (!run.failing_to_execute_foreign_is_an_error) return error.MakeSkipped; |
| 1704 | if (e == error.MakeFailed) return error.MakeFailed; // error already reported | 1708 | if (e == error.MakeFailed) return error.MakeFailed; // error already reported |
| 1705 | return step.fail("unable to spawn interpreter {s}: {t}", .{ interp_argv.items[0], e }); | 1709 | return step.fail("unable to spawn interpreter {s}: {t}", .{ interp_argv.items[0], e }); |
| ... | @@ -1851,14 +1855,16 @@ const EvalGenericResult = struct { | ... | @@ -1851,14 +1855,16 @@ const EvalGenericResult = struct { |
| 1851 | 1855 | ||
| 1852 | fn spawnChildAndCollect( | 1856 | fn spawnChildAndCollect( |
| 1853 | run: *Run, | 1857 | run: *Run, |
| 1858 | maker: *Maker, | ||
| 1859 | progress_node: std.Progress.Node, | ||
| 1854 | argv: []const []const u8, | 1860 | argv: []const []const u8, |
| 1855 | environ_map: *EnvMap, | 1861 | environ_map: *EnvMap, |
| 1856 | has_side_effects: bool, | 1862 | has_side_effects: bool, |
| 1857 | options: Step.MakeOptions, | ||
| 1858 | fuzz_context: ?FuzzContext, | 1863 | fuzz_context: ?FuzzContext, |
| 1859 | ) !?EvalGenericResult { | 1864 | ) !?EvalGenericResult { |
| 1860 | const b = run.step.owner; | 1865 | const b = run.step.owner; |
| 1861 | const graph = b.graph; | 1866 | const graph = maker.graph; |
| 1867 | const gpa = maker.gpa; | ||
| 1862 | const io = graph.io; | 1868 | const io = graph.io; |
| 1863 | 1869 | ||
| 1864 | if (fuzz_context != null) { | 1870 | if (fuzz_context != null) { |
| ... | @@ -1870,7 +1876,7 @@ fn spawnChildAndCollect( | ... | @@ -1870,7 +1876,7 @@ fn spawnChildAndCollect( |
| 1870 | 1876 | ||
| 1871 | // If an error occurs, it's caused by this command: | 1877 | // If an error occurs, it's caused by this command: |
| 1872 | assert(run.step.result_failed_command == null); | 1878 | assert(run.step.result_failed_command == null); |
| 1873 | run.step.result_failed_command = try Step.allocPrintCmd(options.gpa, child_cwd, .{ | 1879 | run.step.result_failed_command = try Step.allocPrintCmd(gpa, child_cwd, .{ |
| 1874 | .child = environ_map, | 1880 | .child = environ_map, |
| 1875 | .parent = &graph.environ_map, | 1881 | .parent = &graph.environ_map, |
| 1876 | }, argv); | 1882 | }, argv); |
| ... | @@ -1905,7 +1911,7 @@ fn spawnChildAndCollect( | ... | @@ -1905,7 +1911,7 @@ fn spawnChildAndCollect( |
| 1905 | 1911 | ||
| 1906 | if (run.stdio == .zig_test) { | 1912 | if (run.stdio == .zig_test) { |
| 1907 | const started: Io.Clock.Timestamp = .now(io, .awake); | 1913 | const started: Io.Clock.Timestamp = .now(io, .awake); |
| 1908 | const result = evalZigTest(run, spawn_options, options, fuzz_context) catch |err| switch (err) { | 1914 | const result = evalZigTest(run, maker, progress_node, spawn_options, fuzz_context) catch |err| switch (err) { |
| 1909 | error.Canceled => |e| return e, | 1915 | error.Canceled => |e| return e, |
| 1910 | else => |e| e, | 1916 | else => |e| e, |
| 1911 | }; | 1917 | }; |
| ... | @@ -1915,7 +1921,7 @@ fn spawnChildAndCollect( | ... | @@ -1915,7 +1921,7 @@ fn spawnChildAndCollect( |
| 1915 | } else { | 1921 | } else { |
| 1916 | const inherit = spawn_options.stdout == .inherit or spawn_options.stderr == .inherit; | 1922 | const inherit = spawn_options.stdout == .inherit or spawn_options.stderr == .inherit; |
| 1917 | if (!run.disable_zig_progress and !inherit) { | 1923 | if (!run.disable_zig_progress and !inherit) { |
| 1918 | spawn_options.progress_node = options.progress_node; | 1924 | spawn_options.progress_node = progress_node; |
| 1919 | } | 1925 | } |
| 1920 | const terminal_mode: Io.Terminal.Mode = if (inherit) m: { | 1926 | const terminal_mode: Io.Terminal.Mode = if (inherit) m: { |
| 1921 | const stderr = try io.lockStderr(&.{}, graph.stderr_mode); | 1927 | const stderr = try io.lockStderr(&.{}, graph.stderr_mode); |
| ... | @@ -1925,7 +1931,7 @@ fn spawnChildAndCollect( | ... | @@ -1925,7 +1931,7 @@ fn spawnChildAndCollect( |
| 1925 | try setColorEnvironmentVariables(run, environ_map, terminal_mode); | 1931 | try setColorEnvironmentVariables(run, environ_map, terminal_mode); |
| 1926 | 1932 | ||
| 1927 | const started: Io.Clock.Timestamp = .now(io, .awake); | 1933 | const started: Io.Clock.Timestamp = .now(io, .awake); |
| 1928 | const result = evalGeneric(run, spawn_options) catch |err| switch (err) { | 1934 | const result = evalGeneric(run, maker, spawn_options) catch |err| switch (err) { |
| 1929 | error.Canceled => |e| return e, | 1935 | error.Canceled => |e| return e, |
| 1930 | else => |e| e, | 1936 | else => |e| e, |
| 1931 | }; | 1937 | }; |
| ... | @@ -1934,11 +1940,11 @@ fn spawnChildAndCollect( | ... | @@ -1934,11 +1940,11 @@ fn spawnChildAndCollect( |
| 1934 | } | 1940 | } |
| 1935 | } | 1941 | } |
| 1936 | 1942 | ||
| 1937 | fn hashStdIo(hh: *Cache.HashHelper, stdio: StdIo) void { | 1943 | fn hashStdIo(hh: *Cache.HashHelper, stdio: void) void { |
| 1938 | switch (stdio) { | 1944 | switch (stdio) { |
| 1939 | .infer_from_args, .inherit, .zig_test => {}, | 1945 | .infer_from_args, .inherit, .zig_test => {}, |
| 1940 | .check => |checks| for (checks.items) |check| { | 1946 | .check => |checks| for (checks.items) |check| { |
| 1941 | hh.add(@as(std.meta.Tag(StdIo.Check), check)); | 1947 | hh.add(@as(std.meta.Tag(@This().StdIo.Check), check)); |
| 1942 | switch (check) { | 1948 | switch (check) { |
| 1943 | .expect_stderr_exact, | 1949 | .expect_stderr_exact, |
| 1944 | .expect_stderr_match, | 1950 | .expect_stderr_match, |
| ... | @@ -2010,7 +2016,7 @@ fn setColorEnvironmentVariables(run: *Run, environ_map: *EnvMap, terminal_mode: | ... | @@ -2010,7 +2016,7 @@ fn setColorEnvironmentVariables(run: *Run, environ_map: *EnvMap, terminal_mode: |
| 2010 | } | 2016 | } |
| 2011 | } | 2017 | } |
| 2012 | 2018 | ||
| 2013 | fn checksContainStdout(checks: []const StdIo.Check) bool { | 2019 | fn checksContainStdout(checks: []const @This().StdIo.Check) bool { |
| 2014 | for (checks) |check| switch (check) { | 2020 | for (checks) |check| switch (check) { |
| 2015 | .expect_stderr_exact, | 2021 | .expect_stderr_exact, |
| 2016 | .expect_stderr_match, | 2022 | .expect_stderr_match, |
| ... | @@ -2024,7 +2030,7 @@ fn checksContainStdout(checks: []const StdIo.Check) bool { | ... | @@ -2024,7 +2030,7 @@ fn checksContainStdout(checks: []const StdIo.Check) bool { |
| 2024 | return false; | 2030 | return false; |
| 2025 | } | 2031 | } |
| 2026 | 2032 | ||
| 2027 | fn checksContainStderr(checks: []const StdIo.Check) bool { | 2033 | fn checksContainStderr(checks: []const @This().StdIo.Check) bool { |
| 2028 | for (checks) |check| switch (check) { | 2034 | for (checks) |check| switch (check) { |
| 2029 | .expect_stdout_exact, | 2035 | .expect_stdout_exact, |
| 2030 | .expect_stdout_match, | 2036 | .expect_stdout_match, |
| ... | @@ -2063,9 +2069,9 @@ fn hasAnyOutputArgs(run: Run) bool { | ... | @@ -2063,9 +2069,9 @@ fn hasAnyOutputArgs(run: Run) bool { |
| 2063 | /// | 2069 | /// |
| 2064 | /// Whenever a path is included in the argv of a child, it should be put through this function first | 2070 | /// Whenever a path is included in the argv of a child, it should be put through this function first |
| 2065 | /// to make sure the child doesn't see paths relative to a cwd other than its own. | 2071 | /// to make sure the child doesn't see paths relative to a cwd other than its own. |
| 2066 | fn convertPathArg(run: *Run, path: Build.Cache.Path) []const u8 { | 2072 | fn convertPathArg(run: *Run, maker: *Maker, path: Path) []const u8 { |
| 2067 | const b = run.step.owner; | 2073 | const b = run.step.owner; |
| 2068 | const graph = b.graph; | 2074 | const graph = maker.graph; |
| 2069 | const arena = graph.arena; | 2075 | const arena = graph.arena; |
| 2070 | 2076 | ||
| 2071 | const path_str = path.toString(arena) catch @panic("OOM"); | 2077 | const path_str = path.toString(arena) catch @panic("OOM"); |
| ... | @@ -2091,40 +2097,43 @@ fn convertPathArg(run: *Run, path: Build.Cache.Path) []const u8 { | ... | @@ -2091,40 +2097,43 @@ fn convertPathArg(run: *Run, path: Build.Cache.Path) []const u8 { |
| 2091 | return Dir.path.join(arena, &.{ ".", child_cwd_rel }) catch @panic("OOM"); | 2097 | return Dir.path.join(arena, &.{ ".", child_cwd_rel }) catch @panic("OOM"); |
| 2092 | } | 2098 | } |
| 2093 | 2099 | ||
| 2094 | fn addPathForDynLibs(run: *Run, artifact: *Step.Compile) void { | 2100 | fn addPathForDynLibs(artifact: *Step.Compile) void { |
| 2095 | const b = run.step.owner; | 2101 | if (true) @panic("TODO"); |
| 2096 | const compiles = artifact.getCompileDependencies(true); | 2102 | for (artifact.getCompileDependencies(true)) |compile| { |
| 2097 | for (compiles) |compile| { | ||
| 2098 | if (compile.root_module.resolved_target.?.result.os.tag == .windows and | 2103 | if (compile.root_module.resolved_target.?.result.os.tag == .windows and |
| 2099 | compile.isDynamicLibrary()) | 2104 | compile.isDynamicLibrary()) |
| 2100 | { | 2105 | { |
| 2101 | addPathDir(run, Dir.path.dirname(compile.getEmittedBin().getPath2(b, &run.step)).?); | 2106 | @panic("TODO"); |
| 2107 | //addPathDir(run, Dir.path.dirname(compile.getEmittedBin().getPath2(b, &run.step)).?); | ||
| 2102 | } | 2108 | } |
| 2103 | } | 2109 | } |
| 2104 | } | 2110 | } |
| 2105 | 2111 | ||
| 2106 | fn failForeign( | 2112 | fn failForeign( |
| 2107 | run: *Run, | 2113 | run: *Run, |
| 2114 | maker: *Maker, | ||
| 2115 | step_index: Configuration.Step.Index, | ||
| 2108 | suggested_flag: []const u8, | 2116 | suggested_flag: []const u8, |
| 2109 | argv0: []const u8, | 2117 | argv0: []const u8, |
| 2110 | exe: *Step.Compile, | 2118 | exe: *Step.Compile, |
| 2111 | ) error{ MakeFailed, MakeSkipped, OutOfMemory } { | 2119 | ) Step.ExtendedMakeError { |
| 2120 | const step = maker.stepByIndex(step_index); | ||
| 2112 | switch (run.stdio) { | 2121 | switch (run.stdio) { |
| 2113 | .check, .zig_test => { | 2122 | .check, .zig_test => { |
| 2114 | if (run.skip_foreign_checks) | 2123 | if (run.skip_foreign_checks) return error.MakeSkipped; |
| 2115 | return error.MakeSkipped; | ||
| 2116 | 2124 | ||
| 2117 | const b = run.step.owner; | 2125 | const graph = maker.graph; |
| 2118 | const host_name = try b.graph.host.result.zigTriple(b.allocator); | 2126 | const process_arena = graph.arena; // TODO don't leak into process arena |
| 2119 | const foreign_name = try exe.rootModuleTarget().zigTriple(b.allocator); | 2127 | const host_name = try graph.host.result.zigTriple(process_arena); |
| 2128 | const foreign_name = try exe.rootModuleTarget().zigTriple(process_arena); | ||
| 2120 | 2129 | ||
| 2121 | return run.step.fail( | 2130 | return step.fail( |
| 2122 | \\unable to spawn foreign binary '{s}' ({s}) on host system ({s}) | 2131 | \\unable to spawn foreign binary '{s}' ({s}) on host system ({s}) |
| 2123 | \\ consider using {s} or enabling skip_foreign_checks in the Run step | 2132 | \\ consider using {s} or enabling skip_foreign_checks in the Run step |
| 2124 | , .{ argv0, foreign_name, host_name, suggested_flag }); | 2133 | , .{ argv0, foreign_name, host_name, suggested_flag }); |
| 2125 | }, | 2134 | }, |
| 2126 | else => { | 2135 | else => { |
| 2127 | return run.step.fail("unable to spawn foreign binary '{s}'", .{argv0}); | 2136 | return step.fail("unable to spawn foreign binary '{s}'", .{argv0}); |
| 2128 | }, | 2137 | }, |
| 2129 | } | 2138 | } |
| 2130 | } | 2139 | } |
lib/compiler/Maker/Watch.zig+45-38| ... | @@ -10,6 +10,7 @@ const Configuration = std.Build.Configuration; | ... | @@ -10,6 +10,7 @@ const Configuration = std.Build.Configuration; |
| 10 | 10 | ||
| 11 | const FsEvents = @import("Watch/FsEvents.zig"); | 11 | const FsEvents = @import("Watch/FsEvents.zig"); |
| 12 | const Step = @import("Step.zig"); | 12 | const Step = @import("Step.zig"); |
| 13 | const Maker = @import("../Maker.zig"); | ||
| 13 | 14 | ||
| 14 | os: Os, | 15 | os: Os, |
| 15 | /// The number to show as the number of directories being watched. | 16 | /// The number to show as the number of directories being watched. |
| ... | @@ -18,8 +19,7 @@ dir_count: usize, | ... | @@ -18,8 +19,7 @@ dir_count: usize, |
| 18 | // They are `undefined` on implementations which do not utilize then. | 19 | // They are `undefined` on implementations which do not utilize then. |
| 19 | dir_table: DirTable, | 20 | dir_table: DirTable, |
| 20 | generation: Generation, | 21 | generation: Generation, |
| 21 | configuration: *const Configuration, | 22 | maker: *Maker, |
| 22 | make_steps: []Step, | ||
| 23 | 23 | ||
| 24 | pub const have_impl = Os != void; | 24 | pub const have_impl = Os != void; |
| 25 | 25 | ||
| ... | @@ -105,8 +105,7 @@ const Os = switch (builtin.os.tag) { | ... | @@ -105,8 +105,7 @@ const Os = switch (builtin.os.tag) { |
| 105 | }; | 105 | }; |
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | fn init(cwd_path: []const u8, configuration: *const Configuration, make_steps: []Step) !Watch { | 108 | fn init(maker: *Maker) !Watch { |
| 109 | _ = cwd_path; | ||
| 110 | return .{ | 109 | return .{ |
| 111 | .dir_table = .{}, | 110 | .dir_table = .{}, |
| 112 | .dir_count = 0, | 111 | .dir_count = 0, |
| ... | @@ -118,8 +117,7 @@ const Os = switch (builtin.os.tag) { | ... | @@ -118,8 +117,7 @@ const Os = switch (builtin.os.tag) { |
| 118 | else => {}, | 117 | else => {}, |
| 119 | }, | 118 | }, |
| 120 | .generation = 0, | 119 | .generation = 0, |
| 121 | .make_steps = make_steps, | 120 | .maker = maker, |
| 122 | .configuration = configuration, | ||
| 123 | }; | 121 | }; |
| 124 | } | 122 | } |
| 125 | 123 | ||
| ... | @@ -136,7 +134,8 @@ const Os = switch (builtin.os.tag) { | ... | @@ -136,7 +134,8 @@ const Os = switch (builtin.os.tag) { |
| 136 | return stack_lfh.clone(gpa); | 134 | return stack_lfh.clone(gpa); |
| 137 | } | 135 | } |
| 138 | 136 | ||
| 139 | fn markDirtySteps(w: *Watch, gpa: Allocator, fan_fd: posix.fd_t) !bool { | 137 | fn markDirtySteps(w: *Watch, fan_fd: posix.fd_t) !bool { |
| 138 | const maker = w.maker; | ||
| 140 | const fanotify = std.os.linux.fanotify; | 139 | const fanotify = std.os.linux.fanotify; |
| 141 | const M = fanotify.event_metadata; | 140 | const M = fanotify.event_metadata; |
| 142 | var events_buf: [256 + 4096]u8 = undefined; | 141 | var events_buf: [256 + 4096]u8 = undefined; |
| ... | @@ -155,7 +154,7 @@ const Os = switch (builtin.os.tag) { | ... | @@ -155,7 +154,7 @@ const Os = switch (builtin.os.tag) { |
| 155 | if (meta[0].mask.Q_OVERFLOW) { | 154 | if (meta[0].mask.Q_OVERFLOW) { |
| 156 | any_dirty = true; | 155 | any_dirty = true; |
| 157 | std.log.warn("file system watch queue overflowed; falling back to fstat", .{}); | 156 | std.log.warn("file system watch queue overflowed; falling back to fstat", .{}); |
| 158 | markAllFilesDirty(w, gpa); | 157 | markAllFilesDirty(w); |
| 159 | return true; | 158 | return true; |
| 160 | } | 159 | } |
| 161 | const fid: *align(1) fanotify.event_info_fid = @ptrCast(meta + 1); | 160 | const fid: *align(1) fanotify.event_info_fid = @ptrCast(meta + 1); |
| ... | @@ -167,9 +166,9 @@ const Os = switch (builtin.os.tag) { | ... | @@ -167,9 +166,9 @@ const Os = switch (builtin.os.tag) { |
| 167 | const lfh: FileHandle = .{ .handle = file_handle }; | 166 | const lfh: FileHandle = .{ .handle = file_handle }; |
| 168 | if (w.os.handle_table.getPtr(lfh)) |value| { | 167 | if (w.os.handle_table.getPtr(lfh)) |value| { |
| 169 | if (value.reaction_set.getPtr(".")) |glob_set| | 168 | if (value.reaction_set.getPtr(".")) |glob_set| |
| 170 | any_dirty = markStepSetDirty(gpa, w.make_steps, glob_set, any_dirty); | 169 | any_dirty = markStepSetDirty(maker, glob_set, any_dirty); |
| 171 | if (value.reaction_set.getPtr(file_name)) |step_set| | 170 | if (value.reaction_set.getPtr(file_name)) |step_set| |
| 172 | any_dirty = markStepSetDirty(gpa, w.make_steps, step_set, any_dirty); | 171 | any_dirty = markStepSetDirty(maker, step_set, any_dirty); |
| 173 | } | 172 | } |
| 174 | }, | 173 | }, |
| 175 | else => |t| std.log.warn("unexpected fanotify event '{t}'", .{t}), | 174 | else => |t| std.log.warn("unexpected fanotify event '{t}'", .{t}), |
| ... | @@ -179,9 +178,11 @@ const Os = switch (builtin.os.tag) { | ... | @@ -179,9 +178,11 @@ const Os = switch (builtin.os.tag) { |
| 179 | } | 178 | } |
| 180 | 179 | ||
| 181 | fn update(w: *Watch, gpa: Allocator, steps: []const Configuration.Step.Index) !void { | 180 | fn update(w: *Watch, gpa: Allocator, steps: []const Configuration.Step.Index) !void { |
| 181 | const maker = w.maker; | ||
| 182 | |||
| 182 | // Add missing marks and note persisted ones. | 183 | // Add missing marks and note persisted ones. |
| 183 | for (steps) |step_index| { | 184 | for (steps) |step_index| { |
| 184 | const step = &w.make_steps[@intFromEnum(step_index)]; | 185 | const step = maker.stepByIndex(step_index); |
| 185 | for (step.inputs.table.keys(), step.inputs.table.values()) |path, *files| { | 186 | for (step.inputs.table.keys(), step.inputs.table.values()) |path, *files| { |
| 186 | const reaction_set = rs: { | 187 | const reaction_set = rs: { |
| 187 | const gop = try w.dir_table.getOrPut(gpa, path); | 188 | const gop = try w.dir_table.getOrPut(gpa, path); |
| ... | @@ -298,13 +299,12 @@ const Os = switch (builtin.os.tag) { | ... | @@ -298,13 +299,12 @@ const Os = switch (builtin.os.tag) { |
| 298 | w.dir_count = w.dir_table.count(); | 299 | w.dir_count = w.dir_table.count(); |
| 299 | } | 300 | } |
| 300 | 301 | ||
| 301 | fn wait(w: *Watch, gpa: Allocator, io: Io, timeout: Timeout) !WaitResult { | 302 | fn wait(w: *Watch, timeout: Timeout) !WaitResult { |
| 302 | _ = io; | ||
| 303 | const events_len = try std.posix.poll(w.os.poll_fds.values(), timeout.to_i32_ms()); | 303 | const events_len = try std.posix.poll(w.os.poll_fds.values(), timeout.to_i32_ms()); |
| 304 | if (events_len == 0) | 304 | if (events_len == 0) |
| 305 | return .timeout; | 305 | return .timeout; |
| 306 | for (w.os.poll_fds.values()) |poll_fd| { | 306 | for (w.os.poll_fds.values()) |poll_fd| { |
| 307 | if (poll_fd.revents & std.posix.POLL.IN == std.posix.POLL.IN and try markDirtySteps(w, gpa, poll_fd.fd)) | 307 | if (poll_fd.revents & std.posix.POLL.IN == std.posix.POLL.IN and try markDirtySteps(w, poll_fd.fd)) |
| 308 | return .dirty; | 308 | return .dirty; |
| 309 | } | 309 | } |
| 310 | return .clean; | 310 | return .clean; |
| ... | @@ -515,12 +515,14 @@ const Os = switch (builtin.os.tag) { | ... | @@ -515,12 +515,14 @@ const Os = switch (builtin.os.tag) { |
| 515 | return file_id; | 515 | return file_id; |
| 516 | } | 516 | } |
| 517 | 517 | ||
| 518 | fn markDirtySteps(w: *Watch, gpa: Allocator, dir: *Directory) !bool { | 518 | fn markDirtySteps(w: *Watch, dir: *Directory) !bool { |
| 519 | const maker = w.maker; | ||
| 520 | |||
| 519 | var any_dirty = false; | 521 | var any_dirty = false; |
| 520 | const bytes_returned = dir.iosb.Information; | 522 | const bytes_returned = dir.iosb.Information; |
| 521 | if (bytes_returned == 0) { | 523 | if (bytes_returned == 0) { |
| 522 | std.log.warn("file system watch queue overflowed; falling back to fstat", .{}); | 524 | std.log.warn("file system watch queue overflowed; falling back to fstat", .{}); |
| 523 | markAllFilesDirty(w, gpa); | 525 | markAllFilesDirty(w); |
| 524 | try dir.startListening(w); | 526 | try dir.startListening(w); |
| 525 | return true; | 527 | return true; |
| 526 | } | 528 | } |
| ... | @@ -530,9 +532,9 @@ const Os = switch (builtin.os.tag) { | ... | @@ -530,9 +532,9 @@ const Os = switch (builtin.os.tag) { |
| 530 | const notify: *windows.FILE.NOTIFY.INFORMATION = @ptrCast(@alignCast(&dir.buffer[offset])); | 532 | const notify: *windows.FILE.NOTIFY.INFORMATION = @ptrCast(@alignCast(&dir.buffer[offset])); |
| 531 | const file_name = file_name_buf[0..std.unicode.wtf16LeToWtf8(&file_name_buf, notify.fileName())]; | 533 | const file_name = file_name_buf[0..std.unicode.wtf16LeToWtf8(&file_name_buf, notify.fileName())]; |
| 532 | if (dir.reaction_set.getPtr(".")) |glob_set| | 534 | if (dir.reaction_set.getPtr(".")) |glob_set| |
| 533 | any_dirty = markStepSetDirty(gpa, glob_set, any_dirty); | 535 | any_dirty = markStepSetDirty(maker, glob_set, any_dirty); |
| 534 | if (dir.reaction_set.getPtr(file_name)) |step_set| | 536 | if (dir.reaction_set.getPtr(file_name)) |step_set| |
| 535 | any_dirty = markStepSetDirty(gpa, step_set, any_dirty); | 537 | any_dirty = markStepSetDirty(maker, step_set, any_dirty); |
| 536 | if (notify.NextEntryOffset == 0) | 538 | if (notify.NextEntryOffset == 0) |
| 537 | break; | 539 | break; |
| 538 | 540 | ||
| ... | @@ -619,14 +621,17 @@ const Os = switch (builtin.os.tag) { | ... | @@ -619,14 +621,17 @@ const Os = switch (builtin.os.tag) { |
| 619 | w.dir_count = w.dir_table.count(); | 621 | w.dir_count = w.dir_table.count(); |
| 620 | } | 622 | } |
| 621 | 623 | ||
| 622 | fn wait(w: *Watch, gpa: Allocator, io: Io, timeout: Timeout) !WaitResult { | 624 | fn wait(w: *Watch, timeout: Timeout) !WaitResult { |
| 625 | const maker = w.maker; | ||
| 626 | const io = maker.graph.io; | ||
| 627 | |||
| 623 | for (0..2) |attempt| { | 628 | for (0..2) |attempt| { |
| 624 | while (w.os.ready_dirs.popFirst()) |ready_node| { | 629 | while (w.os.ready_dirs.popFirst()) |ready_node| { |
| 625 | const dir: *Directory = @fieldParentPtr("ready_node", ready_node); | 630 | const dir: *Directory = @fieldParentPtr("ready_node", ready_node); |
| 626 | assert(dir.state == .ready); | 631 | assert(dir.state == .ready); |
| 627 | dir.state = .idle; | 632 | dir.state = .idle; |
| 628 | switch (dir.iosb.u.Status) { | 633 | switch (dir.iosb.u.Status) { |
| 629 | .SUCCESS => return if (try markDirtySteps(w, gpa, dir)) .dirty else .clean, | 634 | .SUCCESS => return if (try markDirtySteps(w, dir)) .dirty else .clean, |
| 630 | .PENDING => unreachable, | 635 | .PENDING => unreachable, |
| 631 | .CANCELLED => {}, | 636 | .CANCELLED => {}, |
| 632 | else => |status| return windows.unexpectedStatus(status), | 637 | else => |status| return windows.unexpectedStatus(status), |
| ... | @@ -810,25 +815,25 @@ const Os = switch (builtin.os.tag) { | ... | @@ -810,25 +815,25 @@ const Os = switch (builtin.os.tag) { |
| 810 | w.dir_count = w.dir_table.count(); | 815 | w.dir_count = w.dir_table.count(); |
| 811 | } | 816 | } |
| 812 | 817 | ||
| 813 | fn wait(w: *Watch, gpa: Allocator, io: Io, timeout: Timeout) !WaitResult { | 818 | fn wait(w: *Watch, timeout: Timeout) !WaitResult { |
| 814 | _ = io; | 819 | const maker = w.maker; |
| 815 | var timespec_buffer: posix.timespec = undefined; | 820 | var timespec_buffer: posix.timespec = undefined; |
| 816 | var event_buffer: [100]posix.Kevent = undefined; | 821 | var event_buffer: [100]posix.Kevent = undefined; |
| 817 | var n = try Io.Kqueue.kevent(w.os.kq_fd, &.{}, &event_buffer, timeout.toTimespec(&timespec_buffer)); | 822 | var n = try Io.Kqueue.kevent(w.os.kq_fd, &.{}, &event_buffer, timeout.toTimespec(&timespec_buffer)); |
| 818 | if (n == 0) return .timeout; | 823 | if (n == 0) return .timeout; |
| 819 | const reaction_sets = w.os.handles.items(.rs); | 824 | const reaction_sets = w.os.handles.items(.rs); |
| 820 | var any_dirty = markDirtySteps(gpa, reaction_sets, event_buffer[0..n], false); | 825 | var any_dirty = markDirtySteps(maker, reaction_sets, event_buffer[0..n], false); |
| 821 | timespec_buffer = .{ .sec = 0, .nsec = 0 }; | 826 | timespec_buffer = .{ .sec = 0, .nsec = 0 }; |
| 822 | while (n == event_buffer.len) { | 827 | while (n == event_buffer.len) { |
| 823 | n = try Io.Kqueue.kevent(w.os.kq_fd, &.{}, &event_buffer, &timespec_buffer); | 828 | n = try Io.Kqueue.kevent(w.os.kq_fd, &.{}, &event_buffer, &timespec_buffer); |
| 824 | if (n == 0) break; | 829 | if (n == 0) break; |
| 825 | any_dirty = markDirtySteps(gpa, reaction_sets, event_buffer[0..n], any_dirty); | 830 | any_dirty = markDirtySteps(maker, reaction_sets, event_buffer[0..n], any_dirty); |
| 826 | } | 831 | } |
| 827 | return if (any_dirty) .dirty else .clean; | 832 | return if (any_dirty) .dirty else .clean; |
| 828 | } | 833 | } |
| 829 | 834 | ||
| 830 | fn markDirtySteps( | 835 | fn markDirtySteps( |
| 831 | gpa: Allocator, | 836 | maker: *Maker, |
| 832 | reaction_sets: []ReactionSet, | 837 | reaction_sets: []ReactionSet, |
| 833 | events: []const std.c.Kevent, | 838 | events: []const std.c.Kevent, |
| 834 | start_any_dirty: bool, | 839 | start_any_dirty: bool, |
| ... | @@ -840,13 +845,13 @@ const Os = switch (builtin.os.tag) { | ... | @@ -840,13 +845,13 @@ const Os = switch (builtin.os.tag) { |
| 840 | // If we knew the basename of the changed file, here we would | 845 | // If we knew the basename of the changed file, here we would |
| 841 | // mark only the step set dirty, and possibly the glob set: | 846 | // mark only the step set dirty, and possibly the glob set: |
| 842 | //if (reaction_set.getPtr(".")) |glob_set| | 847 | //if (reaction_set.getPtr(".")) |glob_set| |
| 843 | // any_dirty = markStepSetDirty(gpa, glob_set, any_dirty); | 848 | // any_dirty = markStepSetDirty(maker, glob_set, any_dirty); |
| 844 | //if (reaction_set.getPtr(file_name)) |step_set| | 849 | //if (reaction_set.getPtr(file_name)) |step_set| |
| 845 | // any_dirty = markStepSetDirty(gpa, step_set, any_dirty); | 850 | // any_dirty = markStepSetDirty(maker, step_set, any_dirty); |
| 846 | // However we don't know the file name so just mark all the | 851 | // However we don't know the file name so just mark all the |
| 847 | // sets dirty for this directory. | 852 | // sets dirty for this directory. |
| 848 | for (reaction_set.values()) |*step_set| { | 853 | for (reaction_set.values()) |*step_set| { |
| 849 | any_dirty = markStepSetDirty(gpa, step_set, any_dirty); | 854 | any_dirty = markStepSetDirty(maker, step_set, any_dirty); |
| 850 | } | 855 | } |
| 851 | } | 856 | } |
| 852 | return any_dirty; | 857 | return any_dirty; |
| ... | @@ -878,8 +883,8 @@ const Os = switch (builtin.os.tag) { | ... | @@ -878,8 +883,8 @@ const Os = switch (builtin.os.tag) { |
| 878 | else => void, | 883 | else => void, |
| 879 | }; | 884 | }; |
| 880 | 885 | ||
| 881 | pub fn init(cwd_path: []const u8, configuration: *const Configuration, make_steps: []Step) !Watch { | 886 | pub fn init(maker: *Maker) !Watch { |
| 882 | return Os.init(cwd_path, configuration, make_steps); | 887 | return Os.init(maker); |
| 883 | } | 888 | } |
| 884 | 889 | ||
| 885 | pub const Match = struct { | 890 | pub const Match = struct { |
| ... | @@ -904,7 +909,9 @@ pub const Match = struct { | ... | @@ -904,7 +909,9 @@ pub const Match = struct { |
| 904 | }; | 909 | }; |
| 905 | }; | 910 | }; |
| 906 | 911 | ||
| 907 | fn markAllFilesDirty(w: *Watch, gpa: Allocator) void { | 912 | fn markAllFilesDirty(w: *Watch) void { |
| 913 | const maker = w.maker; | ||
| 914 | |||
| 908 | for (switch (builtin.os.tag) { | 915 | for (switch (builtin.os.tag) { |
| 909 | .windows => w.os.handle_table.keys(), | 916 | .windows => w.os.handle_table.keys(), |
| 910 | else => w.os.handle_table.values(), | 917 | else => w.os.handle_table.values(), |
| ... | @@ -915,18 +922,18 @@ fn markAllFilesDirty(w: *Watch, gpa: Allocator) void { | ... | @@ -915,18 +922,18 @@ fn markAllFilesDirty(w: *Watch, gpa: Allocator) void { |
| 915 | }; | 922 | }; |
| 916 | for (reaction_set.values()) |step_set| { | 923 | for (reaction_set.values()) |step_set| { |
| 917 | for (step_set.keys()) |step_index| { | 924 | for (step_set.keys()) |step_index| { |
| 918 | const step = &w.make_steps[@intFromEnum(step_index)]; | 925 | const step = maker.stepByIndex(step_index); |
| 919 | _ = step.invalidateResult(gpa); | 926 | _ = maker.invalidateResult(step); |
| 920 | } | 927 | } |
| 921 | } | 928 | } |
| 922 | } | 929 | } |
| 923 | } | 930 | } |
| 924 | 931 | ||
| 925 | fn markStepSetDirty(gpa: Allocator, make_steps: []Step, step_set: *StepSet, any_dirty: bool) bool { | 932 | fn markStepSetDirty(maker: *Maker, step_set: *StepSet, any_dirty: bool) bool { |
| 926 | var this_any_dirty = false; | 933 | var this_any_dirty = false; |
| 927 | for (step_set.keys()) |step_index| { | 934 | for (step_set.keys()) |step_index| { |
| 928 | const step = &make_steps[@intFromEnum(step_index)]; | 935 | const step = maker.stepByIndex(step_index); |
| 929 | if (step.invalidateResult(gpa)) this_any_dirty = true; | 936 | if (maker.invalidateResult(step)) this_any_dirty = true; |
| 930 | } | 937 | } |
| 931 | return any_dirty or this_any_dirty; | 938 | return any_dirty or this_any_dirty; |
| 932 | } | 939 | } |
| ... | @@ -971,6 +978,6 @@ pub const WaitResult = enum { | ... | @@ -971,6 +978,6 @@ pub const WaitResult = enum { |
| 971 | clean, | 978 | clean, |
| 972 | }; | 979 | }; |
| 973 | 980 | ||
| 974 | pub fn wait(w: *Watch, gpa: Allocator, io: Io, timeout: Timeout) !WaitResult { | 981 | pub fn wait(w: *Watch, timeout: Timeout) !WaitResult { |
| 975 | return Os.wait(w, gpa, io, timeout); | 982 | return Os.wait(w, timeout); |
| 976 | } | 983 | } |
lib/compiler/Maker/WebServer.zig+94-71| ... | @@ -14,16 +14,14 @@ const log = std.log.scoped(.web_server); | ... | @@ -14,16 +14,14 @@ const log = std.log.scoped(.web_server); |
| 14 | const mem = std.mem; | 14 | const mem = std.mem; |
| 15 | const net = std.Io.net; | 15 | const net = std.Io.net; |
| 16 | 16 | ||
| 17 | const Maker = @import("../Maker.zig"); | ||
| 17 | const Fuzz = @import("Fuzz.zig"); | 18 | const Fuzz = @import("Fuzz.zig"); |
| 18 | const Graph = @import("Graph.zig"); | 19 | const Graph = @import("Graph.zig"); |
| 19 | const Step = @import("Step.zig"); | 20 | const Step = @import("Step.zig"); |
| 20 | 21 | ||
| 21 | gpa: Allocator, | 22 | maker: *Maker, |
| 22 | graph: *const Graph, | ||
| 23 | all_steps: []const Configuration.Step.Index, | ||
| 24 | listen_address: net.IpAddress, | 23 | listen_address: net.IpAddress, |
| 25 | root_prog_node: std.Progress.Node, | 24 | root_prog_node: std.Progress.Node, |
| 26 | watch: bool, | ||
| 27 | 25 | ||
| 28 | tcp_server: ?net.Server, | 26 | tcp_server: ?net.Server, |
| 29 | serve_task: ?Io.Future(Io.Cancelable!void), | 27 | serve_task: ?Io.Future(Io.Cancelable!void), |
| ... | @@ -65,19 +63,16 @@ pub const base_clock: Io.Clock = .awake; | ... | @@ -65,19 +63,16 @@ pub const base_clock: Io.Clock = .awake; |
| 65 | 63 | ||
| 66 | /// Thread-safe. Triggers updates to be sent to connected WebSocket clients; see `update_id`. | 64 | /// Thread-safe. Triggers updates to be sent to connected WebSocket clients; see `update_id`. |
| 67 | pub fn notifyUpdate(ws: *WebServer) void { | 65 | pub fn notifyUpdate(ws: *WebServer) void { |
| 66 | const io = ws.maker.graph.io; | ||
| 68 | _ = ws.update_id.rmw(.Add, 1, .release); | 67 | _ = ws.update_id.rmw(.Add, 1, .release); |
| 69 | ws.graph.io.futexWake(u32, &ws.update_id.raw, 16); | 68 | io.futexWake(u32, &ws.update_id.raw, 16); |
| 70 | } | 69 | } |
| 71 | 70 | ||
| 72 | pub const Options = struct { | 71 | pub const Options = struct { |
| 73 | gpa: Allocator, | 72 | maker: *Maker, |
| 74 | graph: *const Graph, | ||
| 75 | all_steps: []const Configuration.Step.Index, | ||
| 76 | root_prog_node: std.Progress.Node, | 73 | root_prog_node: std.Progress.Node, |
| 77 | watch: bool, | ||
| 78 | listen_address: net.IpAddress, | 74 | listen_address: net.IpAddress, |
| 79 | base_timestamp: Io.Clock.Timestamp, | 75 | base_timestamp: Io.Clock.Timestamp, |
| 80 | configuration: *const Configuration, | ||
| 81 | }; | 76 | }; |
| 82 | pub fn init(opts: Options) WebServer { | 77 | pub fn init(opts: Options) WebServer { |
| 83 | // The upcoming `Io` interface should allow us to use `Io.async` and `Io.concurrent` | 78 | // The upcoming `Io` interface should allow us to use `Io.async` and `Io.concurrent` |
| ... | @@ -85,10 +80,13 @@ pub fn init(opts: Options) WebServer { | ... | @@ -85,10 +80,13 @@ pub fn init(opts: Options) WebServer { |
| 85 | comptime assert(!builtin.single_threaded); | 80 | comptime assert(!builtin.single_threaded); |
| 86 | assert(opts.base_timestamp.clock == base_clock); | 81 | assert(opts.base_timestamp.clock == base_clock); |
| 87 | 82 | ||
| 88 | const all_steps = opts.all_steps; | 83 | const maker = opts.maker; |
| 89 | const c = opts.configuration; | 84 | const all_steps = maker.step_stack.keys(); |
| 85 | const c = &maker.scanned_config.configuration; | ||
| 86 | const gpa = maker.gpa; | ||
| 87 | const graph = maker.graph; | ||
| 90 | 88 | ||
| 91 | const step_names_trailing = opts.gpa.alloc(u8, len: { | 89 | const step_names_trailing = gpa.alloc(u8, len: { |
| 92 | var name_bytes: usize = 0; | 90 | var name_bytes: usize = 0; |
| 93 | for (all_steps) |step_index| name_bytes += step_index.ptr(c).name.slice(c).len; | 91 | for (all_steps) |step_index| name_bytes += step_index.ptr(c).name.slice(c).len; |
| 94 | break :len name_bytes + all_steps.len * 4; | 92 | break :len name_bytes + all_steps.len * 4; |
| ... | @@ -105,25 +103,22 @@ pub fn init(opts: Options) WebServer { | ... | @@ -105,25 +103,22 @@ pub fn init(opts: Options) WebServer { |
| 105 | assert(idx == step_names_trailing.len); | 103 | assert(idx == step_names_trailing.len); |
| 106 | } | 104 | } |
| 107 | 105 | ||
| 108 | const step_status_bits = opts.gpa.alloc( | 106 | const step_status_bits = gpa.alloc( |
| 109 | u8, | 107 | u8, |
| 110 | std.math.divCeil(usize, all_steps.len, 4) catch unreachable, | 108 | std.math.divCeil(usize, all_steps.len, 4) catch unreachable, |
| 111 | ) catch @panic("out of memory"); | 109 | ) catch @panic("out of memory"); |
| 112 | @memset(step_status_bits, 0); | 110 | @memset(step_status_bits, 0); |
| 113 | 111 | ||
| 114 | const time_reports_len: usize = if (opts.graph.time_report) all_steps.len else 0; | 112 | const time_reports_len: usize = if (graph.time_report) all_steps.len else 0; |
| 115 | const time_report_msgs = opts.gpa.alloc([]u8, time_reports_len) catch @panic("out of memory"); | 113 | const time_report_msgs = gpa.alloc([]u8, time_reports_len) catch @panic("out of memory"); |
| 116 | const time_report_update_times = opts.gpa.alloc(i64, time_reports_len) catch @panic("out of memory"); | 114 | const time_report_update_times = gpa.alloc(i64, time_reports_len) catch @panic("out of memory"); |
| 117 | @memset(time_report_msgs, &.{}); | 115 | @memset(time_report_msgs, &.{}); |
| 118 | @memset(time_report_update_times, std.math.minInt(i64)); | 116 | @memset(time_report_update_times, std.math.minInt(i64)); |
| 119 | 117 | ||
| 120 | return .{ | 118 | return .{ |
| 121 | .gpa = opts.gpa, | 119 | .maker = maker, |
| 122 | .graph = opts.graph, | ||
| 123 | .all_steps = all_steps, | ||
| 124 | .listen_address = opts.listen_address, | 120 | .listen_address = opts.listen_address, |
| 125 | .root_prog_node = opts.root_prog_node, | 121 | .root_prog_node = opts.root_prog_node, |
| 126 | .watch = opts.watch, | ||
| 127 | 122 | ||
| 128 | .tcp_server = null, | 123 | .tcp_server = null, |
| 129 | .serve_task = null, | 124 | .serve_task = null, |
| ... | @@ -148,8 +143,9 @@ pub fn init(opts: Options) WebServer { | ... | @@ -148,8 +143,9 @@ pub fn init(opts: Options) WebServer { |
| 148 | }; | 143 | }; |
| 149 | } | 144 | } |
| 150 | pub fn deinit(ws: *WebServer) void { | 145 | pub fn deinit(ws: *WebServer) void { |
| 151 | const gpa = ws.gpa; | 146 | const maker = ws.maker; |
| 152 | const io = ws.graph.io; | 147 | const gpa = maker.gpa; |
| 148 | const io = maker.graph.io; | ||
| 153 | 149 | ||
| 154 | gpa.free(ws.step_names_trailing); | 150 | gpa.free(ws.step_names_trailing); |
| 155 | gpa.free(ws.step_status_bits); | 151 | gpa.free(ws.step_status_bits); |
| ... | @@ -170,7 +166,8 @@ pub fn deinit(ws: *WebServer) void { | ... | @@ -170,7 +166,8 @@ pub fn deinit(ws: *WebServer) void { |
| 170 | pub fn start(ws: *WebServer) error{AlreadyReported}!void { | 166 | pub fn start(ws: *WebServer) error{AlreadyReported}!void { |
| 171 | assert(ws.tcp_server == null); | 167 | assert(ws.tcp_server == null); |
| 172 | assert(ws.serve_task == null); | 168 | assert(ws.serve_task == null); |
| 173 | const io = ws.graph.io; | 169 | const maker = ws.maker; |
| 170 | const io = maker.graph.io; | ||
| 174 | 171 | ||
| 175 | ws.tcp_server = ws.listen_address.listen(io, .{ .reuse_address = true }) catch |err| { | 172 | ws.tcp_server = ws.listen_address.listen(io, .{ .reuse_address = true }) catch |err| { |
| 176 | log.err("failed to listen to port {d}: {t}", .{ ws.listen_address.getPort(), err }); | 173 | log.err("failed to listen to port {d}: {t}", .{ ws.listen_address.getPort(), err }); |
| ... | @@ -189,9 +186,12 @@ pub fn start(ws: *WebServer) error{AlreadyReported}!void { | ... | @@ -189,9 +186,12 @@ pub fn start(ws: *WebServer) error{AlreadyReported}!void { |
| 189 | } | 186 | } |
| 190 | } | 187 | } |
| 191 | fn serve(ws: *WebServer) Io.Cancelable!void { | 188 | fn serve(ws: *WebServer) Io.Cancelable!void { |
| 192 | const io = ws.graph.io; | 189 | const maker = ws.maker; |
| 190 | const io = maker.graph.io; | ||
| 191 | |||
| 193 | var group: Io.Group = .init; | 192 | var group: Io.Group = .init; |
| 194 | defer group.cancel(io); | 193 | defer group.cancel(io); |
| 194 | |||
| 195 | while (true) { | 195 | while (true) { |
| 196 | var stream = ws.tcp_server.?.accept(io) catch |err| switch (err) { | 196 | var stream = ws.tcp_server.?.accept(io) catch |err| switch (err) { |
| 197 | error.Canceled => |e| return e, | 197 | error.Canceled => |e| return e, |
| ... | @@ -223,8 +223,10 @@ pub fn updateStepStatus( | ... | @@ -223,8 +223,10 @@ pub fn updateStepStatus( |
| 223 | step_index: Configuration.Step.Index, | 223 | step_index: Configuration.Step.Index, |
| 224 | new_status: abi.StepUpdate.Status, | 224 | new_status: abi.StepUpdate.Status, |
| 225 | ) void { | 225 | ) void { |
| 226 | const maker = ws.maker; | ||
| 227 | const all_steps = maker.step_stack.keys(); | ||
| 226 | // TODO don't do linear search, especially in a hot loop like this | 228 | // TODO don't do linear search, especially in a hot loop like this |
| 227 | const step_idx: u32 = for (ws.all_steps, 0..) |s, i| { | 229 | const step_idx: u32 = for (all_steps, 0..) |s, i| { |
| 228 | if (s == step_index) break @intCast(i); | 230 | if (s == step_index) break @intCast(i); |
| 229 | } else unreachable; | 231 | } else unreachable; |
| 230 | const ptr = &ws.step_status_bits[step_idx / 4]; | 232 | const ptr = &ws.step_status_bits[step_idx / 4]; |
| ... | @@ -238,13 +240,16 @@ pub fn updateStepStatus( | ... | @@ -238,13 +240,16 @@ pub fn updateStepStatus( |
| 238 | pub fn finishBuild(ws: *WebServer, opts: struct { | 240 | pub fn finishBuild(ws: *WebServer, opts: struct { |
| 239 | fuzz: bool, | 241 | fuzz: bool, |
| 240 | }) void { | 242 | }) void { |
| 243 | const maker = ws.maker; | ||
| 244 | const all_steps = maker.step_stack.keys(); | ||
| 245 | |||
| 241 | if (opts.fuzz) { | 246 | if (opts.fuzz) { |
| 242 | switch (builtin.os.tag) { | 247 | switch (builtin.os.tag) { |
| 243 | // Current implementation depends on two things that need to be ported to Windows: | 248 | // Current implementation depends on two things that need to be ported to Windows: |
| 244 | // * Memory-mapping to share data between the fuzzer and build runner. | 249 | // * Memory-mapping to share data between the fuzzer and build runner. |
| 245 | // * COFF/PE support added to `std.debug.Info` (it needs a batching API for resolving | 250 | // * COFF/PE support added to `std.debug.Info` (it needs a batching API for resolving |
| 246 | // many addresses to source locations). | 251 | // many addresses to source locations). |
| 247 | .windows => std.process.fatal("--fuzz not yet implemented for {s}", .{@tagName(builtin.os.tag)}), | 252 | .windows => std.process.fatal("--fuzz not yet implemented for {t}", .{builtin.os.tag}), |
| 248 | else => {}, | 253 | else => {}, |
| 249 | } | 254 | } |
| 250 | if (@bitSizeOf(usize) != 64) { | 255 | if (@bitSizeOf(usize) != 64) { |
| ... | @@ -260,28 +265,26 @@ pub fn finishBuild(ws: *WebServer, opts: struct { | ... | @@ -260,28 +265,26 @@ pub fn finishBuild(ws: *WebServer, opts: struct { |
| 260 | ws.build_status.store(.fuzz_init, .monotonic); | 265 | ws.build_status.store(.fuzz_init, .monotonic); |
| 261 | ws.notifyUpdate(); | 266 | ws.notifyUpdate(); |
| 262 | 267 | ||
| 263 | ws.fuzz = Fuzz.init( | 268 | ws.fuzz = Fuzz.init(maker, all_steps, ws.root_prog_node, .{ .forever = .{ .ws = ws } }) catch |err| |
| 264 | ws.gpa, | 269 | std.process.fatal("failed to start fuzzer: {t}", .{err}); |
| 265 | ws.graph.io, | ||
| 266 | ws.all_steps, | ||
| 267 | ws.root_prog_node, | ||
| 268 | .{ .forever = .{ .ws = ws } }, | ||
| 269 | ) catch |err| std.process.fatal("failed to start fuzzer: {s}", .{@errorName(err)}); | ||
| 270 | ws.fuzz.?.start(); | 270 | ws.fuzz.?.start(); |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | ws.build_status.store(if (ws.watch) .watching else .idle, .monotonic); | 273 | ws.build_status.store(if (maker.watch) .watching else .idle, .monotonic); |
| 274 | ws.notifyUpdate(); | 274 | ws.notifyUpdate(); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | pub fn now(s: *const WebServer) i64 { | 277 | pub fn now(ws: *const WebServer) i64 { |
| 278 | const io = s.graph.io; | 278 | const maker = ws.maker; |
| 279 | const io = maker.graph.io; | ||
| 279 | const ts = base_clock.now(io); | 280 | const ts = base_clock.now(io); |
| 280 | return @intCast(s.base_timestamp.durationTo(ts).toNanoseconds()); | 281 | return @intCast(ws.base_timestamp.durationTo(ts).toNanoseconds()); |
| 281 | } | 282 | } |
| 282 | 283 | ||
| 283 | fn accept(ws: *WebServer, stream: net.Stream) void { | 284 | fn accept(ws: *WebServer, stream: net.Stream) void { |
| 284 | const io = ws.graph.io; | 285 | const maker = ws.maker; |
| 286 | const io = maker.graph.io; | ||
| 287 | |||
| 285 | defer { | 288 | defer { |
| 286 | // `net.Stream.close` wants to helpfully overwrite `stream` with | 289 | // `net.Stream.close` wants to helpfully overwrite `stream` with |
| 287 | // `undefined`, but it cannot do so since it is an immutable parameter. | 290 | // `undefined`, but it cannot do so since it is an immutable parameter. |
| ... | @@ -326,12 +329,16 @@ fn accept(ws: *WebServer, stream: net.Stream) void { | ... | @@ -326,12 +329,16 @@ fn accept(ws: *WebServer, stream: net.Stream) void { |
| 326 | } | 329 | } |
| 327 | 330 | ||
| 328 | fn serveWebSocket(ws: *WebServer, sock: *http.Server.WebSocket) !noreturn { | 331 | fn serveWebSocket(ws: *WebServer, sock: *http.Server.WebSocket) !noreturn { |
| 329 | const io = ws.graph.io; | 332 | const maker = ws.maker; |
| 333 | const gpa = maker.gpa; | ||
| 334 | const graph = maker.graph; | ||
| 335 | const io = graph.io; | ||
| 336 | const all_steps = maker.step_stack.keys(); | ||
| 330 | 337 | ||
| 331 | var prev_build_status = ws.build_status.load(.monotonic); | 338 | var prev_build_status = ws.build_status.load(.monotonic); |
| 332 | 339 | ||
| 333 | const prev_step_status_bits = try ws.gpa.alloc(u8, ws.step_status_bits.len); | 340 | const prev_step_status_bits = try gpa.alloc(u8, ws.step_status_bits.len); |
| 334 | defer ws.gpa.free(prev_step_status_bits); | 341 | defer gpa.free(prev_step_status_bits); |
| 335 | for (prev_step_status_bits, ws.step_status_bits) |*copy, *shared| { | 342 | for (prev_step_status_bits, ws.step_status_bits) |*copy, *shared| { |
| 336 | copy.* = @atomicLoad(u8, shared, .monotonic); | 343 | copy.* = @atomicLoad(u8, shared, .monotonic); |
| 337 | } | 344 | } |
| ... | @@ -343,10 +350,10 @@ fn serveWebSocket(ws: *WebServer, sock: *http.Server.WebSocket) !noreturn { | ... | @@ -343,10 +350,10 @@ fn serveWebSocket(ws: *WebServer, sock: *http.Server.WebSocket) !noreturn { |
| 343 | const hello_header: abi.Hello = .{ | 350 | const hello_header: abi.Hello = .{ |
| 344 | .status = prev_build_status, | 351 | .status = prev_build_status, |
| 345 | .flags = .{ | 352 | .flags = .{ |
| 346 | .time_report = ws.graph.time_report, | 353 | .time_report = graph.time_report, |
| 347 | }, | 354 | }, |
| 348 | .timestamp = ws.now(), | 355 | .timestamp = ws.now(), |
| 349 | .steps_len = @intCast(ws.all_steps.len), | 356 | .steps_len = @intCast(all_steps.len), |
| 350 | }; | 357 | }; |
| 351 | var bufs: [3][]const u8 = .{ @ptrCast(&hello_header), ws.step_names_trailing, prev_step_status_bits }; | 358 | var bufs: [3][]const u8 = .{ @ptrCast(&hello_header), ws.step_names_trailing, prev_step_status_bits }; |
| 352 | try sock.writeMessageVec(&bufs, .binary); | 359 | try sock.writeMessageVec(&bufs, .binary); |
| ... | @@ -369,8 +376,8 @@ fn serveWebSocket(ws: *WebServer, sock: *http.Server.WebSocket) !noreturn { | ... | @@ -369,8 +376,8 @@ fn serveWebSocket(ws: *WebServer, sock: *http.Server.WebSocket) !noreturn { |
| 369 | if (update_time <= prev_time) continue; | 376 | if (update_time <= prev_time) continue; |
| 370 | // We want to send `msg`, but shouldn't block `ws.time_report_mutex` while we do, so | 377 | // We want to send `msg`, but shouldn't block `ws.time_report_mutex` while we do, so |
| 371 | // that we don't hold up the build system on the client accepting this packet. | 378 | // that we don't hold up the build system on the client accepting this packet. |
| 372 | const owned_msg = try ws.gpa.dupe(u8, msg); | 379 | const owned_msg = try gpa.dupe(u8, msg); |
| 373 | defer ws.gpa.free(owned_msg); | 380 | defer gpa.free(owned_msg); |
| 374 | // Temporarily unlock, then re-lock after the message is sent. | 381 | // Temporarily unlock, then re-lock after the message is sent. |
| 375 | ws.time_report_mutex.unlock(io); | 382 | ws.time_report_mutex.unlock(io); |
| 376 | defer ws.time_report_mutex.lockUncancelable(io); | 383 | defer ws.time_report_mutex.lockUncancelable(io); |
| ... | @@ -427,7 +434,8 @@ fn serveWebSocket(ws: *WebServer, sock: *http.Server.WebSocket) !noreturn { | ... | @@ -427,7 +434,8 @@ fn serveWebSocket(ws: *WebServer, sock: *http.Server.WebSocket) !noreturn { |
| 427 | } | 434 | } |
| 428 | } | 435 | } |
| 429 | fn recvWebSocketMessages(ws: *WebServer, sock: *http.Server.WebSocket) void { | 436 | fn recvWebSocketMessages(ws: *WebServer, sock: *http.Server.WebSocket) void { |
| 430 | const io = ws.graph.io; | 437 | const maker = ws.maker; |
| 438 | const io = maker.graph.io; | ||
| 431 | 439 | ||
| 432 | while (true) { | 440 | while (true) { |
| 433 | const msg = sock.readSmallMessage() catch return; | 441 | const msg = sock.readSmallMessage() catch return; |
| ... | @@ -485,8 +493,11 @@ fn serveLibFile( | ... | @@ -485,8 +493,11 @@ fn serveLibFile( |
| 485 | sub_path: []const u8, | 493 | sub_path: []const u8, |
| 486 | content_type: []const u8, | 494 | content_type: []const u8, |
| 487 | ) !void { | 495 | ) !void { |
| 496 | const maker = ws.maker; | ||
| 497 | const graph = maker.graph; | ||
| 498 | |||
| 488 | return serveFile(ws, request, .{ | 499 | return serveFile(ws, request, .{ |
| 489 | .root_dir = ws.graph.zig_lib_directory, | 500 | .root_dir = graph.zig_lib_directory, |
| 490 | .sub_path = sub_path, | 501 | .sub_path = sub_path, |
| 491 | }, content_type); | 502 | }, content_type); |
| 492 | } | 503 | } |
| ... | @@ -495,7 +506,9 @@ fn serveClientWasm( | ... | @@ -495,7 +506,9 @@ fn serveClientWasm( |
| 495 | req: *http.Server.Request, | 506 | req: *http.Server.Request, |
| 496 | optimize_mode: std.builtin.OptimizeMode, | 507 | optimize_mode: std.builtin.OptimizeMode, |
| 497 | ) !void { | 508 | ) !void { |
| 498 | var arena_state: std.heap.ArenaAllocator = .init(ws.gpa); | 509 | const gpa = ws.maker.gpa; |
| 510 | |||
| 511 | var arena_state: std.heap.ArenaAllocator = .init(gpa); | ||
| 499 | defer arena_state.deinit(); | 512 | defer arena_state.deinit(); |
| 500 | const arena = arena_state.allocator(); | 513 | const arena = arena_state.allocator(); |
| 501 | 514 | ||
| ... | @@ -510,8 +523,10 @@ pub fn serveFile( | ... | @@ -510,8 +523,10 @@ pub fn serveFile( |
| 510 | path: Cache.Path, | 523 | path: Cache.Path, |
| 511 | content_type: []const u8, | 524 | content_type: []const u8, |
| 512 | ) !void { | 525 | ) !void { |
| 513 | const gpa = ws.gpa; | 526 | const maker = ws.maker; |
| 514 | const io = ws.graph.io; | 527 | const gpa = ws.maker.gpa; |
| 528 | const io = maker.graph.io; | ||
| 529 | |||
| 515 | // The desired API is actually sendfile, which will require enhancing http.Server. | 530 | // The desired API is actually sendfile, which will require enhancing http.Server. |
| 516 | // We load the file with every request so that the user can make changes to the file | 531 | // We load the file with every request so that the user can make changes to the file |
| 517 | // and refresh the HTML page without restarting this server. | 532 | // and refresh the HTML page without restarting this server. |
| ... | @@ -528,7 +543,8 @@ pub fn serveFile( | ... | @@ -528,7 +543,8 @@ pub fn serveFile( |
| 528 | }); | 543 | }); |
| 529 | } | 544 | } |
| 530 | pub fn serveTarFile(ws: *WebServer, request: *http.Server.Request, paths: []const Cache.Path) !void { | 545 | pub fn serveTarFile(ws: *WebServer, request: *http.Server.Request, paths: []const Cache.Path) !void { |
| 531 | const graph = ws.graph; | 546 | const maker = ws.maker; |
| 547 | const graph = maker.graph; | ||
| 532 | const io = graph.io; | 548 | const io = graph.io; |
| 533 | 549 | ||
| 534 | var send_buffer: [0x4000]u8 = undefined; | 550 | var send_buffer: [0x4000]u8 = undefined; |
| ... | @@ -576,8 +592,9 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim | ... | @@ -576,8 +592,9 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim |
| 576 | const arch_os_abi = "wasm32-freestanding"; | 592 | const arch_os_abi = "wasm32-freestanding"; |
| 577 | const cpu_features = "baseline+atomics+bulk_memory+multivalue+mutable_globals+nontrapping_fptoint+reference_types+sign_ext"; | 593 | const cpu_features = "baseline+atomics+bulk_memory+multivalue+mutable_globals+nontrapping_fptoint+reference_types+sign_ext"; |
| 578 | 594 | ||
| 579 | const gpa = ws.gpa; | 595 | const maker = ws.maker; |
| 580 | const graph = ws.graph; | 596 | const gpa = maker.gpa; |
| 597 | const graph = maker.graph; | ||
| 581 | const io = graph.io; | 598 | const io = graph.io; |
| 582 | 599 | ||
| 583 | const main_src_path: Cache.Path = .{ | 600 | const main_src_path: Cache.Path = .{ |
| ... | @@ -697,7 +714,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim | ... | @@ -697,7 +714,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim |
| 697 | if (code != 0) { | 714 | if (code != 0) { |
| 698 | log.err( | 715 | log.err( |
| 699 | "the following command exited with error code {d}:\n{s}", | 716 | "the following command exited with error code {d}:\n{s}", |
| 700 | .{ code, try Step.allocPrintCmd(arena, .inherit, null, argv.items) }, | 717 | .{ code, try std.zig.allocPrintCmd(arena, .inherit, null, argv.items) }, |
| 701 | ); | 718 | ); |
| 702 | return error.WasmCompilationFailed; | 719 | return error.WasmCompilationFailed; |
| 703 | } | 720 | } |
| ... | @@ -705,21 +722,21 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim | ... | @@ -705,21 +722,21 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim |
| 705 | .signal => |sig| { | 722 | .signal => |sig| { |
| 706 | log.err( | 723 | log.err( |
| 707 | "the following command terminated with signal {t}:\n{s}", | 724 | "the following command terminated with signal {t}:\n{s}", |
| 708 | .{ sig, try Step.allocPrintCmd(arena, .inherit, null, argv.items) }, | 725 | .{ sig, try std.zig.allocPrintCmd(arena, .inherit, null, argv.items) }, |
| 709 | ); | 726 | ); |
| 710 | return error.WasmCompilationFailed; | 727 | return error.WasmCompilationFailed; |
| 711 | }, | 728 | }, |
| 712 | .stopped => |sig| { | 729 | .stopped => |sig| { |
| 713 | log.err( | 730 | log.err( |
| 714 | "the following command stopped unexpectedly with signal {t}:\n{s}", | 731 | "the following command stopped unexpectedly with signal {t}:\n{s}", |
| 715 | .{ sig, try Build.Step.allocPrintCmd(arena, .inherit, null, argv.items) }, | 732 | .{ sig, try std.zig.allocPrintCmd(arena, .inherit, null, argv.items) }, |
| 716 | ); | 733 | ); |
| 717 | return error.WasmCompilationFailed; | 734 | return error.WasmCompilationFailed; |
| 718 | }, | 735 | }, |
| 719 | .unknown => { | 736 | .unknown => { |
| 720 | log.err( | 737 | log.err( |
| 721 | "the following command terminated unexpectedly:\n{s}", | 738 | "the following command terminated unexpectedly:\n{s}", |
| 722 | .{try Step.allocPrintCmd(arena, .inherit, null, argv.items)}, | 739 | .{try std.zig.allocPrintCmd(arena, .inherit, null, argv.items)}, |
| 723 | ); | 740 | ); |
| 724 | return error.WasmCompilationFailed; | 741 | return error.WasmCompilationFailed; |
| 725 | }, | 742 | }, |
| ... | @@ -729,14 +746,14 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim | ... | @@ -729,14 +746,14 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim |
| 729 | try result_error_bundle.renderToStderr(io, .{}, .auto); | 746 | try result_error_bundle.renderToStderr(io, .{}, .auto); |
| 730 | log.err("the following command failed with {d} compilation errors:\n{s}", .{ | 747 | log.err("the following command failed with {d} compilation errors:\n{s}", .{ |
| 731 | result_error_bundle.errorMessageCount(), | 748 | result_error_bundle.errorMessageCount(), |
| 732 | try Step.allocPrintCmd(arena, .inherit, null, argv.items), | 749 | try std.zig.allocPrintCmd(arena, .inherit, null, argv.items), |
| 733 | }); | 750 | }); |
| 734 | return error.WasmCompilationFailed; | 751 | return error.WasmCompilationFailed; |
| 735 | } | 752 | } |
| 736 | 753 | ||
| 737 | const base_path = result orelse { | 754 | const base_path = result orelse { |
| 738 | log.err("child process failed to report result\n{s}", .{ | 755 | log.err("child process failed to report result\n{s}", .{ |
| 739 | try Step.allocPrintCmd(arena, .inherit, null, argv.items), | 756 | try std.zig.allocPrintCmd(arena, .inherit, null, argv.items), |
| 740 | }); | 757 | }); |
| 741 | return error.WasmCompilationFailed; | 758 | return error.WasmCompilationFailed; |
| 742 | }; | 759 | }; |
| ... | @@ -773,11 +790,13 @@ pub fn updateTimeReportCompile(ws: *WebServer, opts: struct { | ... | @@ -773,11 +790,13 @@ pub fn updateTimeReportCompile(ws: *WebServer, opts: struct { |
| 773 | /// The trailing data of `abi.time_report.CompileResult`, except the step name. | 790 | /// The trailing data of `abi.time_report.CompileResult`, except the step name. |
| 774 | trailing: []const u8, | 791 | trailing: []const u8, |
| 775 | }) void { | 792 | }) void { |
| 776 | const gpa = ws.gpa; | 793 | const maker = ws.maker; |
| 777 | const io = ws.graph.io; | 794 | const gpa = maker.gpa; |
| 795 | const io = maker.graph.io; | ||
| 796 | const all_steps = maker.step_stack.keys(); | ||
| 778 | 797 | ||
| 779 | // TODO don't do linear search | 798 | // TODO don't do linear search |
| 780 | const step_idx: u32 = for (ws.all_steps, 0..) |s, i| { | 799 | const step_idx: u32 = for (all_steps, 0..) |s, i| { |
| 781 | if (s == opts.compile_step) break @intCast(i); | 800 | if (s == opts.compile_step) break @intCast(i); |
| 782 | } else unreachable; | 801 | } else unreachable; |
| 783 | 802 | ||
| ... | @@ -815,11 +834,13 @@ pub fn updateTimeReportCompile(ws: *WebServer, opts: struct { | ... | @@ -815,11 +834,13 @@ pub fn updateTimeReportCompile(ws: *WebServer, opts: struct { |
| 815 | } | 834 | } |
| 816 | 835 | ||
| 817 | pub fn updateTimeReportGeneric(ws: *WebServer, step_index: Configuration.Step.Index, duration: Io.Duration) void { | 836 | pub fn updateTimeReportGeneric(ws: *WebServer, step_index: Configuration.Step.Index, duration: Io.Duration) void { |
| 818 | const gpa = ws.gpa; | 837 | const maker = ws.maker; |
| 819 | const io = ws.graph.io; | 838 | const gpa = maker.gpa; |
| 839 | const io = maker.graph.io; | ||
| 840 | const all_steps = maker.step_stack.keys(); | ||
| 820 | 841 | ||
| 821 | // TODO don't do linear search | 842 | // TODO don't do linear search |
| 822 | const step_idx: u32 = for (ws.all_steps, 0..) |s, i| { | 843 | const step_idx: u32 = for (all_steps, 0..) |s, i| { |
| 823 | if (s == step_index) break @intCast(i); | 844 | if (s == step_index) break @intCast(i); |
| 824 | } else unreachable; | 845 | } else unreachable; |
| 825 | 846 | ||
| ... | @@ -852,11 +873,13 @@ pub fn updateTimeReportRunTest( | ... | @@ -852,11 +873,13 @@ pub fn updateTimeReportRunTest( |
| 852 | tests: *const Step.Run.CachedTestMetadata, | 873 | tests: *const Step.Run.CachedTestMetadata, |
| 853 | ns_per_test: []const u64, | 874 | ns_per_test: []const u64, |
| 854 | ) void { | 875 | ) void { |
| 855 | const gpa = ws.gpa; | 876 | const maker = ws.maker; |
| 856 | const io = ws.graph.io; | 877 | const gpa = maker.gpa; |
| 878 | const io = maker.graph.io; | ||
| 879 | const all_steps = maker.step_stack.keys(); | ||
| 857 | 880 | ||
| 858 | // TODO don't do linear search | 881 | // TODO don't do linear search |
| 859 | const step_idx: u32 = for (ws.all_steps, 0..) |s, i| { | 882 | const step_idx: u32 = for (all_steps, 0..) |s, i| { |
| 860 | if (s == run_step_index) break @intCast(i); | 883 | if (s == run_step_index) break @intCast(i); |
| 861 | } else unreachable; | 884 | } else unreachable; |
| 862 | 885 | ||
| ... | @@ -910,7 +933,7 @@ const RunnerRequest = union(enum) { | ... | @@ -910,7 +933,7 @@ const RunnerRequest = union(enum) { |
| 910 | rebuild, | 933 | rebuild, |
| 911 | }; | 934 | }; |
| 912 | pub fn getRunnerRequest(ws: *WebServer) ?RunnerRequest { | 935 | pub fn getRunnerRequest(ws: *WebServer) ?RunnerRequest { |
| 913 | const io = ws.graph.io; | 936 | const io = ws.maker.graph.io; |
| 914 | ws.runner_request_mutex.lock(io) catch return; | 937 | ws.runner_request_mutex.lock(io) catch return; |
| 915 | defer ws.runner_request_mutex.unlock(io); | 938 | defer ws.runner_request_mutex.unlock(io); |
| 916 | if (ws.runner_request) |req| { | 939 | if (ws.runner_request) |req| { |
| ... | @@ -921,7 +944,7 @@ pub fn getRunnerRequest(ws: *WebServer) ?RunnerRequest { | ... | @@ -921,7 +944,7 @@ pub fn getRunnerRequest(ws: *WebServer) ?RunnerRequest { |
| 921 | return null; | 944 | return null; |
| 922 | } | 945 | } |
| 923 | pub fn wait(ws: *WebServer) Io.Cancelable!RunnerRequest { | 946 | pub fn wait(ws: *WebServer) Io.Cancelable!RunnerRequest { |
| 924 | const io = ws.graph.io; | 947 | const io = ws.maker.graph.io; |
| 925 | try ws.runner_request_mutex.lock(io); | 948 | try ws.runner_request_mutex.lock(io); |
| 926 | defer ws.runner_request_mutex.unlock(io); | 949 | defer ws.runner_request_mutex.unlock(io); |
| 927 | while (true) { | 950 | while (true) { |
lib/std/Build.zig-13| ... | @@ -45,7 +45,6 @@ install_prefix: []const u8, | ... | @@ -45,7 +45,6 @@ install_prefix: []const u8, |
| 45 | /// Path to the directory containing build.zig. | 45 | /// Path to the directory containing build.zig. |
| 46 | build_root: Cache.Directory, | 46 | build_root: Cache.Directory, |
| 47 | cache_root: Cache.Directory, | 47 | cache_root: Cache.Directory, |
| 48 | pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null, | ||
| 49 | debug_log_scopes: []const []const u8 = &.{}, | 48 | debug_log_scopes: []const []const u8 = &.{}, |
| 50 | debug_compile_errors: bool = false, | 49 | debug_compile_errors: bool = false, |
| 51 | debug_incremental: bool = false, | 50 | debug_incremental: bool = false, |
| ... | @@ -176,18 +175,6 @@ pub const RunError = error{ | ... | @@ -176,18 +175,6 @@ pub const RunError = error{ |
| 176 | ExecNotSupported, | 175 | ExecNotSupported, |
| 177 | } || std.process.SpawnError; | 176 | } || std.process.SpawnError; |
| 178 | 177 | ||
| 179 | pub const PkgConfigError = error{ | ||
| 180 | PkgConfigCrashed, | ||
| 181 | PkgConfigFailed, | ||
| 182 | PkgConfigNotInstalled, | ||
| 183 | PkgConfigInvalidOutput, | ||
| 184 | }; | ||
| 185 | |||
| 186 | pub const PkgConfigPkg = struct { | ||
| 187 | name: []const u8, | ||
| 188 | desc: []const u8, | ||
| 189 | }; | ||
| 190 | |||
| 191 | const UserInputOptionsMap = StringHashMap(UserInputOption); | 178 | const UserInputOptionsMap = StringHashMap(UserInputOption); |
| 192 | const AvailableOptionsMap = StringHashMap(AvailableOption); | 179 | const AvailableOptionsMap = StringHashMap(AvailableOption); |
| 193 | 180 |
lib/std/Build/Step/Compile.zig-40| ... | @@ -8,13 +8,9 @@ const fs = std.fs; | ... | @@ -8,13 +8,9 @@ const fs = std.fs; |
| 8 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
| 9 | const panic = std.debug.panic; | 9 | const panic = std.debug.panic; |
| 10 | const StringHashMap = std.StringHashMap; | 10 | const StringHashMap = std.StringHashMap; |
| 11 | const Sha256 = std.crypto.hash.sha2.Sha256; | ||
| 12 | const Allocator = std.mem.Allocator; | 11 | const Allocator = std.mem.Allocator; |
| 13 | const Step = std.Build.Step; | 12 | const Step = std.Build.Step; |
| 14 | const LazyPath = std.Build.LazyPath; | 13 | const LazyPath = std.Build.LazyPath; |
| 15 | const PkgConfigPkg = std.Build.PkgConfigPkg; | ||
| 16 | const PkgConfigError = std.Build.PkgConfigError; | ||
| 17 | const RunError = std.Build.RunError; | ||
| 18 | const Module = std.Build.Module; | 14 | const Module = std.Build.Module; |
| 19 | const InstallDir = std.Build.InstallDir; | 15 | const InstallDir = std.Build.InstallDir; |
| 20 | const GeneratedFile = std.Build.GeneratedFile; | 16 | const GeneratedFile = std.Build.GeneratedFile; |
| ... | @@ -777,42 +773,6 @@ pub fn setExecCmd(compile: *Compile, args: []const ?[]const u8) void { | ... | @@ -777,42 +773,6 @@ pub fn setExecCmd(compile: *Compile, args: []const ?[]const u8) void { |
| 777 | compile.exec_cmd_args = duped_args; | 773 | compile.exec_cmd_args = duped_args; |
| 778 | } | 774 | } |
| 779 | 775 | ||
| 780 | const CliNamedModules = struct { | ||
| 781 | modules: std.AutoArrayHashMapUnmanaged(*Module, void), | ||
| 782 | names: std.StringArrayHashMapUnmanaged(void), | ||
| 783 | |||
| 784 | /// Traverse the whole dependency graph and give every module a unique | ||
| 785 | /// name, ideally one named after what it's called somewhere in the graph. | ||
| 786 | /// It will help here to have both a mapping from module to name and a set | ||
| 787 | /// of all the currently-used names. | ||
| 788 | fn init(arena: Allocator, root_module: *Module) Allocator.Error!CliNamedModules { | ||
| 789 | var compile: CliNamedModules = .{ | ||
| 790 | .modules = .{}, | ||
| 791 | .names = .{}, | ||
| 792 | }; | ||
| 793 | const graph = root_module.getGraph(); | ||
| 794 | { | ||
| 795 | assert(graph.modules[0] == root_module); | ||
| 796 | try compile.modules.put(arena, root_module, {}); | ||
| 797 | try compile.names.put(arena, "root", {}); | ||
| 798 | } | ||
| 799 | for (graph.modules[1..], graph.names[1..]) |mod, orig_name| { | ||
| 800 | var name = orig_name; | ||
| 801 | var n: usize = 0; | ||
| 802 | while (true) { | ||
| 803 | const gop = try compile.names.getOrPut(arena, name); | ||
| 804 | if (!gop.found_existing) { | ||
| 805 | try compile.modules.putNoClobber(arena, mod, {}); | ||
| 806 | break; | ||
| 807 | } | ||
| 808 | name = try std.fmt.allocPrint(arena, "{s}{d}", .{ orig_name, n }); | ||
| 809 | n += 1; | ||
| 810 | } | ||
| 811 | } | ||
| 812 | return compile; | ||
| 813 | } | ||
| 814 | }; | ||
| 815 | |||
| 816 | fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) ![]const u8 { | 776 | fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) ![]const u8 { |
| 817 | const step = &compile.step; | 777 | const step = &compile.step; |
| 818 | const b = step.owner; | 778 | const b = step.owner; |
lib/std/zig/Configuration.zig+15-11| ... | @@ -436,23 +436,23 @@ pub const Step = extern struct { | ... | @@ -436,23 +436,23 @@ pub const Step = extern struct { |
| 436 | }; | 436 | }; |
| 437 | 437 | ||
| 438 | pub const Tag = enum(u5) { | 438 | pub const Tag = enum(u5) { |
| 439 | top_level, | 439 | check_file, |
| 440 | check_object, | ||
| 440 | compile, | 441 | compile, |
| 442 | config_header, | ||
| 443 | fail, | ||
| 444 | fmt, | ||
| 441 | install_artifact, | 445 | install_artifact, |
| 442 | install_file, | ||
| 443 | install_dir, | 446 | install_dir, |
| 447 | install_file, | ||
| 448 | objcopy, | ||
| 449 | options, | ||
| 444 | remove_dir, | 450 | remove_dir, |
| 445 | fail, | 451 | run, |
| 446 | fmt, | 452 | top_level, |
| 447 | translate_c, | 453 | translate_c, |
| 448 | write_file, | ||
| 449 | update_source_files, | 454 | update_source_files, |
| 450 | run, | 455 | write_file, |
| 451 | check_file, | ||
| 452 | check_object, | ||
| 453 | config_header, | ||
| 454 | objcopy, | ||
| 455 | options, | ||
| 456 | }; | 456 | }; |
| 457 | 457 | ||
| 458 | pub const TopLevel = struct { | 458 | pub const TopLevel = struct { |
| ... | @@ -808,6 +808,10 @@ pub const Step = extern struct { | ... | @@ -808,6 +808,10 @@ pub const Step = extern struct { |
| 808 | _: u23 = 0, | 808 | _: u23 = 0, |
| 809 | }; | 809 | }; |
| 810 | }; | 810 | }; |
| 811 | |||
| 812 | pub fn flags(s: *const Step, c: *const Configuration) Flags { | ||
| 813 | return @bitCast(c.extra[s.extra_index]); | ||
| 814 | } | ||
| 811 | }; | 815 | }; |
| 812 | 816 | ||
| 813 | pub const MaxRss = enum(u32) { | 817 | pub const MaxRss = enum(u32) { |