Skip to content

Commit 7edba14

Browse files
Step.Run: change cwd to ?Build.LazyPath (#17418)
closes #17409
1 parent 7abf9b3 commit 7edba14

File tree

2 files changed

+35
-29
lines changed

2 files changed

+35
-29
lines changed

lib/std/Build/Step/Run.zig

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const std = @import("std");
22
const builtin = @import("builtin");
3-
const Step = std.Build.Step;
3+
const Build = std.Build;
4+
const Step = Build.Step;
45
const fs = std.fs;
56
const mem = std.mem;
67
const process = std.process;
@@ -19,10 +20,8 @@ step: Step,
1920
/// See also addArg and addArgs to modifying this directly
2021
argv: ArrayList(Arg),
2122

22-
/// Set this to modify the current working directory
23-
/// TODO change this to a Build.Cache.Directory to better integrate with
24-
/// future child process cwd API.
25-
cwd: ?[]const u8,
23+
/// Use `setCwd` to set the initial current working directory
24+
cwd: ?Build.LazyPath,
2625

2726
/// Override this field to modify the environment, or use setEnvironmentVariable
2827
env_map: ?*EnvMap,
@@ -287,6 +286,11 @@ pub fn setStdIn(self: *Run, stdin: StdIn) void {
287286
self.stdin = stdin;
288287
}
289288

289+
pub fn setCwd(self: *Run, cwd: Build.LazyPath) void {
290+
cwd.addStepDependencies(&self.step);
291+
self.cwd = cwd;
292+
}
293+
290294
pub fn clearEnvironment(self: *Run) void {
291295
const b = self.step.owner;
292296
const new_env_map = b.allocator.create(EnvMap) catch @panic("OOM");
@@ -650,8 +654,10 @@ fn runCommand(
650654
const b = step.owner;
651655
const arena = b.allocator;
652656

653-
try step.handleChildProcUnsupported(self.cwd, argv);
654-
try Step.handleVerbose2(step.owner, self.cwd, self.env_map, argv);
657+
const cwd: ?[]const u8 = if (self.cwd) |lazy_cwd| lazy_cwd.getPath(b) else null;
658+
659+
try step.handleChildProcUnsupported(cwd, argv);
660+
try Step.handleVerbose2(step.owner, cwd, self.env_map, argv);
655661

656662
const allow_skip = switch (self.stdio) {
657663
.check, .zig_test => self.skip_foreign_checks,
@@ -778,7 +784,7 @@ fn runCommand(
778784
self.addPathForDynLibs(exe);
779785
}
780786

781-
try Step.handleVerbose2(step.owner, self.cwd, self.env_map, interp_argv.items);
787+
try Step.handleVerbose2(step.owner, cwd, self.env_map, interp_argv.items);
782788

783789
break :term spawnChildAndCollect(self, interp_argv.items, has_side_effects, prog_node) catch |e| {
784790
if (!self.failing_to_execute_foreign_is_an_error) return error.MakeSkipped;
@@ -848,7 +854,7 @@ fn runCommand(
848854
, .{
849855
expected_bytes,
850856
result.stdio.stderr.?,
851-
try Step.allocPrintCmd(arena, self.cwd, final_argv),
857+
try Step.allocPrintCmd(arena, cwd, final_argv),
852858
});
853859
}
854860
},
@@ -865,7 +871,7 @@ fn runCommand(
865871
, .{
866872
match,
867873
result.stdio.stderr.?,
868-
try Step.allocPrintCmd(arena, self.cwd, final_argv),
874+
try Step.allocPrintCmd(arena, cwd, final_argv),
869875
});
870876
}
871877
},
@@ -882,7 +888,7 @@ fn runCommand(
882888
, .{
883889
expected_bytes,
884890
result.stdio.stdout.?,
885-
try Step.allocPrintCmd(arena, self.cwd, final_argv),
891+
try Step.allocPrintCmd(arena, cwd, final_argv),
886892
});
887893
}
888894
},
@@ -899,7 +905,7 @@ fn runCommand(
899905
, .{
900906
match,
901907
result.stdio.stdout.?,
902-
try Step.allocPrintCmd(arena, self.cwd, final_argv),
908+
try Step.allocPrintCmd(arena, cwd, final_argv),
903909
});
904910
}
905911
},
@@ -908,7 +914,7 @@ fn runCommand(
908914
return step.fail("the following command {} (expected {}):\n{s}", .{
909915
fmtTerm(result.term),
910916
fmtTerm(expected_term),
911-
try Step.allocPrintCmd(arena, self.cwd, final_argv),
917+
try Step.allocPrintCmd(arena, cwd, final_argv),
912918
});
913919
}
914920
},
@@ -929,18 +935,18 @@ fn runCommand(
929935
prefix,
930936
fmtTerm(result.term),
931937
fmtTerm(expected_term),
932-
try Step.allocPrintCmd(arena, self.cwd, final_argv),
938+
try Step.allocPrintCmd(arena, cwd, final_argv),
933939
});
934940
}
935941
if (!result.stdio.test_results.isSuccess()) {
936942
return step.fail(
937943
"{s}the following test command failed:\n{s}",
938-
.{ prefix, try Step.allocPrintCmd(arena, self.cwd, final_argv) },
944+
.{ prefix, try Step.allocPrintCmd(arena, cwd, final_argv) },
939945
);
940946
}
941947
},
942948
else => {
943-
try step.handleChildProcessTerm(result.term, self.cwd, final_argv);
949+
try step.handleChildProcessTerm(result.term, cwd, final_argv);
944950
},
945951
}
946952
}
@@ -963,8 +969,8 @@ fn spawnChildAndCollect(
963969
const arena = b.allocator;
964970

965971
var child = std.process.Child.init(argv, arena);
966-
if (self.cwd) |cwd| {
967-
child.cwd = b.pathFromRoot(cwd);
972+
if (self.cwd) |lazy_cwd| {
973+
child.cwd = lazy_cwd.getPath(b);
968974
} else {
969975
child.cwd = b.build_root.path;
970976
child.cwd_dir = b.build_root.handle;

test/tests.zig

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -695,15 +695,15 @@ pub fn addCliTests(b: *std.Build) *Step {
695695
// Test `zig init-lib`.
696696
const tmp_path = b.makeTempPath();
697697
const init_lib = b.addSystemCommand(&.{ b.zig_exe, "init-lib" });
698-
init_lib.cwd = tmp_path;
698+
init_lib.setCwd(.{ .cwd_relative = tmp_path });
699699
init_lib.setName("zig init-lib");
700700
init_lib.expectStdOutEqual("");
701701
init_lib.expectStdErrEqual("info: Created build.zig\n" ++
702702
"info: Created src" ++ s ++ "main.zig\n" ++
703703
"info: Next, try `zig build --help` or `zig build test`\n");
704704

705705
const run_test = b.addSystemCommand(&.{ b.zig_exe, "build", "test" });
706-
run_test.cwd = tmp_path;
706+
run_test.setCwd(.{ .cwd_relative = tmp_path });
707707
run_test.setName("zig build test");
708708
run_test.expectStdOutEqual("");
709709
run_test.step.dependOn(&init_lib.step);
@@ -718,7 +718,7 @@ pub fn addCliTests(b: *std.Build) *Step {
718718
// Test `zig init-exe`.
719719
const tmp_path = b.makeTempPath();
720720
const init_exe = b.addSystemCommand(&.{ b.zig_exe, "init-exe" });
721-
init_exe.cwd = tmp_path;
721+
init_exe.setCwd(.{ .cwd_relative = tmp_path });
722722
init_exe.setName("zig init-exe");
723723
init_exe.expectStdOutEqual("");
724724
init_exe.expectStdErrEqual("info: Created build.zig\n" ++
@@ -737,13 +737,13 @@ pub fn addCliTests(b: *std.Build) *Step {
737737
run_bad.step.dependOn(&init_exe.step);
738738

739739
const run_test = b.addSystemCommand(&.{ b.zig_exe, "build", "test" });
740-
run_test.cwd = tmp_path;
740+
run_test.setCwd(.{ .cwd_relative = tmp_path });
741741
run_test.setName("zig build test");
742742
run_test.expectStdOutEqual("");
743743
run_test.step.dependOn(&init_exe.step);
744744

745745
const run_run = b.addSystemCommand(&.{ b.zig_exe, "build", "run" });
746-
run_run.cwd = tmp_path;
746+
run_run.setCwd(.{ .cwd_relative = tmp_path });
747747
run_run.setName("zig build run");
748748
run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n");
749749
run_run.expectStdErrEqual("All your codebase are belong to us.\n");
@@ -821,39 +821,39 @@ pub fn addCliTests(b: *std.Build) *Step {
821821
// Test zig fmt affecting only the appropriate files.
822822
const run1 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "fmt1.zig" });
823823
run1.setName("run zig fmt one file");
824-
run1.cwd = tmp_path;
824+
run1.setCwd(.{ .cwd_relative = tmp_path });
825825
run1.has_side_effects = true;
826826
// stdout should be file path + \n
827827
run1.expectStdOutEqual("fmt1.zig\n");
828828

829829
// Test excluding files and directories from a run
830830
const run2 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." });
831831
run2.setName("run zig fmt on directory with exclusions");
832-
run2.cwd = tmp_path;
832+
run2.setCwd(.{ .cwd_relative = tmp_path });
833833
run2.has_side_effects = true;
834834
run2.expectStdOutEqual("");
835835
run2.step.dependOn(&run1.step);
836836

837837
// Test excluding non-existent file
838838
const run3 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." });
839839
run3.setName("run zig fmt on directory with non-existent exclusion");
840-
run3.cwd = tmp_path;
840+
run3.setCwd(.{ .cwd_relative = tmp_path });
841841
run3.has_side_effects = true;
842842
run3.expectStdOutEqual("." ++ s ++ "subdir" ++ s ++ "fmt3.zig\n");
843843
run3.step.dependOn(&run2.step);
844844

845845
// running it on the dir, only the new file should be changed
846846
const run4 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." });
847847
run4.setName("run zig fmt the directory");
848-
run4.cwd = tmp_path;
848+
run4.setCwd(.{ .cwd_relative = tmp_path });
849849
run4.has_side_effects = true;
850850
run4.expectStdOutEqual("." ++ s ++ "fmt2.zig\n");
851851
run4.step.dependOn(&run3.step);
852852

853853
// both files have been formatted, nothing should change now
854854
const run5 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." });
855855
run5.setName("run zig fmt with nothing to do");
856-
run5.cwd = tmp_path;
856+
run5.setCwd(.{ .cwd_relative = tmp_path });
857857
run5.has_side_effects = true;
858858
run5.expectStdOutEqual("");
859859
run5.step.dependOn(&run4.step);
@@ -867,7 +867,7 @@ pub fn addCliTests(b: *std.Build) *Step {
867867
// Test `zig fmt` handling UTF-16 decoding.
868868
const run6 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." });
869869
run6.setName("run zig fmt convert UTF-16 to UTF-8");
870-
run6.cwd = tmp_path;
870+
run6.setCwd(.{ .cwd_relative = tmp_path });
871871
run6.has_side_effects = true;
872872
run6.expectStdOutEqual("." ++ s ++ "fmt6.zig\n");
873873
run6.step.dependOn(&write6.step);

0 commit comments

Comments
 (0)