Description
Zig Version
0.14.0
Steps to Reproduce and Observed Behavior
Given example.zig
:
const std = @import("std");
export fn check_call() void {
const allocator = std.heap.page_allocator;
const output = collect_output(
allocator,
&.{"bash", "-c", "echo $Slartibartfast"},
) catch "Failure!";
defer allocator.free(output);
std.debug.print("{s}", .{output});
}
pub fn collect_output(allocator: std.mem.Allocator, argv: []const []const u8) ![]const u8 {
var env_map = std.process.EnvMap.init(allocator);
defer env_map.deinit();
try env_map.put("Slartibartfast", "fjords");
const result = try std.process.Child.run(
.{ .allocator = allocator, .argv = argv, .env_map = &env_map },
);
errdefer allocator.free(result.stdout);
allocator.free(result.stderr);
switch (result.term) {
.Exited => |code| {
if (code == 0) {
return result.stdout;
} else {
return error.NonZeroExit;
}
},
else => return error.Failure,
}
}
Try:
# Ok:
:; zig build-lib -dynamic -target x86_64-windows example.zig
# Ok:
:; zig build-lib -dynamic -target x86_64-macos example.zig
# Not ok:
:; zig build-lib -dynamic -target x86_64-linux example.zig
/home/jsirois/.local/opt/zig-linux-x86_64-0.14.0/lib/std/process/Child.zig:605:13: error: missing std lib enhancement: ChildProcess implementation has no way to collect the environment variables to forward to the child process
@compileError("missing std lib enhancement: ChildProcess implementation has no way to collect the environment variables to forward to the child process");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
referenced by:
spawn: /home/jsirois/.local/opt/zig-linux-x86_64-0.14.0/lib/std/process/Child.zig:247:31
run: /home/jsirois/.local/opt/zig-linux-x86_64-0.14.0/lib/std/process/Child.zig:425:20
7 reference(s) hidden; use '-freference-trace=9' to see all references
Expected Behavior
See https://github.com/ziglang/zig/pull/7553/files#r2014522673 where the originating issue is identified in a 2020 change. The same code exists today though:
Lines 591 to 611 in b4b1daf
It seems like the compile error is too aggressive, disallowing legitimate use of the Child API by passing in a hand crafted env_map
. Presumably the else branch could even optimistically use std.os.environ
since it can be set by things other than the zig start code used for exes. In my case, I actually do this! I naively tried passing in env_map though to work around, and then realized what I thought was a compiler bug handling mixed comptime-known / runtime-known if / else branches was actually correct compiler behavior - this just appeared to be an API decision. I'm hoping that decision can be changed to make this API more widely usable.
I'm happy to take this issue up if the idea of populating env from std.os.environ
sounds reasonable. Perhaps paired with stdlib docs updates to point out the caveats. I guess this would require an API for setting std.os.environ since its status is currently inherently ambiguous via undefined instead of optional. Maybe a paired bool flag to indicate it was populated by startup code? Or, if breaking existing users is OK, maybe just switch to an optional since std.os.environ truly is optional.