authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-06-05 13:23:20+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-06-13 16:30:39+01:00
log14e033ed95a43a5ff994df9dc524e5bc4f34452a
tree94d91e0eeceff82157e6741c0c386780529ae4d8
parent5c8b92db7f6e99d075af1cf87d48a5af0c748603
signaturelock-open Commit is signed but in an unrecognized format.

std.Build.Step.Run: convert relative paths to be relative to child cwd

Because any `LazyPath` might be resolved to a relative path, it's incorrect to pass that directly to a child process whose cwd might differ. Instead, if the child has an overriden cwd, we need to convert such paths to be relative to the child cwd using `std.fs.path.relative`.

1 files changed, 46 insertions(+), 22 deletions(-)

lib/std/Build/Step/Run.zig+46-22
......@@ -622,6 +622,18 @@ fn checksContainStderr(checks: []const StdIo.Check) bool {
622622 return false;
623623}
624624
625/// If `path` is cwd-relative, make it relative to the cwd of the child instead.
626///
627/// Whenever a path is included in the argv of a child, it should be put through this function first
628/// to make sure the child doesn't see paths relative to a cwd other than its own.
629fn convertPathArg(run: *Run, path: Build.Cache.Path) []const u8 {
630 const b = run.step.owner;
631 const path_str = path.toString(b.graph.arena) catch @panic("OOM");
632 const child_lazy_cwd = run.cwd orelse return path_str;
633 const child_cwd = child_lazy_cwd.getPath3(b, &run.step).toString(b.graph.arena) catch @panic("OOM");
634 return std.fs.path.relative(b.graph.arena, child_cwd, path_str) catch @panic("OOM");
635}
636
625637const IndexedOutput = struct {
626638 index: usize,
627639 tag: @typeInfo(Arg).@"union".tag_type.?,
......@@ -676,14 +688,14 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
676688 man.hash.addBytes(bytes);
677689 },
678690 .lazy_path => |file| {
679 const file_path = file.lazy_path.getPath2(b, step);
680 try argv_list.append(b.fmt("{s}{s}", .{ file.prefix, file_path }));
691 const file_path = file.lazy_path.getPath3(b, step);
692 try argv_list.append(b.fmt("{s}{s}", .{ file.prefix, run.convertPathArg(file_path) }));
681693 man.hash.addBytes(file.prefix);
682 _ = try man.addFile(file_path, null);
694 _ = try man.addFilePath(file_path, null);
683695 },
684696 .decorated_directory => |dd| {
685697 const file_path = dd.lazy_path.getPath3(b, step);
686 const resolved_arg = b.fmt("{s}{}{s}", .{ dd.prefix, file_path, dd.suffix });
698 const resolved_arg = b.fmt("{s}{s}{s}", .{ dd.prefix, run.convertPathArg(file_path), dd.suffix });
687699 try argv_list.append(resolved_arg);
688700 man.hash.addBytes(resolved_arg);
689701 },
......@@ -696,7 +708,10 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
696708 }
697709 const file_path = artifact.installed_path orelse artifact.generated_bin.?.path.?;
698710
699 try argv_list.append(b.fmt("{s}{s}", .{ pa.prefix, file_path }));
711 try argv_list.append(b.fmt("{s}{s}", .{
712 pa.prefix,
713 run.convertPathArg(.{ .root_dir = .cwd(), .sub_path = file_path }),
714 }));
700715
701716 _ = try man.addFile(file_path, null);
702717 },
......@@ -787,11 +802,14 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
787802 b.cache_root, output_sub_dir_path, @errorName(err),
788803 });
789804 };
790 const output_path = placeholder.output.generated_file.path.?;
805 const arg_output_path = run.convertPathArg(.{
806 .root_dir = .cwd(),
807 .sub_path = placeholder.output.generated_file.getPath(),
808 });
791809 argv_list.items[placeholder.index] = if (placeholder.output.prefix.len == 0)
792 output_path
810 arg_output_path
793811 else
794 b.fmt("{s}{s}", .{ placeholder.output.prefix, output_path });
812 b.fmt("{s}{s}", .{ placeholder.output.prefix, arg_output_path });
795813 }
796814
797815 try runCommand(run, argv_list.items, has_side_effects, output_dir_path, prog_node, null);
......@@ -816,12 +834,15 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
816834 b.cache_root, output_sub_dir_path, @errorName(err),
817835 });
818836 };
819 const output_path = try b.cache_root.join(arena, &output_components);
820 placeholder.output.generated_file.path = output_path;
821 argv_list.items[placeholder.index] = if (placeholder.output.prefix.len == 0)
822 output_path
823 else
824 b.fmt("{s}{s}", .{ placeholder.output.prefix, output_path });
837 const raw_output_path: Build.Cache.Path = .{
838 .root_dir = b.cache_root,
839 .sub_path = b.pathJoin(&output_components),
840 };
841 placeholder.output.generated_file.path = raw_output_path.toString(b.graph.arena) catch @panic("OOM");
842 argv_list.items[placeholder.index] = b.fmt("{s}{s}", .{
843 placeholder.output.prefix,
844 run.convertPathArg(raw_output_path),
845 });
825846 }
826847
827848 try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, prog_node, null);
......@@ -899,20 +920,23 @@ pub fn rerunInFuzzMode(
899920 try argv_list.append(arena, bytes);
900921 },
901922 .lazy_path => |file| {
902 const file_path = file.lazy_path.getPath2(b, step);
903 try argv_list.append(arena, b.fmt("{s}{s}", .{ file.prefix, file_path }));
923 const file_path = file.lazy_path.getPath3(b, step);
924 try argv_list.append(arena, b.fmt("{s}{s}", .{ file.prefix, run.convertPathArg(file_path) }));
904925 },
905926 .decorated_directory => |dd| {
906927 const file_path = dd.lazy_path.getPath3(b, step);
907 try argv_list.append(arena, b.fmt("{s}{}{s}", .{ dd.prefix, file_path, dd.suffix }));
928 try argv_list.append(arena, b.fmt("{s}{s}{s}", .{ dd.prefix, run.convertPathArg(file_path), dd.suffix }));
908929 },
909930 .artifact => |pa| {
910931 const artifact = pa.artifact;
911 const file_path = if (artifact == run.producer.?)
912 b.fmt("{}", .{run.rebuilt_executable.?})
913 else
914 (artifact.installed_path orelse artifact.generated_bin.?.path.?);
915 try argv_list.append(arena, b.fmt("{s}{s}", .{ pa.prefix, file_path }));
932 const file_path: []const u8 = p: {
933 if (artifact == run.producer.?) break :p b.fmt("{}", .{run.rebuilt_executable.?});
934 break :p artifact.installed_path orelse artifact.generated_bin.?.path.?;
935 };
936 try argv_list.append(arena, b.fmt("{s}{s}", .{
937 pa.prefix,
938 run.convertPathArg(.{ .root_dir = .cwd(), .sub_path = file_path }),
939 }));
916940 },
917941 .output_file, .output_directory => unreachable,
918942 }