| author | |
| committer | |
| log | f83834993e2628e347da71a11ffb07c804fc46c5 |
| tree | 21fd10b3ba19c4236326549872a202a4ffe29b3f |
| parent | fe2bd9dda8467b775da4fe3bd535aece9e07ee1b |
17 files changed, 164 insertions(+), 97 deletions(-)
lib/std/crypto/tlcsprng.zig+8-13| ... | @@ -5,7 +5,6 @@ | ... | @@ -5,7 +5,6 @@ |
| 5 | 5 | ||
| 6 | const std = @import("std"); | 6 | const std = @import("std"); |
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const root = @import("root"); | ||
| 9 | const mem = std.mem; | 8 | const mem = std.mem; |
| 10 | const os = std.os; | 9 | const os = std.os; |
| 11 | 10 | ||
| ... | @@ -67,8 +66,8 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { | ... | @@ -67,8 +66,8 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { |
| 67 | // Allow applications to decide they would prefer to have every call to | 66 | // Allow applications to decide they would prefer to have every call to |
| 68 | // std.crypto.random always make an OS syscall, rather than rely on an | 67 | // std.crypto.random always make an OS syscall, rather than rely on an |
| 69 | // application implementation of a CSPRNG. | 68 | // application implementation of a CSPRNG. |
| 70 | if (comptime std.meta.globalOption("crypto_always_getrandom", bool) orelse false) { | 69 | if (std.options.crypto_always_getrandom) { |
| 71 | return fillWithOsEntropy(buffer); | 70 | return defaultRandomSeed(buffer); |
| 72 | } | 71 | } |
| 73 | 72 | ||
| 74 | if (wipe_mem.len == 0) { | 73 | if (wipe_mem.len == 0) { |
| ... | @@ -86,7 +85,7 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { | ... | @@ -86,7 +85,7 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { |
| 86 | ) catch { | 85 | ) catch { |
| 87 | // Could not allocate memory for the local state, fall back to | 86 | // Could not allocate memory for the local state, fall back to |
| 88 | // the OS syscall. | 87 | // the OS syscall. |
| 89 | return fillWithOsEntropy(buffer); | 88 | return std.options.cryptoRandomSeed(buffer); |
| 90 | }; | 89 | }; |
| 91 | // The memory is already zero-initialized. | 90 | // The memory is already zero-initialized. |
| 92 | } else { | 91 | } else { |
| ... | @@ -128,14 +127,14 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { | ... | @@ -128,14 +127,14 @@ fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { |
| 128 | // Since we failed to set up fork safety, we fall back to always | 127 | // Since we failed to set up fork safety, we fall back to always |
| 129 | // calling getrandom every time. | 128 | // calling getrandom every time. |
| 130 | ctx.init_state = .failed; | 129 | ctx.init_state = .failed; |
| 131 | return fillWithOsEntropy(buffer); | 130 | return std.options.cryptoRandomSeed(buffer); |
| 132 | }, | 131 | }, |
| 133 | .initialized => { | 132 | .initialized => { |
| 134 | return fillWithCsprng(buffer); | 133 | return fillWithCsprng(buffer); |
| 135 | }, | 134 | }, |
| 136 | .failed => { | 135 | .failed => { |
| 137 | if (want_fork_safety) { | 136 | if (want_fork_safety) { |
| 138 | return fillWithOsEntropy(buffer); | 137 | return std.options.cryptoRandomSeed(buffer); |
| 139 | } else { | 138 | } else { |
| 140 | unreachable; | 139 | unreachable; |
| 141 | } | 140 | } |
| ... | @@ -165,7 +164,7 @@ fn fillWithCsprng(buffer: []u8) void { | ... | @@ -165,7 +164,7 @@ fn fillWithCsprng(buffer: []u8) void { |
| 165 | mem.set(u8, ctx.gimli.toSlice()[0..std.crypto.core.Gimli.RATE], 0); | 164 | mem.set(u8, ctx.gimli.toSlice()[0..std.crypto.core.Gimli.RATE], 0); |
| 166 | } | 165 | } |
| 167 | 166 | ||
| 168 | fn fillWithOsEntropy(buffer: []u8) void { | 167 | pub fn defaultRandomSeed(buffer: []u8) void { |
| 169 | os.getrandom(buffer) catch @panic("getrandom() failed to provide entropy"); | 168 | os.getrandom(buffer) catch @panic("getrandom() failed to provide entropy"); |
| 170 | } | 169 | } |
| 171 | 170 | ||
| ... | @@ -174,12 +173,8 @@ fn initAndFill(buffer: []u8) void { | ... | @@ -174,12 +173,8 @@ fn initAndFill(buffer: []u8) void { |
| 174 | // Because we panic on getrandom() failing, we provide the opportunity | 173 | // Because we panic on getrandom() failing, we provide the opportunity |
| 175 | // to override the default seed function. This also makes | 174 | // to override the default seed function. This also makes |
| 176 | // `std.crypto.random` available on freestanding targets, provided that | 175 | // `std.crypto.random` available on freestanding targets, provided that |
| 177 | // the `cryptoRandomSeed` function is provided. | 176 | // the `std.options.cryptoRandomSeed` function is provided. |
| 178 | if (@hasDecl(root, "cryptoRandomSeed")) { | 177 | std.options.cryptoRandomSeed(&seed); |
| 179 | root.cryptoRandomSeed(&seed); | ||
| 180 | } else { | ||
| 181 | fillWithOsEntropy(&seed); | ||
| 182 | } | ||
| 183 | 178 | ||
| 184 | const ctx = @ptrCast(*Context, wipe_mem.ptr); | 179 | const ctx = @ptrCast(*Context, wipe_mem.ptr); |
| 185 | ctx.gimli = std.crypto.core.Gimli.init(seed); | 180 | ctx.gimli = std.crypto.core.Gimli.init(seed); |
lib/std/debug.zig+3-4| ... | @@ -1861,10 +1861,9 @@ pub const have_segfault_handling_support = switch (native_os) { | ... | @@ -1861,10 +1861,9 @@ pub const have_segfault_handling_support = switch (native_os) { |
| 1861 | .freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"), | 1861 | .freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"), |
| 1862 | else => false, | 1862 | else => false, |
| 1863 | }; | 1863 | }; |
| 1864 | pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler")) | 1864 | |
| 1865 | root.enable_segfault_handler | 1865 | const enable_segfault_handler = std.options.enable_segfault_handler; |
| 1866 | else | 1866 | pub const default_enable_segfault_handler = runtime_safety and have_segfault_handling_support; |
| 1867 | runtime_safety and have_segfault_handling_support; | ||
| 1868 | 1867 | ||
| 1869 | pub fn maybeEnableSegfaultHandler() void { | 1868 | pub fn maybeEnableSegfaultHandler() void { |
| 1870 | if (enable_segfault_handler) { | 1869 | if (enable_segfault_handler) { |
lib/std/event/batch.zig+1-1| ... | @@ -17,7 +17,7 @@ pub fn Batch( | ... | @@ -17,7 +17,7 @@ pub fn Batch( |
| 17 | comptime async_behavior: enum { | 17 | comptime async_behavior: enum { |
| 18 | /// Observe the value of `std.io.is_async` to decide whether `add` | 18 | /// Observe the value of `std.io.is_async` to decide whether `add` |
| 19 | /// and `wait` will be async functions. Asserts that the jobs do not suspend when | 19 | /// and `wait` will be async functions. Asserts that the jobs do not suspend when |
| 20 | /// `std.io.mode == .blocking`. This is a generally safe assumption, and the | 20 | /// `std.options.io_mode == .blocking`. This is a generally safe assumption, and the |
| 21 | /// usual recommended option for this parameter. | 21 | /// usual recommended option for this parameter. |
| 22 | auto_async, | 22 | auto_async, |
| 23 | 23 |
lib/std/event/loop.zig+13-10| ... | @@ -1,6 +1,5 @@ | ... | @@ -1,6 +1,5 @@ |
| 1 | const std = @import("../std.zig"); | 1 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const root = @import("root"); | ||
| 4 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 5 | const testing = std.testing; | 4 | const testing = std.testing; |
| 6 | const mem = std.mem; | 5 | const mem = std.mem; |
| ... | @@ -104,25 +103,29 @@ pub const Loop = struct { | ... | @@ -104,25 +103,29 @@ pub const Loop = struct { |
| 104 | }; | 103 | }; |
| 105 | }; | 104 | }; |
| 106 | 105 | ||
| 107 | const LoopOrVoid = switch (std.io.mode) { | 106 | pub const Instance = switch (std.options.io_mode) { |
| 108 | .blocking => void, | 107 | .blocking => @TypeOf(null), |
| 109 | .evented => Loop, | 108 | .evented => ?*Loop, |
| 110 | }; | 109 | }; |
| 110 | pub const instance = std.options.event_loop; | ||
| 111 | 111 | ||
| 112 | var global_instance_state: LoopOrVoid = undefined; | 112 | var global_instance_state: Loop = undefined; |
| 113 | const default_instance: ?*LoopOrVoid = switch (std.io.mode) { | 113 | pub const default_instance = switch (std.options.io_mode) { |
| 114 | .blocking => null, | 114 | .blocking => null, |
| 115 | .evented => &global_instance_state, | 115 | .evented => &global_instance_state, |
| 116 | }; | 116 | }; |
| 117 | pub const instance: ?*LoopOrVoid = if (@hasDecl(root, "event_loop")) root.event_loop else default_instance; | 117 | |
| 118 | pub const Mode = enum { | ||
| 119 | single_threaded, | ||
| 120 | multi_threaded, | ||
| 121 | }; | ||
| 122 | pub const default_mode = .multi_threaded; | ||
| 118 | 123 | ||
| 119 | /// TODO copy elision / named return values so that the threads referencing *Loop | 124 | /// TODO copy elision / named return values so that the threads referencing *Loop |
| 120 | /// have the correct pointer value. | 125 | /// have the correct pointer value. |
| 121 | /// https://github.com/ziglang/zig/issues/2761 and https://github.com/ziglang/zig/issues/2765 | 126 | /// https://github.com/ziglang/zig/issues/2761 and https://github.com/ziglang/zig/issues/2765 |
| 122 | pub fn init(self: *Loop) !void { | 127 | pub fn init(self: *Loop) !void { |
| 123 | if (builtin.single_threaded or | 128 | if (builtin.single_threaded or std.options.event_loop_mode == .single_threaded) { |
| 124 | (@hasDecl(root, "event_loop_mode") and root.event_loop_mode == .single_threaded)) | ||
| 125 | { | ||
| 126 | return self.initSingleThreaded(); | 129 | return self.initSingleThreaded(); |
| 127 | } else { | 130 | } else { |
| 128 | return self.initMultiThreaded(); | 131 | return self.initMultiThreaded(); |
lib/std/fs.zig+6-6| ... | @@ -2661,17 +2661,17 @@ pub fn cwd() Dir { | ... | @@ -2661,17 +2661,17 @@ pub fn cwd() Dir { |
| 2661 | if (builtin.os.tag == .windows) { | 2661 | if (builtin.os.tag == .windows) { |
| 2662 | return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle }; | 2662 | return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle }; |
| 2663 | } else if (builtin.os.tag == .wasi) { | 2663 | } else if (builtin.os.tag == .wasi) { |
| 2664 | if (@hasDecl(root, "wasi_cwd")) { | 2664 | return std.options.wasiCwd(); |
| 2665 | return root.wasi_cwd(); | ||
| 2666 | } else { | ||
| 2667 | // Expect the first preopen to be current working directory. | ||
| 2668 | return .{ .fd = 3 }; | ||
| 2669 | } | ||
| 2670 | } else { | 2665 | } else { |
| 2671 | return Dir{ .fd = os.AT.FDCWD }; | 2666 | return Dir{ .fd = os.AT.FDCWD }; |
| 2672 | } | 2667 | } |
| 2673 | } | 2668 | } |
| 2674 | 2669 | ||
| 2670 | pub fn defaultWasiCwd() Dir { | ||
| 2671 | // Expect the first preopen to be current working directory. | ||
| 2672 | return .{ .fd = 3 }; | ||
| 2673 | } | ||
| 2674 | |||
| 2675 | /// Opens a directory at the given path. The directory is a system resource that remains | 2675 | /// Opens a directory at the given path. The directory is a system resource that remains |
| 2676 | /// open until `close` is called on the result. | 2676 | /// open until `close` is called on the result. |
| 2677 | /// See `openDirAbsoluteZ` for a function that accepts a null-terminated path. | 2677 | /// See `openDirAbsoluteZ` for a function that accepts a null-terminated path. |
lib/std/fs/file.zig+1-1| ... | @@ -21,7 +21,7 @@ pub const File = struct { | ... | @@ -21,7 +21,7 @@ pub const File = struct { |
| 21 | /// blocking. | 21 | /// blocking. |
| 22 | capable_io_mode: io.ModeOverride = io.default_mode, | 22 | capable_io_mode: io.ModeOverride = io.default_mode, |
| 23 | 23 | ||
| 24 | /// Furthermore, even when `std.io.mode` is async, it is still sometimes desirable | 24 | /// Furthermore, even when `std.options.io_mode` is async, it is still sometimes desirable |
| 25 | /// to perform blocking I/O, although not by default. For example, when printing a | 25 | /// to perform blocking I/O, although not by default. For example, when printing a |
| 26 | /// stack trace to stderr. This field tracks both by acting as an overriding I/O mode. | 26 | /// stack trace to stderr. This field tracks both by acting as an overriding I/O mode. |
| 27 | /// When not building in async I/O mode, the type only has the `.blocking` tag, making | 27 | /// When not building in async I/O mode, the type only has the `.blocking` tag, making |
lib/std/io.zig+1-8| ... | @@ -19,14 +19,7 @@ pub const Mode = enum { | ... | @@ -19,14 +19,7 @@ pub const Mode = enum { |
| 19 | evented, | 19 | evented, |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | /// The application's chosen I/O mode. This defaults to `Mode.blocking` but can be overridden | 22 | const mode = std.options.io_mode; |
| 23 | /// by `root.event_loop`. | ||
| 24 | pub const mode: Mode = if (@hasDecl(root, "io_mode")) | ||
| 25 | root.io_mode | ||
| 26 | else if (@hasDecl(root, "event_loop")) | ||
| 27 | Mode.evented | ||
| 28 | else | ||
| 29 | Mode.blocking; | ||
| 30 | pub const is_async = mode != .blocking; | 23 | pub const is_async = mode != .blocking; |
| 31 | 24 | ||
| 32 | /// This is an enum value to use for I/O mode at runtime, since it takes up zero bytes at runtime, | 25 | /// This is an enum value to use for I/O mode at runtime, since it takes up zero bytes at runtime, |
lib/std/log.zig+15-26| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | //! std.log is a standardized interface for logging which allows for the logging | 1 | //! std.log is a standardized interface for logging which allows for the logging |
| 2 | //! of programs and libraries using this interface to be formatted and filtered | 2 | //! of programs and libraries using this interface to be formatted and filtered |
| 3 | //! by the implementer of the root.log function. | 3 | //! by the implementer of the `std.options.logFn` function. |
| 4 | //! | 4 | //! |
| 5 | //! Each log message has an associated scope enum, which can be used to give | 5 | //! Each log message has an associated scope enum, which can be used to give |
| 6 | //! context to the logging. The logging functions in std.log implicitly use a | 6 | //! context to the logging. The logging functions in std.log implicitly use a |
| ... | @@ -13,16 +13,20 @@ | ... | @@ -13,16 +13,20 @@ |
| 13 | //! `const log = std.log.scoped(.libfoo);` to use .libfoo as the scope of its | 13 | //! `const log = std.log.scoped(.libfoo);` to use .libfoo as the scope of its |
| 14 | //! log messages. | 14 | //! log messages. |
| 15 | //! | 15 | //! |
| 16 | //! An example root.log might look something like this: | 16 | //! An example `logFn` might look something like this: |
| 17 | //! | 17 | //! |
| 18 | //! ``` | 18 | //! ``` |
| 19 | //! const std = @import("std"); | 19 | //! const std = @import("std"); |
| 20 | //! | 20 | //! |
| 21 | //! // Set the log level to info | 21 | //! pub const std_options = struct { |
| 22 | //! pub const log_level: std.log.Level = .info; | 22 | //! // Set the log level to info |
| 23 | //! pub const log_level = .info; | ||
| 23 | //! | 24 | //! |
| 24 | //! // Define root.log to override the std implementation | 25 | //! // Define logFn to override the std implementation |
| 25 | //! pub fn log( | 26 | //! pub const logFn = myLogFn; |
| 27 | //! }; | ||
| 28 | //! | ||
| 29 | //! pub fn myLogFn( | ||
| 26 | //! comptime level: std.log.Level, | 30 | //! comptime level: std.log.Level, |
| 27 | //! comptime scope: @TypeOf(.EnumLiteral), | 31 | //! comptime scope: @TypeOf(.EnumLiteral), |
| 28 | //! comptime format: []const u8, | 32 | //! comptime format: []const u8, |
| ... | @@ -70,7 +74,6 @@ | ... | @@ -70,7 +74,6 @@ |
| 70 | 74 | ||
| 71 | const std = @import("std.zig"); | 75 | const std = @import("std.zig"); |
| 72 | const builtin = @import("builtin"); | 76 | const builtin = @import("builtin"); |
| 73 | const root = @import("root"); | ||
| 74 | 77 | ||
| 75 | pub const Level = enum { | 78 | pub const Level = enum { |
| 76 | /// Error: something has gone wrong. This might be recoverable or might | 79 | /// Error: something has gone wrong. This might be recoverable or might |
| ... | @@ -102,22 +105,14 @@ pub const default_level: Level = switch (builtin.mode) { | ... | @@ -102,22 +105,14 @@ pub const default_level: Level = switch (builtin.mode) { |
| 102 | .ReleaseFast, .ReleaseSmall => .err, | 105 | .ReleaseFast, .ReleaseSmall => .err, |
| 103 | }; | 106 | }; |
| 104 | 107 | ||
| 105 | /// The current log level. This is set to root.log_level if present, otherwise | 108 | const level = std.options.log_level; |
| 106 | /// log.default_level. | ||
| 107 | pub const level: Level = if (@hasDecl(root, "log_level")) | ||
| 108 | root.log_level | ||
| 109 | else | ||
| 110 | default_level; | ||
| 111 | 109 | ||
| 112 | pub const ScopeLevel = struct { | 110 | pub const ScopeLevel = struct { |
| 113 | scope: @Type(.EnumLiteral), | 111 | scope: @Type(.EnumLiteral), |
| 114 | level: Level, | 112 | level: Level, |
| 115 | }; | 113 | }; |
| 116 | 114 | ||
| 117 | const scope_levels = if (@hasDecl(root, "scope_levels")) | 115 | const scope_levels = std.options.log_scope_levels; |
| 118 | root.scope_levels | ||
| 119 | else | ||
| 120 | [0]ScopeLevel{}; | ||
| 121 | 116 | ||
| 122 | fn log( | 117 | fn log( |
| 123 | comptime message_level: Level, | 118 | comptime message_level: Level, |
| ... | @@ -127,13 +122,7 @@ fn log( | ... | @@ -127,13 +122,7 @@ fn log( |
| 127 | ) void { | 122 | ) void { |
| 128 | if (comptime !logEnabled(message_level, scope)) return; | 123 | if (comptime !logEnabled(message_level, scope)) return; |
| 129 | 124 | ||
| 130 | if (@hasDecl(root, "log")) { | 125 | std.options.logFn(message_level, scope, format, args); |
| 131 | if (@typeInfo(@TypeOf(root.log)) != .Fn) | ||
| 132 | @compileError("Expected root.log to be a function"); | ||
| 133 | root.log(message_level, scope, format, args); | ||
| 134 | } else { | ||
| 135 | defaultLog(message_level, scope, format, args); | ||
| 136 | } | ||
| 137 | } | 126 | } |
| 138 | 127 | ||
| 139 | /// Determine if a specific log message level and scope combination are enabled for logging. | 128 | /// 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 { | ... | @@ -149,8 +138,8 @@ pub fn defaultLogEnabled(comptime message_level: Level) bool { |
| 149 | return comptime logEnabled(message_level, default_log_scope); | 138 | return comptime logEnabled(message_level, default_log_scope); |
| 150 | } | 139 | } |
| 151 | 140 | ||
| 152 | /// The default implementation for root.log. root.log may forward log messages | 141 | /// The default implementation for the log function, custom log functions may |
| 153 | /// to this function. | 142 | /// forward log messages to this function. |
| 154 | pub fn defaultLog( | 143 | pub fn defaultLog( |
| 155 | comptime message_level: Level, | 144 | comptime message_level: Level, |
| 156 | comptime scope: @Type(.EnumLiteral), | 145 | comptime scope: @Type(.EnumLiteral), |
lib/std/start.zig+2-2| ... | @@ -527,7 +527,7 @@ const bad_main_ret = "expected return type of main to be 'void', '!void', 'noret | ... | @@ -527,7 +527,7 @@ const bad_main_ret = "expected return type of main to be 'void', '!void', 'noret |
| 527 | // and we want fewer call frames in stack traces. | 527 | // and we want fewer call frames in stack traces. |
| 528 | inline fn initEventLoopAndCallMain() u8 { | 528 | inline fn initEventLoopAndCallMain() u8 { |
| 529 | if (std.event.Loop.instance) |loop| { | 529 | if (std.event.Loop.instance) |loop| { |
| 530 | if (!@hasDecl(root, "event_loop")) { | 530 | if (loop == std.event.Loop.default_instance) { |
| 531 | loop.init() catch |err| { | 531 | loop.init() catch |err| { |
| 532 | std.log.err("{s}", .{@errorName(err)}); | 532 | std.log.err("{s}", .{@errorName(err)}); |
| 533 | if (@errorReturnTrace()) |trace| { | 533 | if (@errorReturnTrace()) |trace| { |
| ... | @@ -556,7 +556,7 @@ inline fn initEventLoopAndCallMain() u8 { | ... | @@ -556,7 +556,7 @@ inline fn initEventLoopAndCallMain() u8 { |
| 556 | // because it is working around stage1 compiler bugs. | 556 | // because it is working around stage1 compiler bugs. |
| 557 | inline fn initEventLoopAndCallWinMain() std.os.windows.INT { | 557 | inline fn initEventLoopAndCallWinMain() std.os.windows.INT { |
| 558 | if (std.event.Loop.instance) |loop| { | 558 | if (std.event.Loop.instance) |loop| { |
| 559 | if (!@hasDecl(root, "event_loop")) { | 559 | if (loop == std.event.Loop.default_instance) { |
| 560 | loop.init() catch |err| { | 560 | loop.init() catch |err| { |
| 561 | std.log.err("{s}", .{@errorName(err)}); | 561 | std.log.err("{s}", .{@errorName(err)}); |
| 562 | if (@errorReturnTrace()) |trace| { | 562 | if (@errorReturnTrace()) |trace| { |
lib/std/std.zig+69| ... | @@ -94,10 +94,79 @@ pub const wasm = @import("wasm.zig"); | ... | @@ -94,10 +94,79 @@ pub const wasm = @import("wasm.zig"); |
| 94 | pub const zig = @import("zig.zig"); | 94 | pub const zig = @import("zig.zig"); |
| 95 | pub const start = @import("start.zig"); | 95 | pub const start = @import("start.zig"); |
| 96 | 96 | ||
| 97 | const root = @import("root"); | ||
| 98 | const options_override = if (@hasDecl(root, "std_options")) root.std_options else struct {}; | ||
| 99 | |||
| 100 | pub const options = struct { | ||
| 101 | pub const enable_segfault_handler: bool = if (@hasDecl(options_override, "enable_segfault_handler")) | ||
| 102 | options_override.enable_segfault_handler | ||
| 103 | else | ||
| 104 | debug.default_enable_segfault_handler; | ||
| 105 | |||
| 106 | /// Function used to implement std.fs.cwd for wasi. | ||
| 107 | pub const wasiCwd: fn () fs.Dir = if (@hasDecl(options_override, "wasiCwd")) | ||
| 108 | options_override.wasiCwd | ||
| 109 | else | ||
| 110 | fs.defaultWasiCwd; | ||
| 111 | |||
| 112 | /// The application's chosen I/O mode. | ||
| 113 | pub const io_mode: io.Mode = if (@hasDecl(options_override, "io_mode")) | ||
| 114 | options_override.io_mode | ||
| 115 | else if (@hasDecl(options_override, "event_loop")) | ||
| 116 | .evented | ||
| 117 | else | ||
| 118 | .blocking; | ||
| 119 | |||
| 120 | pub const event_loop: event.Loop.Instance = if (@hasDecl(options_override, "event_loop")) | ||
| 121 | options_override.event_loop | ||
| 122 | else | ||
| 123 | event.Loop.default_instance; | ||
| 124 | |||
| 125 | pub const event_loop_mode: event.Loop.Mode = if (@hasDecl(options_override, "event_loop_mode")) | ||
| 126 | options_override.event_loop_mode | ||
| 127 | else | ||
| 128 | event.Loop.default_mode; | ||
| 129 | |||
| 130 | /// The current log level. | ||
| 131 | pub const log_level: log.Level = if (@hasDecl(options_override, "log_level")) | ||
| 132 | options_override.log_level | ||
| 133 | else | ||
| 134 | log.default_level; | ||
| 135 | |||
| 136 | pub const log_scope_levels: []const log.ScopeLevel = if (@hasDecl(options_override, "log_scope_levels")) | ||
| 137 | options_override.log_scope_levels | ||
| 138 | else | ||
| 139 | &.{}; | ||
| 140 | |||
| 141 | pub const logFn: fn ( | ||
| 142 | comptime message_level: log.Level, | ||
| 143 | comptime scope: @TypeOf(.enum_literal), | ||
| 144 | comptime format: []const u8, | ||
| 145 | args: anytype, | ||
| 146 | ) void = if (@hasDecl(options_override, "logFn")) | ||
| 147 | options_override.logFn | ||
| 148 | else | ||
| 149 | log.defaultLog; | ||
| 150 | |||
| 151 | pub const cryptoRandomSeed: fn (buffer: []u8) void = if (@hasDecl(options_override, "cryptoRandomSeed")) | ||
| 152 | options_override.cryptoRandomSeed | ||
| 153 | else | ||
| 154 | @import("crypto/tlcsprng.zig").defaultRandomSeed; | ||
| 155 | |||
| 156 | pub const crypto_always_getrandom: bool = if (@hasDecl(options_override, "crypto_always_getrandom")) | ||
| 157 | options_override.crypto_always_getrandom | ||
| 158 | else | ||
| 159 | false; | ||
| 160 | }; | ||
| 161 | |||
| 97 | // This forces the start.zig file to be imported, and the comptime logic inside that | 162 | // This forces the start.zig file to be imported, and the comptime logic inside that |
| 98 | // file decides whether to export any appropriate start symbols, and call main. | 163 | // file decides whether to export any appropriate start symbols, and call main. |
| 99 | comptime { | 164 | comptime { |
| 100 | _ = start; | 165 | _ = start; |
| 166 | |||
| 167 | for (@typeInfo(options_override).Struct.decls) |decl| { | ||
| 168 | if (!@hasDecl(options, decl.name)) @compileError("no option named " ++ decl.name); | ||
| 169 | } | ||
| 101 | } | 170 | } |
| 102 | 171 | ||
| 103 | test { | 172 | test { |
lib/test_runner.zig+5-2| ... | @@ -2,7 +2,10 @@ const std = @import("std"); | ... | @@ -2,7 +2,10 @@ const std = @import("std"); |
| 2 | const io = std.io; | 2 | const io = std.io; |
| 3 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 4 | 4 | ||
| 5 | pub const io_mode: io.Mode = builtin.test_io_mode; | 5 | pub const std_options = struct { |
| 6 | pub const io_mode: io.Mode = builtin.test_io_mode; | ||
| 7 | pub const logFn = log; | ||
| 8 | }; | ||
| 6 | 9 | ||
| 7 | var log_err_count: usize = 0; | 10 | var log_err_count: usize = 0; |
| 8 | 11 | ||
| ... | @@ -45,7 +48,7 @@ pub fn main() void { | ... | @@ -45,7 +48,7 @@ pub fn main() void { |
| 45 | if (!have_tty) { | 48 | if (!have_tty) { |
| 46 | std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name }); | 49 | std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name }); |
| 47 | } | 50 | } |
| 48 | const result = if (test_fn.async_frame_size) |size| switch (io_mode) { | 51 | const result = if (test_fn.async_frame_size) |size| switch (std.options.io_mode) { |
| 49 | .evented => blk: { | 52 | .evented => blk: { |
| 50 | if (async_frame_buffer.len < size) { | 53 | if (async_frame_buffer.len < size) { |
| 51 | std.heap.page_allocator.free(async_frame_buffer); | 54 | std.heap.page_allocator.free(async_frame_buffer); |
src/crash_report.zig+3-5| ... | @@ -13,12 +13,10 @@ const Decl = Module.Decl; | ... | @@ -13,12 +13,10 @@ const Decl = Module.Decl; |
| 13 | 13 | ||
| 14 | pub const is_enabled = builtin.mode == .Debug; | 14 | pub const is_enabled = builtin.mode == .Debug; |
| 15 | 15 | ||
| 16 | /// To use these crash report diagnostics, publish these symbols in your main file. | 16 | /// To use these crash report diagnostics, publish this panic in your main file |
| 17 | /// and add `pub const enable_segfault_handler = false;` to your `std_options`. | ||
| 17 | /// You will also need to call initialize() on startup, preferably as the very first operation in your program. | 18 | /// You will also need to call initialize() on startup, preferably as the very first operation in your program. |
| 18 | pub const root_decls = struct { | 19 | pub const panic = if (is_enabled) compilerPanic else std.builtin.default_panic; |
| 19 | pub const panic = if (is_enabled) compilerPanic else std.builtin.default_panic; | ||
| 20 | pub const enable_segfault_handler = false; | ||
| 21 | }; | ||
| 22 | 20 | ||
| 23 | /// Install signal handlers to identify crashes and report diagnostics. | 21 | /// Install signal handlers to identify crashes and report diagnostics. |
| 24 | pub fn initialize() void { | 22 | pub fn initialize() void { |
src/main.zig+16-10| ... | @@ -25,11 +25,23 @@ const target_util = @import("target.zig"); | ... | @@ -25,11 +25,23 @@ const target_util = @import("target.zig"); |
| 25 | const ThreadPool = @import("ThreadPool.zig"); | 25 | const ThreadPool = @import("ThreadPool.zig"); |
| 26 | const crash_report = @import("crash_report.zig"); | 26 | const crash_report = @import("crash_report.zig"); |
| 27 | 27 | ||
| 28 | // Crash report needs to override the panic handler and other root decls | 28 | pub const std_options = struct { |
| 29 | pub usingnamespace crash_report.root_decls; | 29 | pub const wasiCwd = wasi_cwd; |
| 30 | pub const logFn = log; | ||
| 31 | pub const enable_segfault_handler = false; | ||
| 32 | |||
| 33 | pub const log_level: std.log.Level = switch (builtin.mode) { | ||
| 34 | .Debug => .debug, | ||
| 35 | .ReleaseSafe, .ReleaseFast => .info, | ||
| 36 | .ReleaseSmall => .err, | ||
| 37 | }; | ||
| 38 | }; | ||
| 39 | |||
| 40 | // Crash report needs to override the panic handler | ||
| 41 | pub const panic = crash_report.panic; | ||
| 30 | 42 | ||
| 31 | var wasi_preopens: fs.wasi.Preopens = undefined; | 43 | var wasi_preopens: fs.wasi.Preopens = undefined; |
| 32 | pub inline fn wasi_cwd() fs.Dir { | 44 | pub fn wasi_cwd() fs.Dir { |
| 33 | // Expect the first preopen to be current working directory. | 45 | // Expect the first preopen to be current working directory. |
| 34 | const cwd_fd: std.os.fd_t = 3; | 46 | const cwd_fd: std.os.fd_t = 3; |
| 35 | assert(mem.eql(u8, wasi_preopens.names[cwd_fd], ".")); | 47 | assert(mem.eql(u8, wasi_preopens.names[cwd_fd], ".")); |
| ... | @@ -111,12 +123,6 @@ const debug_usage = normal_usage ++ | ... | @@ -111,12 +123,6 @@ const debug_usage = normal_usage ++ |
| 111 | 123 | ||
| 112 | const usage = if (debug_extensions_enabled) debug_usage else normal_usage; | 124 | const usage = if (debug_extensions_enabled) debug_usage else normal_usage; |
| 113 | 125 | ||
| 114 | pub const log_level: std.log.Level = switch (builtin.mode) { | ||
| 115 | .Debug => .debug, | ||
| 116 | .ReleaseSafe, .ReleaseFast => .info, | ||
| 117 | .ReleaseSmall => .err, | ||
| 118 | }; | ||
| 119 | |||
| 120 | var log_scopes: std.ArrayListUnmanaged([]const u8) = .{}; | 126 | var log_scopes: std.ArrayListUnmanaged([]const u8) = .{}; |
| 121 | 127 | ||
| 122 | pub fn log( | 128 | pub fn log( |
| ... | @@ -128,7 +134,7 @@ pub fn log( | ... | @@ -128,7 +134,7 @@ pub fn log( |
| 128 | // Hide debug messages unless: | 134 | // Hide debug messages unless: |
| 129 | // * logging enabled with `-Dlog`. | 135 | // * logging enabled with `-Dlog`. |
| 130 | // * the --debug-log arg for the scope has been provided | 136 | // * the --debug-log arg for the scope has been provided |
| 131 | if (@enumToInt(level) > @enumToInt(std.log.level) or | 137 | if (@enumToInt(level) > @enumToInt(std.options.log_level) or |
| 132 | @enumToInt(level) > @enumToInt(std.log.Level.info)) | 138 | @enumToInt(level) > @enumToInt(std.log.Level.info)) |
| 133 | { | 139 | { |
| 134 | if (!build_options.enable_logging) return; | 140 | if (!build_options.enable_logging) return; |
test/behavior/pointers.zig+2-2| ... | @@ -509,8 +509,8 @@ test "ptrCast comptime known slice to C pointer" { | ... | @@ -509,8 +509,8 @@ test "ptrCast comptime known slice to C pointer" { |
| 509 | test "ptrToInt on a generic function" { | 509 | test "ptrToInt on a generic function" { |
| 510 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 510 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 511 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 511 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 512 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO | 512 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 513 | if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO | 513 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 514 | 514 | ||
| 515 | const S = struct { | 515 | const S = struct { |
| 516 | fn generic(i: anytype) @TypeOf(i) { | 516 | fn generic(i: anytype) @TypeOf(i) { |
test/compare_output.zig+12-6| ... | @@ -440,11 +440,14 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { | ... | @@ -440,11 +440,14 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 440 | cases.add("std.log per scope log level override", | 440 | cases.add("std.log per scope log level override", |
| 441 | \\const std = @import("std"); | 441 | \\const std = @import("std"); |
| 442 | \\ | 442 | \\ |
| 443 | \\pub const log_level: std.log.Level = .debug; | 443 | \\pub const std_options = struct { |
| 444 | \\ | 444 | \\ pub const log_level: std.log.Level = .debug; |
| 445 | \\pub const scope_levels = [_]std.log.ScopeLevel{ | 445 | \\ |
| 446 | \\ .{ .scope = .a, .level = .warn }, | 446 | \\ pub const log_scope_levels = &[_]std.log.ScopeLevel{ |
| 447 | \\ .{ .scope = .c, .level = .err }, | 447 | \\ .{ .scope = .a, .level = .warn }, |
| 448 | \\ .{ .scope = .c, .level = .err }, | ||
| 449 | \\ }; | ||
| 450 | \\ pub const logFn = log; | ||
| 448 | \\}; | 451 | \\}; |
| 449 | \\ | 452 | \\ |
| 450 | \\const loga = std.log.scoped(.a); | 453 | \\const loga = std.log.scoped(.a); |
| ... | @@ -494,7 +497,10 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { | ... | @@ -494,7 +497,10 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 494 | cases.add("std.heap.LoggingAllocator logs to std.log", | 497 | cases.add("std.heap.LoggingAllocator logs to std.log", |
| 495 | \\const std = @import("std"); | 498 | \\const std = @import("std"); |
| 496 | \\ | 499 | \\ |
| 497 | \\pub const log_level: std.log.Level = .debug; | 500 | \\pub const std_options = struct { |
| 501 | \\ pub const log_level: std.log.Level = .debug; | ||
| 502 | \\ pub const logFn = log; | ||
| 503 | \\}; | ||
| 498 | \\ | 504 | \\ |
| 499 | \\pub fn main() !void { | 505 | \\pub fn main() !void { |
| 500 | \\ var allocator_buf: [10]u8 = undefined; | 506 | \\ var allocator_buf: [10]u8 = undefined; |
test/standalone/issue_7030/main.zig+4| ... | @@ -1,5 +1,9 @@ | ... | @@ -1,5 +1,9 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | 2 | ||
| 3 | pub const std_options = struct { | ||
| 4 | pub const logFn = log; | ||
| 5 | }; | ||
| 6 | |||
| 3 | pub fn log( | 7 | pub fn log( |
| 4 | comptime message_level: std.log.Level, | 8 | comptime message_level: std.log.Level, |
| 5 | comptime scope: @Type(.EnumLiteral), | 9 | comptime scope: @Type(.EnumLiteral), |
test/standalone/issue_9693/main.zig+3-1| ... | @@ -1,2 +1,4 @@ | ... | @@ -1,2 +1,4 @@ |
| 1 | pub const io_mode = .evented; | 1 | pub const std_options = struct { |
| 2 | pub const io_mode = .evented; | ||
| 3 | }; | ||
| 2 | pub fn main() void {} | 4 | pub fn main() void {} |