| ... | @@ -249,7 +249,7 @@ pub fn addDepFileOutputArg(self: *Run, basename: []const u8) std.Build.LazyPath | ... | @@ -249,7 +249,7 @@ pub fn addDepFileOutputArg(self: *Run, basename: []const u8) std.Build.LazyPath |
| 249 | /// Add a prefixed path argument to a dep file (.d) for the child process to | 249 | /// Add a prefixed path argument to a dep file (.d) for the child process to |
| 250 | /// write its discovered additional dependencies. | 250 | /// write its discovered additional dependencies. |
| 251 | /// Only one dep file argument is allowed by instance. | 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 | assert(self.dep_output_file == null); | 253 | assert(self.dep_output_file == null); |
| 254 | | 254 | |
| 255 | const b = self.step.owner; | 255 | const b = self.step.owner; |
| ... | @@ -264,6 +264,8 @@ pub fn addPrefixedDepFileOutputArg(self: *Run, prefix: []const u8, basename: []c | ... | @@ -264,6 +264,8 @@ pub fn addPrefixedDepFileOutputArg(self: *Run, prefix: []const u8, basename: []c |
| 264 | self.dep_output_file = dep_file; | 264 | self.dep_output_file = dep_file; |
| 265 | | 265 | |
| 266 | self.argv.append(.{ .output = dep_file }) catch @panic("OOM"); | 266 | self.argv.append(.{ .output = dep_file }) catch @panic("OOM"); |
| | 267 | |
| | 268 | return .{ .generated = &dep_file.generated_file }; |
| 267 | } | 269 | } |
| 268 | | 270 | |
| 269 | pub fn addArg(self: *Run, arg: []const u8) void { | 271 | pub fn addArg(self: *Run, arg: []const u8) void { |
| ... | @@ -454,6 +456,10 @@ fn checksContainStderr(checks: []const StdIo.Check) bool { | ... | @@ -454,6 +456,10 @@ fn checksContainStderr(checks: []const StdIo.Check) bool { |
| 454 | return false; | 456 | return false; |
| 455 | } | 457 | } |
| 456 | | 458 | |
| | 459 | const IndexedOutput = struct { |
| | 460 | index: usize, |
| | 461 | output: *Output, |
| | 462 | }; |
| 457 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 463 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 458 | const b = step.owner; | 464 | const b = step.owner; |
| 459 | const arena = b.allocator; | 465 | const arena = b.allocator; |
| ... | @@ -461,10 +467,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -461,10 +467,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 461 | const has_side_effects = self.hasSideEffects(); | 467 | const has_side_effects = self.hasSideEffects(); |
| 462 | | 468 | |
| 463 | var argv_list = ArrayList([]const u8).init(arena); | 469 | var argv_list = ArrayList([]const u8).init(arena); |
| 464 | var output_placeholders = ArrayList(struct { | 470 | var output_placeholders = ArrayList(IndexedOutput).init(arena); |
| 465 | index: usize, | | |
| 466 | output: *Output, | | |
| 467 | }).init(arena); | | |
| 468 | | 471 | |
| 469 | var man = b.cache.obtain(); | 472 | var man = b.cache.obtain(); |
| 470 | defer man.deinit(); | 473 | defer man.deinit(); |
| ... | @@ -546,32 +549,25 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -546,32 +549,25 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 546 | if (try step.cacheHit(&man)) { | 549 | if (try step.cacheHit(&man)) { |
| 547 | // cache hit, skip running command | 550 | // cache hit, skip running command |
| 548 | const digest = man.final(); | 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| { | 553 | try populateGeneratedPaths( |
| 556 | output.generated_file.path = try b.cache_root.join(arena, &.{ | 554 | arena, |
| 557 | "o", &digest, output.basename, | 555 | output_placeholders.items, |
| 558 | }); | 556 | self.captured_stdout, |
| 559 | } | 557 | self.captured_stderr, |
| 560 | | 558 | b.cache_root, |
| 561 | if (self.captured_stderr) |output| { | 559 | &digest, |
| 562 | output.generated_file.path = try b.cache_root.join(arena, &.{ | 560 | ); |
| 563 | "o", &digest, output.basename, | | |
| 564 | }); | | |
| 565 | } | | |
| 566 | | 561 | |
| 567 | step.result_cached = true; | 562 | step.result_cached = true; |
| 568 | return; | 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 | for (output_placeholders.items) |placeholder| { | 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 | const output_sub_path = try fs.path.join(arena, &output_components); | 571 | const output_sub_path = try fs.path.join(arena, &output_components); |
| 576 | const output_sub_dir_path = fs.path.dirname(output_sub_path).?; | 572 | const output_sub_dir_path = fs.path.dirname(output_sub_path).?; |
| 577 | b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { | 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,12 +584,83 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 588 | argv_list.items[placeholder.index] = cli_arg; | 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 | if (self.dep_output_file) |dep_output_file| | 589 | if (self.dep_output_file) |dep_output_file| |
| 594 | try man.addDepFilePost(std.fs.cwd(), dep_output_file.generated_file.getPath()); | 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 | try step.writeManifest(&man); | 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 | fn formatTerm( | 666 | fn formatTerm( |
| ... | @@ -645,7 +712,7 @@ fn runCommand( | ... | @@ -645,7 +712,7 @@ fn runCommand( |
| 645 | self: *Run, | 712 | self: *Run, |
| 646 | argv: []const []const u8, | 713 | argv: []const []const u8, |
| 647 | has_side_effects: bool, | 714 | has_side_effects: bool, |
| 648 | digest: ?*const [std.Build.Cache.hex_digest_len]u8, | 715 | tmp_dir_path: ?[]const u8, |
| 649 | prog_node: *std.Progress.Node, | 716 | prog_node: *std.Progress.Node, |
| 650 | ) !void { | 717 | ) !void { |
| 651 | const step = &self.step; | 718 | const step = &self.step; |
| ... | @@ -816,7 +883,7 @@ fn runCommand( | ... | @@ -816,7 +883,7 @@ fn runCommand( |
| 816 | }, | 883 | }, |
| 817 | }) |stream| { | 884 | }) |stream| { |
| 818 | if (stream.captured) |output| { | 885 | if (stream.captured) |output| { |
| 819 | const output_components = .{ "o", digest.?, output.basename }; | 886 | const output_components = .{ tmp_dir_path.?, output.basename }; |
| 820 | const output_path = try b.cache_root.join(arena, &output_components); | 887 | const output_path = try b.cache_root.join(arena, &output_components); |
| 821 | output.generated_file.path = output_path; | 888 | output.generated_file.path = output_path; |
| 822 | | 889 | |