mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
update main function to accept args and environ
Now `main` takes an `init: std.Init` parameter, and this is the only way to access command line arguments and environment variables. After a deprecation period, this will close #4524
This commit is contained in:
parent
8a3aebaee0
commit
85e8cc8abc
@ -41,14 +41,14 @@ test {
|
||||
_ = windows;
|
||||
}
|
||||
|
||||
/// See also `getenv`. Populated by startup code before main().
|
||||
/// TODO this is a footgun because the value will be undefined when using `zig build-lib`.
|
||||
/// https://github.com/ziglang/zig/issues/4524
|
||||
/// Deprecated in favor of accepting a `std.process.Init` argument to main.
|
||||
/// To be removed after 0.14.0 is tagged.
|
||||
/// See https://github.com/ziglang/zig/issues/4524 for more details.
|
||||
pub var environ: [][*:0]u8 = undefined;
|
||||
|
||||
/// Populated by startup code before main().
|
||||
/// Not available on WASI or Windows without libc. See `std.process.argsAlloc`
|
||||
/// or `std.process.argsWithAllocator` for a cross-platform alternative.
|
||||
/// Deprecated in favor of accepting a `std.process.Init` argument to main.
|
||||
/// To be removed after 0.14.0 is tagged.
|
||||
/// See https://github.com/ziglang/zig/issues/4524 for more details.
|
||||
pub var argv: [][*:0]u8 = if (builtin.link_libc) undefined else switch (native_os) {
|
||||
.windows => @compileError("argv isn't supported on Windows: use std.process.argsAlloc instead"),
|
||||
.wasi => @compileError("argv isn't supported on WASI: use std.process.argsAlloc instead"),
|
||||
|
||||
1086
lib/std/process.zig
1086
lib/std/process.zig
File diff suppressed because it is too large
Load Diff
@ -185,17 +185,13 @@ fn _DllMainCRTStartup(
|
||||
}
|
||||
|
||||
fn wasm_freestanding_start() callconv(.c) void {
|
||||
// This is marked inline because for some reason LLVM in
|
||||
// release mode fails to inline it, and we want fewer call frames in stack traces.
|
||||
_ = @call(.always_inline, callMain, .{});
|
||||
_ = callMain(.void);
|
||||
}
|
||||
|
||||
fn wasi_start() callconv(.c) void {
|
||||
// The function call is marked inline because for some reason LLVM in
|
||||
// release mode fails to inline it, and we want fewer call frames in stack traces.
|
||||
switch (builtin.wasi_exec_model) {
|
||||
.reactor => _ = @call(.always_inline, callMain, .{}),
|
||||
.command => std.os.wasi.proc_exit(@call(.always_inline, callMain, .{})),
|
||||
.reactor => _ = callMain(.void),
|
||||
.command => std.os.wasi.proc_exit(callMain(.void)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -472,7 +468,7 @@ fn WinStartup() callconv(.withStackAlign(.c, 1)) noreturn {
|
||||
|
||||
std.debug.maybeEnableSegfaultHandler();
|
||||
|
||||
std.os.windows.ntdll.RtlExitUserProcess(callMain());
|
||||
std.os.windows.ntdll.RtlExitUserProcess(callMain(.void));
|
||||
}
|
||||
|
||||
fn wWinMainCRTStartup() callconv(.withStackAlign(.c, 1)) noreturn {
|
||||
@ -499,7 +495,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
|
||||
while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
|
||||
const envp = @as([*][*:0]u8, @ptrCast(envp_optional))[0..envp_count];
|
||||
|
||||
if (native_os == .linux) {
|
||||
const aux: std.process.Init.Aux = if (native_os == .linux) aux: {
|
||||
// Find the beginning of the auxiliary vector
|
||||
const auxv: [*]elf.Auxv = @ptrCast(@alignCast(envp.ptr + envp_count + 1));
|
||||
|
||||
@ -566,9 +562,11 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
|
||||
const slice = init_array_start[0 .. init_array_end - init_array_start];
|
||||
for (slice) |func| func();
|
||||
}
|
||||
}
|
||||
|
||||
std.posix.exit(callMainWithArgs(argc, argv, envp));
|
||||
break :aux .{ .data = auxv };
|
||||
} else .{ .data = {} };
|
||||
|
||||
std.posix.exit(callMainWithArgs(argc, argv, envp, aux));
|
||||
}
|
||||
|
||||
fn expandStackSize(phdrs: []elf.Phdr) void {
|
||||
@ -606,14 +604,18 @@ fn expandStackSize(phdrs: []elf.Phdr) void {
|
||||
}
|
||||
}
|
||||
|
||||
inline fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
|
||||
std.os.argv = argv[0..argc];
|
||||
std.os.environ = envp;
|
||||
inline fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8, aux: std.process.Init.Aux) u8 {
|
||||
std.os.argv = argv[0..argc]; // To be removed after 0.15.0 is tagged.
|
||||
std.os.environ = envp; // To be removed after 0.15.0 is tagged.
|
||||
|
||||
std.debug.maybeEnableSegfaultHandler();
|
||||
maybeIgnoreSigpipe();
|
||||
|
||||
return callMain();
|
||||
return callMain(.{
|
||||
.args = .{ .data = if (builtin.os.tag == .windows) {} else argv[0..argc] },
|
||||
.env = .{ .data = if (builtin.os.tag == .windows) {} else envp },
|
||||
.aux = aux,
|
||||
});
|
||||
}
|
||||
|
||||
fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) callconv(.c) c_int {
|
||||
@ -628,21 +630,28 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal
|
||||
expandStackSize(phdrs);
|
||||
}
|
||||
|
||||
return callMainWithArgs(@as(usize, @intCast(c_argc)), @as([*][*:0]u8, @ptrCast(c_argv)), envp);
|
||||
return callMainWithArgs(@intCast(c_argc), @ptrCast(c_argv), envp, .{ .data = {} });
|
||||
}
|
||||
|
||||
fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int {
|
||||
std.os.argv = @as([*][*:0]u8, @ptrCast(c_argv))[0..@as(usize, @intCast(c_argc))];
|
||||
return callMain();
|
||||
const args = @as([*][*:0]u8, @ptrCast(c_argv))[0..@as(usize, @intCast(c_argc))];
|
||||
std.os.argv = args; // To be removed after 0.15.0 is tagged.
|
||||
return callMain(.{
|
||||
.args = .{ .data = args },
|
||||
.env = .{ .data = {} },
|
||||
.aux = .{ .data = {} },
|
||||
});
|
||||
}
|
||||
|
||||
// General error message for a malformed return type
|
||||
const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";
|
||||
|
||||
pub inline fn callMain() u8 {
|
||||
const ReturnType = @typeInfo(@TypeOf(root.main)).@"fn".return_type.?;
|
||||
pub inline fn callMain(init: std.process.Init) u8 {
|
||||
const func = @typeInfo(@TypeOf(root.main)).@"fn";
|
||||
const ReturnType = func.return_type.?;
|
||||
|
||||
switch (ReturnType) {
|
||||
// To be deleted after 0.15.0 is tagged.
|
||||
if (func.params.len == 0) switch (ReturnType) {
|
||||
void => {
|
||||
root.main();
|
||||
return 0;
|
||||
@ -665,6 +674,37 @@ pub inline fn callMain() u8 {
|
||||
return 1;
|
||||
};
|
||||
|
||||
return switch (@TypeOf(result)) {
|
||||
void => 0,
|
||||
u8 => result,
|
||||
else => @compileError(bad_main_ret),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
switch (ReturnType) {
|
||||
void => {
|
||||
root.main(init);
|
||||
return 0;
|
||||
},
|
||||
noreturn, u8 => {
|
||||
return root.main(init);
|
||||
},
|
||||
else => {
|
||||
if (@typeInfo(ReturnType) != .error_union) @compileError(bad_main_ret);
|
||||
|
||||
const result = root.main(init) catch |err| {
|
||||
if (builtin.zig_backend == .stage2_riscv64) {
|
||||
std.debug.print("error: failed with error\n", .{});
|
||||
return 1;
|
||||
}
|
||||
std.log.err("{s}", .{@errorName(err)});
|
||||
if (@errorReturnTrace()) |trace| {
|
||||
std.debug.dumpStackTrace(trace.*);
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
return switch (@TypeOf(result)) {
|
||||
void => 0,
|
||||
u8 => result,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user