I would like to query if an environment variable is present or not. In 0.15.2, I could do this:
const is_release: bool = if (std.process.getEnvVarOwned(allocator, "GATORCAT_RELEASE")) |_| true else |_| false;
How do I do this in 0.16?
I would like to query if an environment variable is present or not. In 0.15.2, I could do this:
const is_release: bool = if (std.process.getEnvVarOwned(allocator, "GATORCAT_RELEASE")) |_| true else |_| false;
How do I do this in 0.16?
init.environ_map.contains("GATORCAT_RELEASE")
Since #30644 the environment is not stored in a global variable.
There’s also std.process.Environ.contains if you’re using std.process.Init.Minimal:
pub fn main(init: std.process.Init.Minimal) !void {
// set up allocator
const is_release = try init.environ.contains(allocator, "GATORCAT_RELEASE");
}
If you don’t care about WASI support there’s also std.process.Environ.containsConstant which doesn’t require an allocator (the equivalent in 0.15.2 was std.process.hasEnvVarConstant).
Just to clarify, Environ is the raw unprocessed data from the OS, EnvironMap is the that data processed into an array hash map.
It is odd that Environ has contains* functions, as it doesn’t have any other counterpart to the EnvironMap API.
The Environ.contains* functions just create an EnvironMap each time, which is to say they process all the data each time.
with exception to
containsConstant, which uses thegetPosix/Windowsfunctions that go through the unprocessed data.
If you need it more than once use createMap to get an EnvironMap once and query that instead.
The environ / process args APIs are very frustrating because its hard to tell from reading the code how I am supposed to initialize them. I know it goes back to the OS, because the OS initializes them somewhere in memory for me, but its still frustrating. I wish it was a syscall instead, it would make more sense that way to me.
My normal workflow:
contains function that does what I want: Zig DocumentationEnviron as first argument, ok cool lets go look at Environ…Environ has no init function, and its not clear at all how the hell I am supposed to create itSame story for std.process.Args. Very annoying.
Think about it like this, because this is literally what it is, environment and args are passed to the entry point function, not as arguments but through specific registers since this behaviour predates standard ABIs.
What libc does, and zig used to do, is put them in global vars to be accessed easily, but that has foot guns and allows hidden control flow.
So now zig just passes them to main via std.process.Init[.Minimal]
How the environment (and command-line arguments) is passed to a process is platform-dependent, and not how you describe for some operating systems.
Yes I should have clarified.
I described how it is done on POSIX.
Windows includes environment in a bunch of information available globally to the process.