authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-13 12:21:31-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-15 10:48:14-07:00
loga0dd2919eb3b708909275ebdd5b07c5e828e622f
tree4b36472e0c86024bea30bc3074249e29559ea91b
parent61d7e31078fc54010009494d894e2461b41eeee2

std.build.RunStep: clean up some leftover mess

* Remove some functions that are no longer needed since EmulateableRunStep is gone. * Add removeEnvironmentVariable function. * Support printing environment variables in --verbose mode.

2 files changed, 57 insertions(+), 34 deletions(-)

lib/std/Build/RunStep.zig+21-32
...@@ -206,40 +206,30 @@ pub fn clearEnvironment(self: *RunStep) void {...@@ -206,40 +206,30 @@ pub fn clearEnvironment(self: *RunStep) void {
206}206}
207207
208pub fn addPathDir(self: *RunStep, search_path: []const u8) void {208pub fn addPathDir(self: *RunStep, search_path: []const u8) void {
209 addPathDirInternal(&self.step, self.step.owner, search_path);209 const b = self.step.owner;
210}210 const env_map = getEnvMapInternal(self);
211
212/// For internal use only, users of `RunStep` should use `addPathDir` directly.
213pub fn addPathDirInternal(step: *Step, builder: *std.Build, search_path: []const u8) void {
214 const env_map = getEnvMapInternal(step, builder.allocator);
215211
216 const key = "PATH";212 const key = "PATH";
217 var prev_path = env_map.get(key);213 var prev_path = env_map.get(key);
218214
219 if (prev_path) |pp| {215 if (prev_path) |pp| {
220 const new_path = builder.fmt("{s}" ++ [1]u8{fs.path.delimiter} ++ "{s}", .{ pp, search_path });216 const new_path = b.fmt("{s}" ++ [1]u8{fs.path.delimiter} ++ "{s}", .{ pp, search_path });
221 env_map.put(key, new_path) catch @panic("OOM");217 env_map.put(key, new_path) catch @panic("OOM");
222 } else {218 } else {
223 env_map.put(key, builder.dupePath(search_path)) catch @panic("OOM");219 env_map.put(key, b.dupePath(search_path)) catch @panic("OOM");
224 }220 }
225}221}
226222
227pub fn getEnvMap(self: *RunStep) *EnvMap {223pub fn getEnvMap(self: *RunStep) *EnvMap {
228 return getEnvMapInternal(&self.step, self.step.owner.allocator);224 return getEnvMapInternal(self);
229}225}
230226
231fn getEnvMapInternal(step: *Step, allocator: Allocator) *EnvMap {227fn getEnvMapInternal(self: *RunStep) *EnvMap {
232 const maybe_env_map = switch (step.id) {228 const arena = self.step.owner.allocator;
233 .run => step.cast(RunStep).?.env_map,229 return self.env_map orelse {
234 else => unreachable,230 const env_map = arena.create(EnvMap) catch @panic("OOM");
235 };231 env_map.* = process.getEnvMap(arena) catch @panic("unhandled error");
236 return maybe_env_map orelse {232 self.env_map = env_map;
237 const env_map = allocator.create(EnvMap) catch @panic("OOM");
238 env_map.* = process.getEnvMap(allocator) catch @panic("unhandled error");
239 switch (step.id) {
240 .run => step.cast(RunStep).?.env_map = env_map,
241 else => unreachable,
242 }
243 return env_map;233 return env_map;
244 };234 };
245}235}
...@@ -250,6 +240,10 @@ pub fn setEnvironmentVariable(self: *RunStep, key: []const u8, value: []const u8...@@ -250,6 +240,10 @@ pub fn setEnvironmentVariable(self: *RunStep, key: []const u8, value: []const u8
250 env_map.put(b.dupe(key), b.dupe(value)) catch @panic("unhandled error");240 env_map.put(b.dupe(key), b.dupe(value)) catch @panic("unhandled error");
251}241}
252242
243pub fn removeEnvironmentVariable(self: *RunStep, key: []const u8) void {
244 self.getEnvMap().remove(key);
245}
246
253/// Adds a check for exact stderr match. Does not add any other checks.247/// Adds a check for exact stderr match. Does not add any other checks.
254pub fn expectStdErrEqual(self: *RunStep, bytes: []const u8) void {248pub fn expectStdErrEqual(self: *RunStep, bytes: []const u8) void {
255 const new_check: StdIo.Check = .{ .expect_stderr_exact = self.step.owner.dupe(bytes) };249 const new_check: StdIo.Check = .{ .expect_stderr_exact = self.step.owner.dupe(bytes) };
...@@ -553,7 +547,7 @@ fn runCommand(...@@ -553,7 +547,7 @@ fn runCommand(
553 const arena = b.allocator;547 const arena = b.allocator;
554548
555 try step.handleChildProcUnsupported(self.cwd, argv);549 try step.handleChildProcUnsupported(self.cwd, argv);
556 try Step.handleVerbose(step.owner, self.cwd, argv);550 try Step.handleVerbose2(step.owner, self.cwd, self.env_map, argv);
557551
558 const allow_skip = switch (self.stdio) {552 const allow_skip = switch (self.stdio) {
559 .check, .zig_test => self.skip_foreign_checks,553 .check, .zig_test => self.skip_foreign_checks,
...@@ -676,10 +670,10 @@ fn runCommand(...@@ -676,10 +670,10 @@ fn runCommand(
676670
677 if (exe.target.isWindows()) {671 if (exe.target.isWindows()) {
678 // On Windows we don't have rpaths so we have to add .dll search paths to PATH672 // On Windows we don't have rpaths so we have to add .dll search paths to PATH
679 RunStep.addPathForDynLibsInternal(&self.step, b, exe);673 self.addPathForDynLibs(exe);
680 }674 }
681675
682 try Step.handleVerbose(step.owner, self.cwd, interp_argv.items);676 try Step.handleVerbose2(step.owner, self.cwd, self.env_map, interp_argv.items);
683677
684 break :term spawnChildAndCollect(self, interp_argv.items, has_side_effects, prog_node) catch |e| {678 break :term spawnChildAndCollect(self, interp_argv.items, has_side_effects, prog_node) catch |e| {
685 return step.fail("unable to spawn {s}: {s}", .{679 return step.fail("unable to spawn {s}: {s}", .{
...@@ -1177,18 +1171,13 @@ fn evalGeneric(self: *RunStep, child: *std.process.Child) !StdIoResult {...@@ -1177,18 +1171,13 @@ fn evalGeneric(self: *RunStep, child: *std.process.Child) !StdIoResult {
1177}1171}
11781172
1179fn addPathForDynLibs(self: *RunStep, artifact: *CompileStep) void {1173fn addPathForDynLibs(self: *RunStep, artifact: *CompileStep) void {
1180 addPathForDynLibsInternal(&self.step, self.step.owner, artifact);1174 const b = self.step.owner;
1181}
1182
1183/// This should only be used for internal usage, this is called automatically
1184/// for the user.
1185pub fn addPathForDynLibsInternal(step: *Step, builder: *std.Build, artifact: *CompileStep) void {
1186 for (artifact.link_objects.items) |link_object| {1175 for (artifact.link_objects.items) |link_object| {
1187 switch (link_object) {1176 switch (link_object) {
1188 .other_step => |other| {1177 .other_step => |other| {
1189 if (other.target.isWindows() and other.isDynamicLibrary()) {1178 if (other.target.isWindows() and other.isDynamicLibrary()) {
1190 addPathDirInternal(step, builder, fs.path.dirname(other.getOutputSource().getPath(builder)).?);1179 addPathDir(self, fs.path.dirname(other.getOutputSource().getPath(b)).?);
1191 addPathForDynLibsInternal(step, builder, other);1180 addPathForDynLibs(self, other);
1192 }1181 }
1193 },1182 },
1194 else => {},1183 else => {},
lib/std/Build/Step.zig+36-2
...@@ -427,11 +427,20 @@ pub fn handleVerbose(...@@ -427,11 +427,20 @@ pub fn handleVerbose(
427 b: *Build,427 b: *Build,
428 opt_cwd: ?[]const u8,428 opt_cwd: ?[]const u8,
429 argv: []const []const u8,429 argv: []const []const u8,
430) error{OutOfMemory}!void {
431 return handleVerbose2(b, opt_cwd, null, argv);
432}
433
434pub fn handleVerbose2(
435 b: *Build,
436 opt_cwd: ?[]const u8,
437 opt_env: ?*const std.process.EnvMap,
438 argv: []const []const u8,
430) error{OutOfMemory}!void {439) error{OutOfMemory}!void {
431 if (b.verbose) {440 if (b.verbose) {
432 // Intention of verbose is to print all sub-process command lines to441 // Intention of verbose is to print all sub-process command lines to
433 // stderr before spawning them.442 // stderr before spawning them.
434 const text = try allocPrintCmd(b.allocator, opt_cwd, argv);443 const text = try allocPrintCmd2(b.allocator, opt_cwd, opt_env, argv);
435 std.debug.print("{s}\n", .{text});444 std.debug.print("{s}\n", .{text});
436 }445 }
437}446}
...@@ -474,9 +483,34 @@ pub fn handleChildProcessTerm(...@@ -474,9 +483,34 @@ pub fn handleChildProcessTerm(
474 }483 }
475}484}
476485
477pub fn allocPrintCmd(arena: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) ![]u8 {486pub fn allocPrintCmd(
487 arena: Allocator,
488 opt_cwd: ?[]const u8,
489 argv: []const []const u8,
490) ![]u8 {
491 return allocPrintCmd2(arena, opt_cwd, null, argv);
492}
493
494pub fn allocPrintCmd2(
495 arena: Allocator,
496 opt_cwd: ?[]const u8,
497 opt_env: ?*const std.process.EnvMap,
498 argv: []const []const u8,
499) ![]u8 {
478 var buf: std.ArrayListUnmanaged(u8) = .{};500 var buf: std.ArrayListUnmanaged(u8) = .{};
479 if (opt_cwd) |cwd| try buf.writer(arena).print("cd {s} && ", .{cwd});501 if (opt_cwd) |cwd| try buf.writer(arena).print("cd {s} && ", .{cwd});
502 if (opt_env) |env| {
503 const process_env_map = try std.process.getEnvMap(arena);
504 var it = env.iterator();
505 while (it.next()) |entry| {
506 const key = entry.key_ptr.*;
507 const value = entry.value_ptr.*;
508 if (process_env_map.get(key)) |process_value| {
509 if (std.mem.eql(u8, value, process_value)) continue;
510 }
511 try buf.writer(arena).print("{s}={s} ", .{ key, value });
512 }
513 }
480 for (argv) |arg| {514 for (argv) |arg| {
481 try buf.writer(arena).print("{s} ", .{arg});515 try buf.writer(arena).print("{s} ", .{arg});
482 }516 }