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 {
206206}
207207
208208pub fn addPathDir(self: *RunStep, search_path: []const u8) void {
209 addPathDirInternal(&self.step, self.step.owner, search_path);
210}
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);
209 const b = self.step.owner;
210 const env_map = getEnvMapInternal(self);
215211
216212 const key = "PATH";
217213 var prev_path = env_map.get(key);
218214
219215 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 });
221217 env_map.put(key, new_path) catch @panic("OOM");
222218 } 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");
224220 }
225221}
226222
227223pub fn getEnvMap(self: *RunStep) *EnvMap {
228 return getEnvMapInternal(&self.step, self.step.owner.allocator);
224 return getEnvMapInternal(self);
229225}
230226
231fn getEnvMapInternal(step: *Step, allocator: Allocator) *EnvMap {
232 const maybe_env_map = switch (step.id) {
233 .run => step.cast(RunStep).?.env_map,
234 else => unreachable,
235 };
236 return maybe_env_map orelse {
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 }
227fn getEnvMapInternal(self: *RunStep) *EnvMap {
228 const arena = self.step.owner.allocator;
229 return self.env_map orelse {
230 const env_map = arena.create(EnvMap) catch @panic("OOM");
231 env_map.* = process.getEnvMap(arena) catch @panic("unhandled error");
232 self.env_map = env_map;
243233 return env_map;
244234 };
245235}
......@@ -250,6 +240,10 @@ pub fn setEnvironmentVariable(self: *RunStep, key: []const u8, value: []const u8
250240 env_map.put(b.dupe(key), b.dupe(value)) catch @panic("unhandled error");
251241}
252242
243pub fn removeEnvironmentVariable(self: *RunStep, key: []const u8) void {
244 self.getEnvMap().remove(key);
245}
246
253247/// Adds a check for exact stderr match. Does not add any other checks.
254248pub fn expectStdErrEqual(self: *RunStep, bytes: []const u8) void {
255249 const new_check: StdIo.Check = .{ .expect_stderr_exact = self.step.owner.dupe(bytes) };
......@@ -553,7 +547,7 @@ fn runCommand(
553547 const arena = b.allocator;
554548
555549 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
558552 const allow_skip = switch (self.stdio) {
559553 .check, .zig_test => self.skip_foreign_checks,
......@@ -676,10 +670,10 @@ fn runCommand(
676670
677671 if (exe.target.isWindows()) {
678672 // 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);
680674 }
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
684678 break :term spawnChildAndCollect(self, interp_argv.items, has_side_effects, prog_node) catch |e| {
685679 return step.fail("unable to spawn {s}: {s}", .{
......@@ -1177,18 +1171,13 @@ fn evalGeneric(self: *RunStep, child: *std.process.Child) !StdIoResult {
11771171}
11781172
11791173fn addPathForDynLibs(self: *RunStep, artifact: *CompileStep) void {
1180 addPathForDynLibsInternal(&self.step, self.step.owner, artifact);
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 {
1174 const b = self.step.owner;
11861175 for (artifact.link_objects.items) |link_object| {
11871176 switch (link_object) {
11881177 .other_step => |other| {
11891178 if (other.target.isWindows() and other.isDynamicLibrary()) {
1190 addPathDirInternal(step, builder, fs.path.dirname(other.getOutputSource().getPath(builder)).?);
1191 addPathForDynLibsInternal(step, builder, other);
1179 addPathDir(self, fs.path.dirname(other.getOutputSource().getPath(b)).?);
1180 addPathForDynLibs(self, other);
11921181 }
11931182 },
11941183 else => {},
lib/std/Build/Step.zig+36-2
......@@ -427,11 +427,20 @@ pub fn handleVerbose(
427427 b: *Build,
428428 opt_cwd: ?[]const u8,
429429 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,
430439) error{OutOfMemory}!void {
431440 if (b.verbose) {
432441 // Intention of verbose is to print all sub-process command lines to
433442 // 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);
435444 std.debug.print("{s}\n", .{text});
436445 }
437446}
......@@ -474,9 +483,34 @@ pub fn handleChildProcessTerm(
474483 }
475484}
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 {
478500 var buf: std.ArrayListUnmanaged(u8) = .{};
479501 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 }
480514 for (argv) |arg| {
481515 try buf.writer(arena).print("{s} ", .{arg});
482516 }