mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-07 22:34:28 +00:00
std: collect all options under one namespace
This commit is contained in:
parent
fe2bd9dda8
commit
f83834993e
17 changed files with 164 additions and 97 deletions
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const root = @import("root");
|
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const os = std.os;
|
const os = std.os;
|
||||||
|
|
||||||
|
|
@ -67,8 +66,8 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void {
|
||||||
// Allow applications to decide they would prefer to have every call to
|
// Allow applications to decide they would prefer to have every call to
|
||||||
// std.crypto.random always make an OS syscall, rather than rely on an
|
// std.crypto.random always make an OS syscall, rather than rely on an
|
||||||
// application implementation of a CSPRNG.
|
// application implementation of a CSPRNG.
|
||||||
if (comptime std.meta.globalOption("crypto_always_getrandom", bool) orelse false) {
|
if (std.options.crypto_always_getrandom) {
|
||||||
return fillWithOsEntropy(buffer);
|
return defaultRandomSeed(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wipe_mem.len == 0) {
|
if (wipe_mem.len == 0) {
|
||||||
|
|
@ -86,7 +85,7 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void {
|
||||||
) catch {
|
) catch {
|
||||||
// Could not allocate memory for the local state, fall back to
|
// Could not allocate memory for the local state, fall back to
|
||||||
// the OS syscall.
|
// the OS syscall.
|
||||||
return fillWithOsEntropy(buffer);
|
return std.options.cryptoRandomSeed(buffer);
|
||||||
};
|
};
|
||||||
// The memory is already zero-initialized.
|
// The memory is already zero-initialized.
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -128,14 +127,14 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void {
|
||||||
// Since we failed to set up fork safety, we fall back to always
|
// Since we failed to set up fork safety, we fall back to always
|
||||||
// calling getrandom every time.
|
// calling getrandom every time.
|
||||||
ctx.init_state = .failed;
|
ctx.init_state = .failed;
|
||||||
return fillWithOsEntropy(buffer);
|
return std.options.cryptoRandomSeed(buffer);
|
||||||
},
|
},
|
||||||
.initialized => {
|
.initialized => {
|
||||||
return fillWithCsprng(buffer);
|
return fillWithCsprng(buffer);
|
||||||
},
|
},
|
||||||
.failed => {
|
.failed => {
|
||||||
if (want_fork_safety) {
|
if (want_fork_safety) {
|
||||||
return fillWithOsEntropy(buffer);
|
return std.options.cryptoRandomSeed(buffer);
|
||||||
} else {
|
} else {
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
@ -165,7 +164,7 @@ fn fillWithCsprng(buffer: []u8) void {
|
||||||
mem.set(u8, ctx.gimli.toSlice()[0..std.crypto.core.Gimli.RATE], 0);
|
mem.set(u8, ctx.gimli.toSlice()[0..std.crypto.core.Gimli.RATE], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fillWithOsEntropy(buffer: []u8) void {
|
pub fn defaultRandomSeed(buffer: []u8) void {
|
||||||
os.getrandom(buffer) catch @panic("getrandom() failed to provide entropy");
|
os.getrandom(buffer) catch @panic("getrandom() failed to provide entropy");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,12 +173,8 @@ fn initAndFill(buffer: []u8) void {
|
||||||
// Because we panic on getrandom() failing, we provide the opportunity
|
// Because we panic on getrandom() failing, we provide the opportunity
|
||||||
// to override the default seed function. This also makes
|
// to override the default seed function. This also makes
|
||||||
// `std.crypto.random` available on freestanding targets, provided that
|
// `std.crypto.random` available on freestanding targets, provided that
|
||||||
// the `cryptoRandomSeed` function is provided.
|
// the `std.options.cryptoRandomSeed` function is provided.
|
||||||
if (@hasDecl(root, "cryptoRandomSeed")) {
|
std.options.cryptoRandomSeed(&seed);
|
||||||
root.cryptoRandomSeed(&seed);
|
|
||||||
} else {
|
|
||||||
fillWithOsEntropy(&seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ctx = @ptrCast(*Context, wipe_mem.ptr);
|
const ctx = @ptrCast(*Context, wipe_mem.ptr);
|
||||||
ctx.gimli = std.crypto.core.Gimli.init(seed);
|
ctx.gimli = std.crypto.core.Gimli.init(seed);
|
||||||
|
|
|
||||||
|
|
@ -1861,10 +1861,9 @@ pub const have_segfault_handling_support = switch (native_os) {
|
||||||
.freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"),
|
.freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"),
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
|
|
||||||
root.enable_segfault_handler
|
const enable_segfault_handler = std.options.enable_segfault_handler;
|
||||||
else
|
pub const default_enable_segfault_handler = runtime_safety and have_segfault_handling_support;
|
||||||
runtime_safety and have_segfault_handling_support;
|
|
||||||
|
|
||||||
pub fn maybeEnableSegfaultHandler() void {
|
pub fn maybeEnableSegfaultHandler() void {
|
||||||
if (enable_segfault_handler) {
|
if (enable_segfault_handler) {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ pub fn Batch(
|
||||||
comptime async_behavior: enum {
|
comptime async_behavior: enum {
|
||||||
/// Observe the value of `std.io.is_async` to decide whether `add`
|
/// Observe the value of `std.io.is_async` to decide whether `add`
|
||||||
/// and `wait` will be async functions. Asserts that the jobs do not suspend when
|
/// and `wait` will be async functions. Asserts that the jobs do not suspend when
|
||||||
/// `std.io.mode == .blocking`. This is a generally safe assumption, and the
|
/// `std.options.io_mode == .blocking`. This is a generally safe assumption, and the
|
||||||
/// usual recommended option for this parameter.
|
/// usual recommended option for this parameter.
|
||||||
auto_async,
|
auto_async,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
const std = @import("../std.zig");
|
const std = @import("../std.zig");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const root = @import("root");
|
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
|
|
@ -104,25 +103,29 @@ pub const Loop = struct {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const LoopOrVoid = switch (std.io.mode) {
|
pub const Instance = switch (std.options.io_mode) {
|
||||||
.blocking => void,
|
.blocking => @TypeOf(null),
|
||||||
.evented => Loop,
|
.evented => ?*Loop,
|
||||||
};
|
};
|
||||||
|
pub const instance = std.options.event_loop;
|
||||||
|
|
||||||
var global_instance_state: LoopOrVoid = undefined;
|
var global_instance_state: Loop = undefined;
|
||||||
const default_instance: ?*LoopOrVoid = switch (std.io.mode) {
|
pub const default_instance = switch (std.options.io_mode) {
|
||||||
.blocking => null,
|
.blocking => null,
|
||||||
.evented => &global_instance_state,
|
.evented => &global_instance_state,
|
||||||
};
|
};
|
||||||
pub const instance: ?*LoopOrVoid = if (@hasDecl(root, "event_loop")) root.event_loop else default_instance;
|
|
||||||
|
pub const Mode = enum {
|
||||||
|
single_threaded,
|
||||||
|
multi_threaded,
|
||||||
|
};
|
||||||
|
pub const default_mode = .multi_threaded;
|
||||||
|
|
||||||
/// TODO copy elision / named return values so that the threads referencing *Loop
|
/// TODO copy elision / named return values so that the threads referencing *Loop
|
||||||
/// have the correct pointer value.
|
/// have the correct pointer value.
|
||||||
/// https://github.com/ziglang/zig/issues/2761 and https://github.com/ziglang/zig/issues/2765
|
/// https://github.com/ziglang/zig/issues/2761 and https://github.com/ziglang/zig/issues/2765
|
||||||
pub fn init(self: *Loop) !void {
|
pub fn init(self: *Loop) !void {
|
||||||
if (builtin.single_threaded or
|
if (builtin.single_threaded or std.options.event_loop_mode == .single_threaded) {
|
||||||
(@hasDecl(root, "event_loop_mode") and root.event_loop_mode == .single_threaded))
|
|
||||||
{
|
|
||||||
return self.initSingleThreaded();
|
return self.initSingleThreaded();
|
||||||
} else {
|
} else {
|
||||||
return self.initMultiThreaded();
|
return self.initMultiThreaded();
|
||||||
|
|
|
||||||
|
|
@ -2661,17 +2661,17 @@ pub fn cwd() Dir {
|
||||||
if (builtin.os.tag == .windows) {
|
if (builtin.os.tag == .windows) {
|
||||||
return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };
|
return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };
|
||||||
} else if (builtin.os.tag == .wasi) {
|
} else if (builtin.os.tag == .wasi) {
|
||||||
if (@hasDecl(root, "wasi_cwd")) {
|
return std.options.wasiCwd();
|
||||||
return root.wasi_cwd();
|
|
||||||
} else {
|
|
||||||
// Expect the first preopen to be current working directory.
|
|
||||||
return .{ .fd = 3 };
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return Dir{ .fd = os.AT.FDCWD };
|
return Dir{ .fd = os.AT.FDCWD };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn defaultWasiCwd() Dir {
|
||||||
|
// Expect the first preopen to be current working directory.
|
||||||
|
return .{ .fd = 3 };
|
||||||
|
}
|
||||||
|
|
||||||
/// Opens a directory at the given path. The directory is a system resource that remains
|
/// Opens a directory at the given path. The directory is a system resource that remains
|
||||||
/// open until `close` is called on the result.
|
/// open until `close` is called on the result.
|
||||||
/// See `openDirAbsoluteZ` for a function that accepts a null-terminated path.
|
/// See `openDirAbsoluteZ` for a function that accepts a null-terminated path.
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ pub const File = struct {
|
||||||
/// blocking.
|
/// blocking.
|
||||||
capable_io_mode: io.ModeOverride = io.default_mode,
|
capable_io_mode: io.ModeOverride = io.default_mode,
|
||||||
|
|
||||||
/// Furthermore, even when `std.io.mode` is async, it is still sometimes desirable
|
/// Furthermore, even when `std.options.io_mode` is async, it is still sometimes desirable
|
||||||
/// to perform blocking I/O, although not by default. For example, when printing a
|
/// to perform blocking I/O, although not by default. For example, when printing a
|
||||||
/// stack trace to stderr. This field tracks both by acting as an overriding I/O mode.
|
/// stack trace to stderr. This field tracks both by acting as an overriding I/O mode.
|
||||||
/// When not building in async I/O mode, the type only has the `.blocking` tag, making
|
/// When not building in async I/O mode, the type only has the `.blocking` tag, making
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,7 @@ pub const Mode = enum {
|
||||||
evented,
|
evented,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The application's chosen I/O mode. This defaults to `Mode.blocking` but can be overridden
|
const mode = std.options.io_mode;
|
||||||
/// by `root.event_loop`.
|
|
||||||
pub const mode: Mode = if (@hasDecl(root, "io_mode"))
|
|
||||||
root.io_mode
|
|
||||||
else if (@hasDecl(root, "event_loop"))
|
|
||||||
Mode.evented
|
|
||||||
else
|
|
||||||
Mode.blocking;
|
|
||||||
pub const is_async = mode != .blocking;
|
pub const is_async = mode != .blocking;
|
||||||
|
|
||||||
/// This is an enum value to use for I/O mode at runtime, since it takes up zero bytes at runtime,
|
/// This is an enum value to use for I/O mode at runtime, since it takes up zero bytes at runtime,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! std.log is a standardized interface for logging which allows for the logging
|
//! std.log is a standardized interface for logging which allows for the logging
|
||||||
//! of programs and libraries using this interface to be formatted and filtered
|
//! of programs and libraries using this interface to be formatted and filtered
|
||||||
//! by the implementer of the root.log function.
|
//! by the implementer of the `std.options.logFn` function.
|
||||||
//!
|
//!
|
||||||
//! Each log message has an associated scope enum, which can be used to give
|
//! Each log message has an associated scope enum, which can be used to give
|
||||||
//! context to the logging. The logging functions in std.log implicitly use a
|
//! context to the logging. The logging functions in std.log implicitly use a
|
||||||
|
|
@ -13,16 +13,20 @@
|
||||||
//! `const log = std.log.scoped(.libfoo);` to use .libfoo as the scope of its
|
//! `const log = std.log.scoped(.libfoo);` to use .libfoo as the scope of its
|
||||||
//! log messages.
|
//! log messages.
|
||||||
//!
|
//!
|
||||||
//! An example root.log might look something like this:
|
//! An example `logFn` might look something like this:
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! const std = @import("std");
|
//! const std = @import("std");
|
||||||
//!
|
//!
|
||||||
|
//! pub const std_options = struct {
|
||||||
//! // Set the log level to info
|
//! // Set the log level to info
|
||||||
//! pub const log_level: std.log.Level = .info;
|
//! pub const log_level = .info;
|
||||||
//!
|
//!
|
||||||
//! // Define root.log to override the std implementation
|
//! // Define logFn to override the std implementation
|
||||||
//! pub fn log(
|
//! pub const logFn = myLogFn;
|
||||||
|
//! };
|
||||||
|
//!
|
||||||
|
//! pub fn myLogFn(
|
||||||
//! comptime level: std.log.Level,
|
//! comptime level: std.log.Level,
|
||||||
//! comptime scope: @TypeOf(.EnumLiteral),
|
//! comptime scope: @TypeOf(.EnumLiteral),
|
||||||
//! comptime format: []const u8,
|
//! comptime format: []const u8,
|
||||||
|
|
@ -70,7 +74,6 @@
|
||||||
|
|
||||||
const std = @import("std.zig");
|
const std = @import("std.zig");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const root = @import("root");
|
|
||||||
|
|
||||||
pub const Level = enum {
|
pub const Level = enum {
|
||||||
/// Error: something has gone wrong. This might be recoverable or might
|
/// Error: something has gone wrong. This might be recoverable or might
|
||||||
|
|
@ -102,22 +105,14 @@ pub const default_level: Level = switch (builtin.mode) {
|
||||||
.ReleaseFast, .ReleaseSmall => .err,
|
.ReleaseFast, .ReleaseSmall => .err,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The current log level. This is set to root.log_level if present, otherwise
|
const level = std.options.log_level;
|
||||||
/// log.default_level.
|
|
||||||
pub const level: Level = if (@hasDecl(root, "log_level"))
|
|
||||||
root.log_level
|
|
||||||
else
|
|
||||||
default_level;
|
|
||||||
|
|
||||||
pub const ScopeLevel = struct {
|
pub const ScopeLevel = struct {
|
||||||
scope: @Type(.EnumLiteral),
|
scope: @Type(.EnumLiteral),
|
||||||
level: Level,
|
level: Level,
|
||||||
};
|
};
|
||||||
|
|
||||||
const scope_levels = if (@hasDecl(root, "scope_levels"))
|
const scope_levels = std.options.log_scope_levels;
|
||||||
root.scope_levels
|
|
||||||
else
|
|
||||||
[0]ScopeLevel{};
|
|
||||||
|
|
||||||
fn log(
|
fn log(
|
||||||
comptime message_level: Level,
|
comptime message_level: Level,
|
||||||
|
|
@ -127,13 +122,7 @@ fn log(
|
||||||
) void {
|
) void {
|
||||||
if (comptime !logEnabled(message_level, scope)) return;
|
if (comptime !logEnabled(message_level, scope)) return;
|
||||||
|
|
||||||
if (@hasDecl(root, "log")) {
|
std.options.logFn(message_level, scope, format, args);
|
||||||
if (@typeInfo(@TypeOf(root.log)) != .Fn)
|
|
||||||
@compileError("Expected root.log to be a function");
|
|
||||||
root.log(message_level, scope, format, args);
|
|
||||||
} else {
|
|
||||||
defaultLog(message_level, scope, format, args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine if a specific log message level and scope combination are enabled for logging.
|
/// Determine if a specific log message level and scope combination are enabled for logging.
|
||||||
|
|
@ -149,8 +138,8 @@ pub fn defaultLogEnabled(comptime message_level: Level) bool {
|
||||||
return comptime logEnabled(message_level, default_log_scope);
|
return comptime logEnabled(message_level, default_log_scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The default implementation for root.log. root.log may forward log messages
|
/// The default implementation for the log function, custom log functions may
|
||||||
/// to this function.
|
/// forward log messages to this function.
|
||||||
pub fn defaultLog(
|
pub fn defaultLog(
|
||||||
comptime message_level: Level,
|
comptime message_level: Level,
|
||||||
comptime scope: @Type(.EnumLiteral),
|
comptime scope: @Type(.EnumLiteral),
|
||||||
|
|
|
||||||
|
|
@ -527,7 +527,7 @@ const bad_main_ret = "expected return type of main to be 'void', '!void', 'noret
|
||||||
// and we want fewer call frames in stack traces.
|
// and we want fewer call frames in stack traces.
|
||||||
inline fn initEventLoopAndCallMain() u8 {
|
inline fn initEventLoopAndCallMain() u8 {
|
||||||
if (std.event.Loop.instance) |loop| {
|
if (std.event.Loop.instance) |loop| {
|
||||||
if (!@hasDecl(root, "event_loop")) {
|
if (loop == std.event.Loop.default_instance) {
|
||||||
loop.init() catch |err| {
|
loop.init() catch |err| {
|
||||||
std.log.err("{s}", .{@errorName(err)});
|
std.log.err("{s}", .{@errorName(err)});
|
||||||
if (@errorReturnTrace()) |trace| {
|
if (@errorReturnTrace()) |trace| {
|
||||||
|
|
@ -556,7 +556,7 @@ inline fn initEventLoopAndCallMain() u8 {
|
||||||
// because it is working around stage1 compiler bugs.
|
// because it is working around stage1 compiler bugs.
|
||||||
inline fn initEventLoopAndCallWinMain() std.os.windows.INT {
|
inline fn initEventLoopAndCallWinMain() std.os.windows.INT {
|
||||||
if (std.event.Loop.instance) |loop| {
|
if (std.event.Loop.instance) |loop| {
|
||||||
if (!@hasDecl(root, "event_loop")) {
|
if (loop == std.event.Loop.default_instance) {
|
||||||
loop.init() catch |err| {
|
loop.init() catch |err| {
|
||||||
std.log.err("{s}", .{@errorName(err)});
|
std.log.err("{s}", .{@errorName(err)});
|
||||||
if (@errorReturnTrace()) |trace| {
|
if (@errorReturnTrace()) |trace| {
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,79 @@ pub const wasm = @import("wasm.zig");
|
||||||
pub const zig = @import("zig.zig");
|
pub const zig = @import("zig.zig");
|
||||||
pub const start = @import("start.zig");
|
pub const start = @import("start.zig");
|
||||||
|
|
||||||
|
const root = @import("root");
|
||||||
|
const options_override = if (@hasDecl(root, "std_options")) root.std_options else struct {};
|
||||||
|
|
||||||
|
pub const options = struct {
|
||||||
|
pub const enable_segfault_handler: bool = if (@hasDecl(options_override, "enable_segfault_handler"))
|
||||||
|
options_override.enable_segfault_handler
|
||||||
|
else
|
||||||
|
debug.default_enable_segfault_handler;
|
||||||
|
|
||||||
|
/// Function used to implement std.fs.cwd for wasi.
|
||||||
|
pub const wasiCwd: fn () fs.Dir = if (@hasDecl(options_override, "wasiCwd"))
|
||||||
|
options_override.wasiCwd
|
||||||
|
else
|
||||||
|
fs.defaultWasiCwd;
|
||||||
|
|
||||||
|
/// The application's chosen I/O mode.
|
||||||
|
pub const io_mode: io.Mode = if (@hasDecl(options_override, "io_mode"))
|
||||||
|
options_override.io_mode
|
||||||
|
else if (@hasDecl(options_override, "event_loop"))
|
||||||
|
.evented
|
||||||
|
else
|
||||||
|
.blocking;
|
||||||
|
|
||||||
|
pub const event_loop: event.Loop.Instance = if (@hasDecl(options_override, "event_loop"))
|
||||||
|
options_override.event_loop
|
||||||
|
else
|
||||||
|
event.Loop.default_instance;
|
||||||
|
|
||||||
|
pub const event_loop_mode: event.Loop.Mode = if (@hasDecl(options_override, "event_loop_mode"))
|
||||||
|
options_override.event_loop_mode
|
||||||
|
else
|
||||||
|
event.Loop.default_mode;
|
||||||
|
|
||||||
|
/// The current log level.
|
||||||
|
pub const log_level: log.Level = if (@hasDecl(options_override, "log_level"))
|
||||||
|
options_override.log_level
|
||||||
|
else
|
||||||
|
log.default_level;
|
||||||
|
|
||||||
|
pub const log_scope_levels: []const log.ScopeLevel = if (@hasDecl(options_override, "log_scope_levels"))
|
||||||
|
options_override.log_scope_levels
|
||||||
|
else
|
||||||
|
&.{};
|
||||||
|
|
||||||
|
pub const logFn: fn (
|
||||||
|
comptime message_level: log.Level,
|
||||||
|
comptime scope: @TypeOf(.enum_literal),
|
||||||
|
comptime format: []const u8,
|
||||||
|
args: anytype,
|
||||||
|
) void = if (@hasDecl(options_override, "logFn"))
|
||||||
|
options_override.logFn
|
||||||
|
else
|
||||||
|
log.defaultLog;
|
||||||
|
|
||||||
|
pub const cryptoRandomSeed: fn (buffer: []u8) void = if (@hasDecl(options_override, "cryptoRandomSeed"))
|
||||||
|
options_override.cryptoRandomSeed
|
||||||
|
else
|
||||||
|
@import("crypto/tlcsprng.zig").defaultRandomSeed;
|
||||||
|
|
||||||
|
pub const crypto_always_getrandom: bool = if (@hasDecl(options_override, "crypto_always_getrandom"))
|
||||||
|
options_override.crypto_always_getrandom
|
||||||
|
else
|
||||||
|
false;
|
||||||
|
};
|
||||||
|
|
||||||
// This forces the start.zig file to be imported, and the comptime logic inside that
|
// This forces the start.zig file to be imported, and the comptime logic inside that
|
||||||
// file decides whether to export any appropriate start symbols, and call main.
|
// file decides whether to export any appropriate start symbols, and call main.
|
||||||
comptime {
|
comptime {
|
||||||
_ = start;
|
_ = start;
|
||||||
|
|
||||||
|
for (@typeInfo(options_override).Struct.decls) |decl| {
|
||||||
|
if (!@hasDecl(options, decl.name)) @compileError("no option named " ++ decl.name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@ const std = @import("std");
|
||||||
const io = std.io;
|
const io = std.io;
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
pub const std_options = struct {
|
||||||
pub const io_mode: io.Mode = builtin.test_io_mode;
|
pub const io_mode: io.Mode = builtin.test_io_mode;
|
||||||
|
pub const logFn = log;
|
||||||
|
};
|
||||||
|
|
||||||
var log_err_count: usize = 0;
|
var log_err_count: usize = 0;
|
||||||
|
|
||||||
|
|
@ -45,7 +48,7 @@ pub fn main() void {
|
||||||
if (!have_tty) {
|
if (!have_tty) {
|
||||||
std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name });
|
std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name });
|
||||||
}
|
}
|
||||||
const result = if (test_fn.async_frame_size) |size| switch (io_mode) {
|
const result = if (test_fn.async_frame_size) |size| switch (std.options.io_mode) {
|
||||||
.evented => blk: {
|
.evented => blk: {
|
||||||
if (async_frame_buffer.len < size) {
|
if (async_frame_buffer.len < size) {
|
||||||
std.heap.page_allocator.free(async_frame_buffer);
|
std.heap.page_allocator.free(async_frame_buffer);
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,10 @@ const Decl = Module.Decl;
|
||||||
|
|
||||||
pub const is_enabled = builtin.mode == .Debug;
|
pub const is_enabled = builtin.mode == .Debug;
|
||||||
|
|
||||||
/// To use these crash report diagnostics, publish these symbols in your main file.
|
/// To use these crash report diagnostics, publish this panic in your main file
|
||||||
|
/// and add `pub const enable_segfault_handler = false;` to your `std_options`.
|
||||||
/// You will also need to call initialize() on startup, preferably as the very first operation in your program.
|
/// You will also need to call initialize() on startup, preferably as the very first operation in your program.
|
||||||
pub const root_decls = struct {
|
|
||||||
pub const panic = if (is_enabled) compilerPanic else std.builtin.default_panic;
|
pub const panic = if (is_enabled) compilerPanic else std.builtin.default_panic;
|
||||||
pub const enable_segfault_handler = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Install signal handlers to identify crashes and report diagnostics.
|
/// Install signal handlers to identify crashes and report diagnostics.
|
||||||
pub fn initialize() void {
|
pub fn initialize() void {
|
||||||
|
|
|
||||||
26
src/main.zig
26
src/main.zig
|
|
@ -25,11 +25,23 @@ const target_util = @import("target.zig");
|
||||||
const ThreadPool = @import("ThreadPool.zig");
|
const ThreadPool = @import("ThreadPool.zig");
|
||||||
const crash_report = @import("crash_report.zig");
|
const crash_report = @import("crash_report.zig");
|
||||||
|
|
||||||
// Crash report needs to override the panic handler and other root decls
|
pub const std_options = struct {
|
||||||
pub usingnamespace crash_report.root_decls;
|
pub const wasiCwd = wasi_cwd;
|
||||||
|
pub const logFn = log;
|
||||||
|
pub const enable_segfault_handler = false;
|
||||||
|
|
||||||
|
pub const log_level: std.log.Level = switch (builtin.mode) {
|
||||||
|
.Debug => .debug,
|
||||||
|
.ReleaseSafe, .ReleaseFast => .info,
|
||||||
|
.ReleaseSmall => .err,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Crash report needs to override the panic handler
|
||||||
|
pub const panic = crash_report.panic;
|
||||||
|
|
||||||
var wasi_preopens: fs.wasi.Preopens = undefined;
|
var wasi_preopens: fs.wasi.Preopens = undefined;
|
||||||
pub inline fn wasi_cwd() fs.Dir {
|
pub fn wasi_cwd() fs.Dir {
|
||||||
// Expect the first preopen to be current working directory.
|
// Expect the first preopen to be current working directory.
|
||||||
const cwd_fd: std.os.fd_t = 3;
|
const cwd_fd: std.os.fd_t = 3;
|
||||||
assert(mem.eql(u8, wasi_preopens.names[cwd_fd], "."));
|
assert(mem.eql(u8, wasi_preopens.names[cwd_fd], "."));
|
||||||
|
|
@ -111,12 +123,6 @@ const debug_usage = normal_usage ++
|
||||||
|
|
||||||
const usage = if (debug_extensions_enabled) debug_usage else normal_usage;
|
const usage = if (debug_extensions_enabled) debug_usage else normal_usage;
|
||||||
|
|
||||||
pub const log_level: std.log.Level = switch (builtin.mode) {
|
|
||||||
.Debug => .debug,
|
|
||||||
.ReleaseSafe, .ReleaseFast => .info,
|
|
||||||
.ReleaseSmall => .err,
|
|
||||||
};
|
|
||||||
|
|
||||||
var log_scopes: std.ArrayListUnmanaged([]const u8) = .{};
|
var log_scopes: std.ArrayListUnmanaged([]const u8) = .{};
|
||||||
|
|
||||||
pub fn log(
|
pub fn log(
|
||||||
|
|
@ -128,7 +134,7 @@ pub fn log(
|
||||||
// Hide debug messages unless:
|
// Hide debug messages unless:
|
||||||
// * logging enabled with `-Dlog`.
|
// * logging enabled with `-Dlog`.
|
||||||
// * the --debug-log arg for the scope has been provided
|
// * the --debug-log arg for the scope has been provided
|
||||||
if (@enumToInt(level) > @enumToInt(std.log.level) or
|
if (@enumToInt(level) > @enumToInt(std.options.log_level) or
|
||||||
@enumToInt(level) > @enumToInt(std.log.Level.info))
|
@enumToInt(level) > @enumToInt(std.log.Level.info))
|
||||||
{
|
{
|
||||||
if (!build_options.enable_logging) return;
|
if (!build_options.enable_logging) return;
|
||||||
|
|
|
||||||
|
|
@ -509,8 +509,8 @@ test "ptrCast comptime known slice to C pointer" {
|
||||||
test "ptrToInt on a generic function" {
|
test "ptrToInt on a generic function" {
|
||||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn generic(i: anytype) @TypeOf(i) {
|
fn generic(i: anytype) @TypeOf(i) {
|
||||||
|
|
|
||||||
|
|
@ -440,12 +440,15 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
|
||||||
cases.add("std.log per scope log level override",
|
cases.add("std.log per scope log level override",
|
||||||
\\const std = @import("std");
|
\\const std = @import("std");
|
||||||
\\
|
\\
|
||||||
|
\\pub const std_options = struct {
|
||||||
\\ pub const log_level: std.log.Level = .debug;
|
\\ pub const log_level: std.log.Level = .debug;
|
||||||
\\
|
\\
|
||||||
\\pub const scope_levels = [_]std.log.ScopeLevel{
|
\\ pub const log_scope_levels = &[_]std.log.ScopeLevel{
|
||||||
\\ .{ .scope = .a, .level = .warn },
|
\\ .{ .scope = .a, .level = .warn },
|
||||||
\\ .{ .scope = .c, .level = .err },
|
\\ .{ .scope = .c, .level = .err },
|
||||||
\\ };
|
\\ };
|
||||||
|
\\ pub const logFn = log;
|
||||||
|
\\};
|
||||||
\\
|
\\
|
||||||
\\const loga = std.log.scoped(.a);
|
\\const loga = std.log.scoped(.a);
|
||||||
\\const logb = std.log.scoped(.b);
|
\\const logb = std.log.scoped(.b);
|
||||||
|
|
@ -494,7 +497,10 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
|
||||||
cases.add("std.heap.LoggingAllocator logs to std.log",
|
cases.add("std.heap.LoggingAllocator logs to std.log",
|
||||||
\\const std = @import("std");
|
\\const std = @import("std");
|
||||||
\\
|
\\
|
||||||
|
\\pub const std_options = struct {
|
||||||
\\ pub const log_level: std.log.Level = .debug;
|
\\ pub const log_level: std.log.Level = .debug;
|
||||||
|
\\ pub const logFn = log;
|
||||||
|
\\};
|
||||||
\\
|
\\
|
||||||
\\pub fn main() !void {
|
\\pub fn main() !void {
|
||||||
\\ var allocator_buf: [10]u8 = undefined;
|
\\ var allocator_buf: [10]u8 = undefined;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const std_options = struct {
|
||||||
|
pub const logFn = log;
|
||||||
|
};
|
||||||
|
|
||||||
pub fn log(
|
pub fn log(
|
||||||
comptime message_level: std.log.Level,
|
comptime message_level: std.log.Level,
|
||||||
comptime scope: @Type(.EnumLiteral),
|
comptime scope: @Type(.EnumLiteral),
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,4 @@
|
||||||
|
pub const std_options = struct {
|
||||||
pub const io_mode = .evented;
|
pub const io_mode = .evented;
|
||||||
|
};
|
||||||
pub fn main() void {}
|
pub fn main() void {}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue