From 7edba14d7cba465a2ffe12a45f96424849bbaf11 Mon Sep 17 00:00:00 2001 From: Krzysztof Wolicki Date: Wed, 11 Oct 2023 00:39:44 +0200 Subject: [PATCH] Step.Run: change `cwd` to `?Build.LazyPath` (#17418) closes #17409 --- lib/std/Build/Step/Run.zig | 42 ++++++++++++++++++++++---------------- test/tests.zig | 22 ++++++++++---------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 9d8f26559c..845abe83bb 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1,6 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); -const Step = std.Build.Step; +const Build = std.Build; +const Step = Build.Step; const fs = std.fs; const mem = std.mem; const process = std.process; @@ -19,10 +20,8 @@ step: Step, /// See also addArg and addArgs to modifying this directly argv: ArrayList(Arg), -/// Set this to modify the current working directory -/// TODO change this to a Build.Cache.Directory to better integrate with -/// future child process cwd API. -cwd: ?[]const u8, +/// Use `setCwd` to set the initial current working directory +cwd: ?Build.LazyPath, /// Override this field to modify the environment, or use setEnvironmentVariable env_map: ?*EnvMap, @@ -287,6 +286,11 @@ pub fn setStdIn(self: *Run, stdin: StdIn) void { self.stdin = stdin; } +pub fn setCwd(self: *Run, cwd: Build.LazyPath) void { + cwd.addStepDependencies(&self.step); + self.cwd = cwd; +} + pub fn clearEnvironment(self: *Run) void { const b = self.step.owner; const new_env_map = b.allocator.create(EnvMap) catch @panic("OOM"); @@ -650,8 +654,10 @@ fn runCommand( const b = step.owner; const arena = b.allocator; - try step.handleChildProcUnsupported(self.cwd, argv); - try Step.handleVerbose2(step.owner, self.cwd, self.env_map, argv); + const cwd: ?[]const u8 = if (self.cwd) |lazy_cwd| lazy_cwd.getPath(b) else null; + + try step.handleChildProcUnsupported(cwd, argv); + try Step.handleVerbose2(step.owner, cwd, self.env_map, argv); const allow_skip = switch (self.stdio) { .check, .zig_test => self.skip_foreign_checks, @@ -778,7 +784,7 @@ fn runCommand( self.addPathForDynLibs(exe); } - try Step.handleVerbose2(step.owner, self.cwd, self.env_map, interp_argv.items); + try Step.handleVerbose2(step.owner, cwd, self.env_map, interp_argv.items); break :term spawnChildAndCollect(self, interp_argv.items, has_side_effects, prog_node) catch |e| { if (!self.failing_to_execute_foreign_is_an_error) return error.MakeSkipped; @@ -848,7 +854,7 @@ fn runCommand( , .{ expected_bytes, result.stdio.stderr.?, - try Step.allocPrintCmd(arena, self.cwd, final_argv), + try Step.allocPrintCmd(arena, cwd, final_argv), }); } }, @@ -865,7 +871,7 @@ fn runCommand( , .{ match, result.stdio.stderr.?, - try Step.allocPrintCmd(arena, self.cwd, final_argv), + try Step.allocPrintCmd(arena, cwd, final_argv), }); } }, @@ -882,7 +888,7 @@ fn runCommand( , .{ expected_bytes, result.stdio.stdout.?, - try Step.allocPrintCmd(arena, self.cwd, final_argv), + try Step.allocPrintCmd(arena, cwd, final_argv), }); } }, @@ -899,7 +905,7 @@ fn runCommand( , .{ match, result.stdio.stdout.?, - try Step.allocPrintCmd(arena, self.cwd, final_argv), + try Step.allocPrintCmd(arena, cwd, final_argv), }); } }, @@ -908,7 +914,7 @@ fn runCommand( return step.fail("the following command {} (expected {}):\n{s}", .{ fmtTerm(result.term), fmtTerm(expected_term), - try Step.allocPrintCmd(arena, self.cwd, final_argv), + try Step.allocPrintCmd(arena, cwd, final_argv), }); } }, @@ -929,18 +935,18 @@ fn runCommand( prefix, fmtTerm(result.term), fmtTerm(expected_term), - try Step.allocPrintCmd(arena, self.cwd, final_argv), + try Step.allocPrintCmd(arena, cwd, final_argv), }); } if (!result.stdio.test_results.isSuccess()) { return step.fail( "{s}the following test command failed:\n{s}", - .{ prefix, try Step.allocPrintCmd(arena, self.cwd, final_argv) }, + .{ prefix, try Step.allocPrintCmd(arena, cwd, final_argv) }, ); } }, else => { - try step.handleChildProcessTerm(result.term, self.cwd, final_argv); + try step.handleChildProcessTerm(result.term, cwd, final_argv); }, } } @@ -963,8 +969,8 @@ fn spawnChildAndCollect( const arena = b.allocator; var child = std.process.Child.init(argv, arena); - if (self.cwd) |cwd| { - child.cwd = b.pathFromRoot(cwd); + if (self.cwd) |lazy_cwd| { + child.cwd = lazy_cwd.getPath(b); } else { child.cwd = b.build_root.path; child.cwd_dir = b.build_root.handle; diff --git a/test/tests.zig b/test/tests.zig index cc0d8e9b6a..0185f665c9 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -695,7 +695,7 @@ pub fn addCliTests(b: *std.Build) *Step { // Test `zig init-lib`. const tmp_path = b.makeTempPath(); const init_lib = b.addSystemCommand(&.{ b.zig_exe, "init-lib" }); - init_lib.cwd = tmp_path; + init_lib.setCwd(.{ .cwd_relative = tmp_path }); init_lib.setName("zig init-lib"); init_lib.expectStdOutEqual(""); init_lib.expectStdErrEqual("info: Created build.zig\n" ++ @@ -703,7 +703,7 @@ pub fn addCliTests(b: *std.Build) *Step { "info: Next, try `zig build --help` or `zig build test`\n"); const run_test = b.addSystemCommand(&.{ b.zig_exe, "build", "test" }); - run_test.cwd = tmp_path; + run_test.setCwd(.{ .cwd_relative = tmp_path }); run_test.setName("zig build test"); run_test.expectStdOutEqual(""); run_test.step.dependOn(&init_lib.step); @@ -718,7 +718,7 @@ pub fn addCliTests(b: *std.Build) *Step { // Test `zig init-exe`. const tmp_path = b.makeTempPath(); const init_exe = b.addSystemCommand(&.{ b.zig_exe, "init-exe" }); - init_exe.cwd = tmp_path; + init_exe.setCwd(.{ .cwd_relative = tmp_path }); init_exe.setName("zig init-exe"); init_exe.expectStdOutEqual(""); init_exe.expectStdErrEqual("info: Created build.zig\n" ++ @@ -737,13 +737,13 @@ pub fn addCliTests(b: *std.Build) *Step { run_bad.step.dependOn(&init_exe.step); const run_test = b.addSystemCommand(&.{ b.zig_exe, "build", "test" }); - run_test.cwd = tmp_path; + run_test.setCwd(.{ .cwd_relative = tmp_path }); run_test.setName("zig build test"); run_test.expectStdOutEqual(""); run_test.step.dependOn(&init_exe.step); const run_run = b.addSystemCommand(&.{ b.zig_exe, "build", "run" }); - run_run.cwd = tmp_path; + run_run.setCwd(.{ .cwd_relative = tmp_path }); run_run.setName("zig build run"); run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n"); run_run.expectStdErrEqual("All your codebase are belong to us.\n"); @@ -821,7 +821,7 @@ pub fn addCliTests(b: *std.Build) *Step { // Test zig fmt affecting only the appropriate files. const run1 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "fmt1.zig" }); run1.setName("run zig fmt one file"); - run1.cwd = tmp_path; + run1.setCwd(.{ .cwd_relative = tmp_path }); run1.has_side_effects = true; // stdout should be file path + \n run1.expectStdOutEqual("fmt1.zig\n"); @@ -829,7 +829,7 @@ pub fn addCliTests(b: *std.Build) *Step { // Test excluding files and directories from a run const run2 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." }); run2.setName("run zig fmt on directory with exclusions"); - run2.cwd = tmp_path; + run2.setCwd(.{ .cwd_relative = tmp_path }); run2.has_side_effects = true; run2.expectStdOutEqual(""); run2.step.dependOn(&run1.step); @@ -837,7 +837,7 @@ pub fn addCliTests(b: *std.Build) *Step { // Test excluding non-existent file const run3 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." }); run3.setName("run zig fmt on directory with non-existent exclusion"); - run3.cwd = tmp_path; + run3.setCwd(.{ .cwd_relative = tmp_path }); run3.has_side_effects = true; run3.expectStdOutEqual("." ++ s ++ "subdir" ++ s ++ "fmt3.zig\n"); run3.step.dependOn(&run2.step); @@ -845,7 +845,7 @@ pub fn addCliTests(b: *std.Build) *Step { // running it on the dir, only the new file should be changed const run4 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); run4.setName("run zig fmt the directory"); - run4.cwd = tmp_path; + run4.setCwd(.{ .cwd_relative = tmp_path }); run4.has_side_effects = true; run4.expectStdOutEqual("." ++ s ++ "fmt2.zig\n"); run4.step.dependOn(&run3.step); @@ -853,7 +853,7 @@ pub fn addCliTests(b: *std.Build) *Step { // both files have been formatted, nothing should change now const run5 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); run5.setName("run zig fmt with nothing to do"); - run5.cwd = tmp_path; + run5.setCwd(.{ .cwd_relative = tmp_path }); run5.has_side_effects = true; run5.expectStdOutEqual(""); run5.step.dependOn(&run4.step); @@ -867,7 +867,7 @@ pub fn addCliTests(b: *std.Build) *Step { // Test `zig fmt` handling UTF-16 decoding. const run6 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); run6.setName("run zig fmt convert UTF-16 to UTF-8"); - run6.cwd = tmp_path; + run6.setCwd(.{ .cwd_relative = tmp_path }); run6.has_side_effects = true; run6.expectStdOutEqual("." ++ s ++ "fmt6.zig\n"); run6.step.dependOn(&write6.step);