mirror of
https://github.com/ziglang/zig.git
synced 2025-12-16 03:03:09 +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;
|
_ = windows;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See also `getenv`. Populated by startup code before main().
|
/// Deprecated in favor of accepting a `std.process.Init` argument to main.
|
||||||
/// TODO this is a footgun because the value will be undefined when using `zig build-lib`.
|
/// To be removed after 0.14.0 is tagged.
|
||||||
/// https://github.com/ziglang/zig/issues/4524
|
/// See https://github.com/ziglang/zig/issues/4524 for more details.
|
||||||
pub var environ: [][*:0]u8 = undefined;
|
pub var environ: [][*:0]u8 = undefined;
|
||||||
|
|
||||||
/// Populated by startup code before main().
|
/// Deprecated in favor of accepting a `std.process.Init` argument to main.
|
||||||
/// Not available on WASI or Windows without libc. See `std.process.argsAlloc`
|
/// To be removed after 0.14.0 is tagged.
|
||||||
/// or `std.process.argsWithAllocator` for a cross-platform alternative.
|
/// 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) {
|
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"),
|
.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"),
|
.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 {
|
fn wasm_freestanding_start() callconv(.c) void {
|
||||||
// This is marked inline because for some reason LLVM in
|
_ = callMain(.void);
|
||||||
// release mode fails to inline it, and we want fewer call frames in stack traces.
|
|
||||||
_ = @call(.always_inline, callMain, .{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wasi_start() callconv(.c) 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) {
|
switch (builtin.wasi_exec_model) {
|
||||||
.reactor => _ = @call(.always_inline, callMain, .{}),
|
.reactor => _ = callMain(.void),
|
||||||
.command => std.os.wasi.proc_exit(@call(.always_inline, callMain, .{})),
|
.command => std.os.wasi.proc_exit(callMain(.void)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,7 +468,7 @@ fn WinStartup() callconv(.withStackAlign(.c, 1)) noreturn {
|
|||||||
|
|
||||||
std.debug.maybeEnableSegfaultHandler();
|
std.debug.maybeEnableSegfaultHandler();
|
||||||
|
|
||||||
std.os.windows.ntdll.RtlExitUserProcess(callMain());
|
std.os.windows.ntdll.RtlExitUserProcess(callMain(.void));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wWinMainCRTStartup() callconv(.withStackAlign(.c, 1)) noreturn {
|
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) {}
|
while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
|
||||||
const envp = @as([*][*:0]u8, @ptrCast(envp_optional))[0..envp_count];
|
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
|
// Find the beginning of the auxiliary vector
|
||||||
const auxv: [*]elf.Auxv = @ptrCast(@alignCast(envp.ptr + envp_count + 1));
|
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];
|
const slice = init_array_start[0 .. init_array_end - init_array_start];
|
||||||
for (slice) |func| func();
|
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 {
|
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 {
|
inline fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8, aux: std.process.Init.Aux) u8 {
|
||||||
std.os.argv = argv[0..argc];
|
std.os.argv = argv[0..argc]; // To be removed after 0.15.0 is tagged.
|
||||||
std.os.environ = envp;
|
std.os.environ = envp; // To be removed after 0.15.0 is tagged.
|
||||||
|
|
||||||
std.debug.maybeEnableSegfaultHandler();
|
std.debug.maybeEnableSegfaultHandler();
|
||||||
maybeIgnoreSigpipe();
|
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 {
|
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);
|
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 {
|
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))];
|
const args = @as([*][*:0]u8, @ptrCast(c_argv))[0..@as(usize, @intCast(c_argc))];
|
||||||
return callMain();
|
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
|
// 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'";
|
const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";
|
||||||
|
|
||||||
pub inline fn callMain() u8 {
|
pub inline fn callMain(init: std.process.Init) u8 {
|
||||||
const ReturnType = @typeInfo(@TypeOf(root.main)).@"fn".return_type.?;
|
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 => {
|
void => {
|
||||||
root.main();
|
root.main();
|
||||||
return 0;
|
return 0;
|
||||||
@ -665,6 +674,37 @@ pub inline fn callMain() u8 {
|
|||||||
return 1;
|
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)) {
|
return switch (@TypeOf(result)) {
|
||||||
void => 0,
|
void => 0,
|
||||||
u8 => result,
|
u8 => result,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user