| ... | @@ -243,7 +243,7 @@ pub fn addDepFileOutputArg(self: *Run, basename: []const u8) std.Build.LazyPath | ... | @@ -243,7 +243,7 @@ pub fn addDepFileOutputArg(self: *Run, basename: []const u8) std.Build.LazyPath |
| 243 | /// Add a prefixed path argument to a dep file (.d) for the child process to | 243 | /// Add a prefixed path argument to a dep file (.d) for the child process to |
| 244 | /// write its discovered additional dependencies. | 244 | /// write its discovered additional dependencies. |
| 245 | /// Only one dep file argument is allowed by instance. | 245 | /// Only one dep file argument is allowed by instance. |
| 246 | pub fn addPrefixedDepFileOutputArg(self: *Run, prefix: []const u8, basename: []const u8) void { | 246 | pub fn addPrefixedDepFileOutputArg(self: *Run, prefix: []const u8, basename: []const u8) std.Build.LazyPath { |
| 247 | assert(self.dep_output_file == null); | 247 | assert(self.dep_output_file == null); |
| 248 | | 248 | |
| 249 | const b = self.step.owner; | 249 | const b = self.step.owner; |
| ... | @@ -258,6 +258,8 @@ pub fn addPrefixedDepFileOutputArg(self: *Run, prefix: []const u8, basename: []c | ... | @@ -258,6 +258,8 @@ pub fn addPrefixedDepFileOutputArg(self: *Run, prefix: []const u8, basename: []c |
| 258 | self.dep_output_file = dep_file; | 258 | self.dep_output_file = dep_file; |
| 259 | | 259 | |
| 260 | self.argv.append(.{ .output = dep_file }) catch @panic("OOM"); | 260 | self.argv.append(.{ .output = dep_file }) catch @panic("OOM"); |
| | 261 | |
| | 262 | return .{ .generated = &dep_file.generated_file }; |
| 261 | } | 263 | } |
| 262 | | 264 | |
| 263 | pub fn addArg(self: *Run, arg: []const u8) void { | 265 | pub fn addArg(self: *Run, arg: []const u8) void { |
| ... | @@ -448,6 +450,10 @@ fn checksContainStderr(checks: []const StdIo.Check) bool { | ... | @@ -448,6 +450,10 @@ fn checksContainStderr(checks: []const StdIo.Check) bool { |
| 448 | return false; | 450 | return false; |
| 449 | } | 451 | } |
| 450 | | 452 | |
| | 453 | const IndexedOutput = struct { |
| | 454 | index: usize, |
| | 455 | output: *Output, |
| | 456 | }; |
| 451 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 457 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 452 | const b = step.owner; | 458 | const b = step.owner; |
| 453 | const arena = b.allocator; | 459 | const arena = b.allocator; |
| ... | @@ -455,10 +461,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -455,10 +461,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 455 | const has_side_effects = self.hasSideEffects(); | 461 | const has_side_effects = self.hasSideEffects(); |
| 456 | | 462 | |
| 457 | var argv_list = ArrayList([]const u8).init(arena); | 463 | var argv_list = ArrayList([]const u8).init(arena); |
| 458 | var output_placeholders = ArrayList(struct { | 464 | var output_placeholders = ArrayList(IndexedOutput).init(arena); |
| 459 | index: usize, | | |
| 460 | output: *Output, | | |
| 461 | }).init(arena); | | |
| 462 | | 465 | |
| 463 | var man = b.cache.obtain(); | 466 | var man = b.cache.obtain(); |
| 464 | defer man.deinit(); | 467 | defer man.deinit(); |
| ... | @@ -540,32 +543,25 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -540,32 +543,25 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 540 | if (try step.cacheHit(&man)) { | 543 | if (try step.cacheHit(&man)) { |
| 541 | // cache hit, skip running command | 544 | // cache hit, skip running command |
| 542 | const digest = man.final(); | 545 | const digest = man.final(); |
| 543 | for (output_placeholders.items) |placeholder| { | | |
| 544 | placeholder.output.generated_file.path = try b.cache_root.join(arena, &.{ | | |
| 545 | "o", &digest, placeholder.output.basename, | | |
| 546 | }); | | |
| 547 | } | | |
| 548 | | 546 | |
| 549 | if (self.captured_stdout) |output| { | 547 | try populateGeneratedPaths( |
| 550 | output.generated_file.path = try b.cache_root.join(arena, &.{ | 548 | arena, |
| 551 | "o", &digest, output.basename, | 549 | output_placeholders.items, |
| 552 | }); | 550 | self.captured_stdout, |
| 553 | } | 551 | self.captured_stderr, |
| 554 | | 552 | b.cache_root, |
| 555 | if (self.captured_stderr) |output| { | 553 | &digest, |
| 556 | output.generated_file.path = try b.cache_root.join(arena, &.{ | 554 | ); |
| 557 | "o", &digest, output.basename, | | |
| 558 | }); | | |
| 559 | } | | |
| 560 | | 555 | |
| 561 | step.result_cached = true; | 556 | step.result_cached = true; |
| 562 | return; | 557 | return; |
| 563 | } | 558 | } |
| 564 | | 559 | |
| 565 | const digest = man.final(); | 560 | const rand_int = std.crypto.random.int(u64); |
| | 561 | const tmp_dir_path = "tmp" ++ fs.path.sep_str ++ std.Build.hex64(rand_int); |
| 566 | | 562 | |
| 567 | for (output_placeholders.items) |placeholder| { | 563 | for (output_placeholders.items) |placeholder| { |
| 568 | const output_components = .{ "o", &digest, placeholder.output.basename }; | 564 | const output_components = .{ tmp_dir_path, placeholder.output.basename }; |
| 569 | const output_sub_path = try fs.path.join(arena, &output_components); | 565 | const output_sub_path = try fs.path.join(arena, &output_components); |
| 570 | const output_sub_dir_path = fs.path.dirname(output_sub_path).?; | 566 | const output_sub_dir_path = fs.path.dirname(output_sub_path).?; |
| 571 | b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { | 567 | b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { |
| ... | @@ -582,12 +578,83 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -582,12 +578,83 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 582 | argv_list.items[placeholder.index] = cli_arg; | 578 | argv_list.items[placeholder.index] = cli_arg; |
| 583 | } | 579 | } |
| 584 | | 580 | |
| 585 | try runCommand(self, argv_list.items, has_side_effects, &digest, prog_node); | 581 | try runCommand(self, argv_list.items, has_side_effects, tmp_dir_path, prog_node); |
| 586 | | 582 | |
| 587 | if (self.dep_output_file) |dep_output_file| | 583 | if (self.dep_output_file) |dep_output_file| |
| 588 | try man.addDepFilePost(std.fs.cwd(), dep_output_file.generated_file.getPath()); | 584 | try man.addDepFilePost(std.fs.cwd(), dep_output_file.generated_file.getPath()); |
| 589 | | 585 | |
| | 586 | const digest = man.final(); |
| | 587 | |
| | 588 | const any_output = output_placeholders.items.len > 0 or |
| | 589 | self.captured_stdout != null or self.captured_stderr != null; |
| | 590 | |
| | 591 | // Rename into place |
| | 592 | if (any_output) { |
| | 593 | const o_sub_path = "o" ++ fs.path.sep_str ++ &digest; |
| | 594 | |
| | 595 | b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| { |
| | 596 | if (err == error.PathAlreadyExists) { |
| | 597 | b.cache_root.handle.deleteTree(o_sub_path) catch |del_err| { |
| | 598 | return step.fail("unable to remove dir '{}'{s}: {s}", .{ |
| | 599 | b.cache_root, |
| | 600 | tmp_dir_path, |
| | 601 | @errorName(del_err), |
| | 602 | }); |
| | 603 | }; |
| | 604 | b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |retry_err| { |
| | 605 | return step.fail("unable to rename dir '{}{s}' to '{}{s}': {s}", .{ |
| | 606 | b.cache_root, tmp_dir_path, |
| | 607 | b.cache_root, o_sub_path, |
| | 608 | @errorName(retry_err), |
| | 609 | }); |
| | 610 | }; |
| | 611 | } else { |
| | 612 | return step.fail("unable to rename dir '{}{s}' to '{}{s}': {s}", .{ |
| | 613 | b.cache_root, tmp_dir_path, |
| | 614 | b.cache_root, o_sub_path, |
| | 615 | @errorName(err), |
| | 616 | }); |
| | 617 | } |
| | 618 | }; |
| | 619 | } |
| | 620 | |
| 590 | try step.writeManifest(&man); | 621 | try step.writeManifest(&man); |
| | 622 | |
| | 623 | try populateGeneratedPaths( |
| | 624 | arena, |
| | 625 | output_placeholders.items, |
| | 626 | self.captured_stdout, |
| | 627 | self.captured_stderr, |
| | 628 | b.cache_root, |
| | 629 | &digest, |
| | 630 | ); |
| | 631 | } |
| | 632 | |
| | 633 | fn populateGeneratedPaths( |
| | 634 | arena: std.mem.Allocator, |
| | 635 | output_placeholders: []const IndexedOutput, |
| | 636 | captured_stdout: ?*Output, |
| | 637 | captured_stderr: ?*Output, |
| | 638 | cache_root: Build.Cache.Directory, |
| | 639 | digest: *const Build.Cache.HexDigest, |
| | 640 | ) !void { |
| | 641 | for (output_placeholders) |placeholder| { |
| | 642 | placeholder.output.generated_file.path = try cache_root.join(arena, &.{ |
| | 643 | "o", digest, placeholder.output.basename, |
| | 644 | }); |
| | 645 | } |
| | 646 | |
| | 647 | if (captured_stdout) |output| { |
| | 648 | output.generated_file.path = try cache_root.join(arena, &.{ |
| | 649 | "o", digest, output.basename, |
| | 650 | }); |
| | 651 | } |
| | 652 | |
| | 653 | if (captured_stderr) |output| { |
| | 654 | output.generated_file.path = try cache_root.join(arena, &.{ |
| | 655 | "o", digest, output.basename, |
| | 656 | }); |
| | 657 | } |
| 591 | } | 658 | } |
| 592 | | 659 | |
| 593 | fn formatTerm( | 660 | fn formatTerm( |
| ... | @@ -639,7 +706,7 @@ fn runCommand( | ... | @@ -639,7 +706,7 @@ fn runCommand( |
| 639 | self: *Run, | 706 | self: *Run, |
| 640 | argv: []const []const u8, | 707 | argv: []const []const u8, |
| 641 | has_side_effects: bool, | 708 | has_side_effects: bool, |
| 642 | digest: ?*const [std.Build.Cache.hex_digest_len]u8, | 709 | tmp_dir_path: ?[]const u8, |
| 643 | prog_node: *std.Progress.Node, | 710 | prog_node: *std.Progress.Node, |
| 644 | ) !void { | 711 | ) !void { |
| 645 | const step = &self.step; | 712 | const step = &self.step; |
| ... | @@ -812,7 +879,7 @@ fn runCommand( | ... | @@ -812,7 +879,7 @@ fn runCommand( |
| 812 | }, | 879 | }, |
| 813 | }) |stream| { | 880 | }) |stream| { |
| 814 | if (stream.captured) |output| { | 881 | if (stream.captured) |output| { |
| 815 | const output_components = .{ "o", digest.?, output.basename }; | 882 | const output_components = .{ tmp_dir_path.?, output.basename }; |
| 816 | const output_path = try b.cache_root.join(arena, &output_components); | 883 | const output_path = try b.cache_root.join(arena, &output_components); |
| 817 | output.generated_file.path = output_path; | 884 | output.generated_file.path = output_path; |
| 818 | | 885 | |