| ... | ... | @@ -249,7 +249,7 @@ pub fn addDepFileOutputArg(self: *Run, basename: []const u8) std.Build.LazyPath |
| 249 | 249 | /// Add a prefixed path argument to a dep file (.d) for the child process to |
| 250 | 250 | /// write its discovered additional dependencies. |
| 251 | 251 | /// Only one dep file argument is allowed by instance. |
| 252 | | pub fn addPrefixedDepFileOutputArg(self: *Run, prefix: []const u8, basename: []const u8) void { |
| 252 | pub fn addPrefixedDepFileOutputArg(self: *Run, prefix: []const u8, basename: []const u8) std.Build.LazyPath { |
| 253 | 253 | assert(self.dep_output_file == null); |
| 254 | 254 | |
| 255 | 255 | const b = self.step.owner; |
| ... | ... | @@ -264,6 +264,8 @@ pub fn addPrefixedDepFileOutputArg(self: *Run, prefix: []const u8, basename: []c |
| 264 | 264 | self.dep_output_file = dep_file; |
| 265 | 265 | |
| 266 | 266 | self.argv.append(.{ .output = dep_file }) catch @panic("OOM"); |
| 267 | |
| 268 | return .{ .generated = &dep_file.generated_file }; |
| 267 | 269 | } |
| 268 | 270 | |
| 269 | 271 | pub fn addArg(self: *Run, arg: []const u8) void { |
| ... | ... | @@ -454,6 +456,10 @@ fn checksContainStderr(checks: []const StdIo.Check) bool { |
| 454 | 456 | return false; |
| 455 | 457 | } |
| 456 | 458 | |
| 459 | const IndexedOutput = struct { |
| 460 | index: usize, |
| 461 | output: *Output, |
| 462 | }; |
| 457 | 463 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 458 | 464 | const b = step.owner; |
| 459 | 465 | const arena = b.allocator; |
| ... | ... | @@ -461,10 +467,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 461 | 467 | const has_side_effects = self.hasSideEffects(); |
| 462 | 468 | |
| 463 | 469 | var argv_list = ArrayList([]const u8).init(arena); |
| 464 | | var output_placeholders = ArrayList(struct { |
| 465 | | index: usize, |
| 466 | | output: *Output, |
| 467 | | }).init(arena); |
| 470 | var output_placeholders = ArrayList(IndexedOutput).init(arena); |
| 468 | 471 | |
| 469 | 472 | var man = b.cache.obtain(); |
| 470 | 473 | defer man.deinit(); |
| ... | ... | @@ -546,32 +549,25 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 546 | 549 | if (try step.cacheHit(&man)) { |
| 547 | 550 | // cache hit, skip running command |
| 548 | 551 | const digest = man.final(); |
| 549 | | for (output_placeholders.items) |placeholder| { |
| 550 | | placeholder.output.generated_file.path = try b.cache_root.join(arena, &.{ |
| 551 | | "o", &digest, placeholder.output.basename, |
| 552 | | }); |
| 553 | | } |
| 554 | 552 | |
| 555 | | if (self.captured_stdout) |output| { |
| 556 | | output.generated_file.path = try b.cache_root.join(arena, &.{ |
| 557 | | "o", &digest, output.basename, |
| 558 | | }); |
| 559 | | } |
| 560 | | |
| 561 | | if (self.captured_stderr) |output| { |
| 562 | | output.generated_file.path = try b.cache_root.join(arena, &.{ |
| 563 | | "o", &digest, output.basename, |
| 564 | | }); |
| 565 | | } |
| 553 | try populateGeneratedPaths( |
| 554 | arena, |
| 555 | output_placeholders.items, |
| 556 | self.captured_stdout, |
| 557 | self.captured_stderr, |
| 558 | b.cache_root, |
| 559 | &digest, |
| 560 | ); |
| 566 | 561 | |
| 567 | 562 | step.result_cached = true; |
| 568 | 563 | return; |
| 569 | 564 | } |
| 570 | 565 | |
| 571 | | const digest = man.final(); |
| 566 | const rand_int = std.crypto.random.int(u64); |
| 567 | const tmp_dir_path = "tmp" ++ fs.path.sep_str ++ std.Build.hex64(rand_int); |
| 572 | 568 | |
| 573 | 569 | for (output_placeholders.items) |placeholder| { |
| 574 | | const output_components = .{ "o", &digest, placeholder.output.basename }; |
| 570 | const output_components = .{ tmp_dir_path, placeholder.output.basename }; |
| 575 | 571 | const output_sub_path = try fs.path.join(arena, &output_components); |
| 576 | 572 | const output_sub_dir_path = fs.path.dirname(output_sub_path).?; |
| 577 | 573 | b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { |
| ... | ... | @@ -588,12 +584,83 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 588 | 584 | argv_list.items[placeholder.index] = cli_arg; |
| 589 | 585 | } |
| 590 | 586 | |
| 591 | | try runCommand(self, argv_list.items, has_side_effects, &digest, prog_node); |
| 587 | try runCommand(self, argv_list.items, has_side_effects, tmp_dir_path, prog_node); |
| 592 | 588 | |
| 593 | 589 | if (self.dep_output_file) |dep_output_file| |
| 594 | 590 | try man.addDepFilePost(std.fs.cwd(), dep_output_file.generated_file.getPath()); |
| 595 | 591 | |
| 592 | const digest = man.final(); |
| 593 | |
| 594 | const any_output = output_placeholders.items.len > 0 or |
| 595 | self.captured_stdout != null or self.captured_stderr != null; |
| 596 | |
| 597 | // Rename into place |
| 598 | if (any_output) { |
| 599 | const o_sub_path = "o" ++ fs.path.sep_str ++ &digest; |
| 600 | |
| 601 | b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| { |
| 602 | if (err == error.PathAlreadyExists) { |
| 603 | b.cache_root.handle.deleteTree(o_sub_path) catch |del_err| { |
| 604 | return step.fail("unable to remove dir '{}'{s}: {s}", .{ |
| 605 | b.cache_root, |
| 606 | tmp_dir_path, |
| 607 | @errorName(del_err), |
| 608 | }); |
| 609 | }; |
| 610 | b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |retry_err| { |
| 611 | return step.fail("unable to rename dir '{}{s}' to '{}{s}': {s}", .{ |
| 612 | b.cache_root, tmp_dir_path, |
| 613 | b.cache_root, o_sub_path, |
| 614 | @errorName(retry_err), |
| 615 | }); |
| 616 | }; |
| 617 | } else { |
| 618 | return step.fail("unable to rename dir '{}{s}' to '{}{s}': {s}", .{ |
| 619 | b.cache_root, tmp_dir_path, |
| 620 | b.cache_root, o_sub_path, |
| 621 | @errorName(err), |
| 622 | }); |
| 623 | } |
| 624 | }; |
| 625 | } |
| 626 | |
| 596 | 627 | try step.writeManifest(&man); |
| 628 | |
| 629 | try populateGeneratedPaths( |
| 630 | arena, |
| 631 | output_placeholders.items, |
| 632 | self.captured_stdout, |
| 633 | self.captured_stderr, |
| 634 | b.cache_root, |
| 635 | &digest, |
| 636 | ); |
| 637 | } |
| 638 | |
| 639 | fn populateGeneratedPaths( |
| 640 | arena: std.mem.Allocator, |
| 641 | output_placeholders: []const IndexedOutput, |
| 642 | captured_stdout: ?*Output, |
| 643 | captured_stderr: ?*Output, |
| 644 | cache_root: Build.Cache.Directory, |
| 645 | digest: *const Build.Cache.HexDigest, |
| 646 | ) !void { |
| 647 | for (output_placeholders) |placeholder| { |
| 648 | placeholder.output.generated_file.path = try cache_root.join(arena, &.{ |
| 649 | "o", digest, placeholder.output.basename, |
| 650 | }); |
| 651 | } |
| 652 | |
| 653 | if (captured_stdout) |output| { |
| 654 | output.generated_file.path = try cache_root.join(arena, &.{ |
| 655 | "o", digest, output.basename, |
| 656 | }); |
| 657 | } |
| 658 | |
| 659 | if (captured_stderr) |output| { |
| 660 | output.generated_file.path = try cache_root.join(arena, &.{ |
| 661 | "o", digest, output.basename, |
| 662 | }); |
| 663 | } |
| 597 | 664 | } |
| 598 | 665 | |
| 599 | 666 | fn formatTerm( |
| ... | ... | @@ -645,7 +712,7 @@ fn runCommand( |
| 645 | 712 | self: *Run, |
| 646 | 713 | argv: []const []const u8, |
| 647 | 714 | has_side_effects: bool, |
| 648 | | digest: ?*const [std.Build.Cache.hex_digest_len]u8, |
| 715 | tmp_dir_path: ?[]const u8, |
| 649 | 716 | prog_node: *std.Progress.Node, |
| 650 | 717 | ) !void { |
| 651 | 718 | const step = &self.step; |
| ... | ... | @@ -816,7 +883,7 @@ fn runCommand( |
| 816 | 883 | }, |
| 817 | 884 | }) |stream| { |
| 818 | 885 | if (stream.captured) |output| { |
| 819 | | const output_components = .{ "o", digest.?, output.basename }; |
| 886 | const output_components = .{ tmp_dir_path.?, output.basename }; |
| 820 | 887 | const output_path = try b.cache_root.join(arena, &output_components); |
| 821 | 888 | output.generated_file.path = output_path; |
| 822 | 889 | |