build runner compiling

This commit is contained in:
Andrew Kelley 2025-02-17 12:22:24 -08:00
parent 716b4489be
commit f3be721785
16 changed files with 195 additions and 205 deletions

View File

@ -2803,7 +2803,7 @@ pub fn dumpBadGetPathHelp(
src_builder: *Build,
asking_step: ?*Step,
) anyerror!void {
var buffered_writer = stderr.unbufferedWriter();
var buffered_writer = stderr.writer().unbuffered();
const w = &buffered_writer;
try w.print(
\\getPath() was called on a GeneratedFile that wasn't built yet.

View File

@ -522,7 +522,8 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
var cwd_cache: ?[]const u8 = null;
var archiver = std.tar.writer(response.writer());
var response_writer = response.writer().unbuffered();
var archiver: std.tar.Writer = .{ .underlying_writer = &response_writer };
for (deduped_paths) |joined_path| {
var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {

View File

@ -287,7 +287,7 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
/// For debugging purposes, prints identifying information about this Step.
pub fn dump(step: *Step, file: std.fs.File) void {
var bw = file.unbufferedWriter();
var bw = file.writer().unbuffered();
const tty_config = std.io.tty.detectConfig(file);
const debug_info = std.debug.getSelfDebugInfo() catch |err| {
bw.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{

View File

@ -55,14 +55,14 @@ fn printType(
switch (T) {
[]const []const u8 => {
if (name) |payload| {
try out.print(gpa, "pub const {}: []const []const u8 = ", .{std.zig.fmtId(payload)});
try out.print(gpa, "pub const {f}: []const []const u8 = ", .{std.zig.fmtId(payload)});
}
try out.appendSlice(gpa, "&[_][]const u8{\n");
for (value) |slice| {
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " \"{}\",\n", .{std.zig.fmtEscapes(slice)});
try out.print(gpa, " \"{f}\",\n", .{std.zig.fmtEscapes(slice)});
}
if (name != null) {
@ -75,7 +75,9 @@ fn printType(
},
[]const u8 => {
if (name) |some| {
try out.print(gpa, "pub const {}: []const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
try out.print(gpa, "pub const {f}: []const u8 = \"{f}\";", .{
std.zig.fmtId(some), std.zig.fmtEscapes(value),
});
} else {
try out.print(gpa, "\"{}\",", .{std.zig.fmtEscapes(value)});
}
@ -293,7 +295,7 @@ fn printEnum(
inline for (val.fields) |field| {
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " {p} = {d},\n", .{ std.zig.fmtId(field.name), field.value });
try out.print(gpa, " {fp} = {d},\n", .{ std.zig.fmtId(field.name), field.value });
}
if (!val.is_exhaustive) {

View File

@ -305,8 +305,8 @@ pub const Os = struct {
ver: WindowsVersion,
comptime fmt_str: []const u8,
_: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
writer: *std.io.BufferedWriter,
) anyerror!void {
const maybe_name = std.enums.tagName(WindowsVersion, ver);
if (comptime std.mem.eql(u8, fmt_str, "s")) {
if (maybe_name) |name|

View File

@ -212,7 +212,7 @@ pub fn unlockStdErr() void {
/// in fact unbuffered and does not need to be flushed.
pub fn lockStdErr2() std.io.BufferedWriter {
std.Progress.lockStdErr();
return io.getStdErr().unbufferedWriter();
return io.getStdErr().writer().unbuffered();
}
/// Print to stderr, unbuffered, and silently returning on failure. Intended
@ -1468,7 +1468,7 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa
}
fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque) void {
var stderr = io.getStdErr().unbufferedWriter();
var stderr = io.getStdErr().writer().unbuffered();
_ = switch (sig) {
posix.SIG.SEGV => if (native_arch == .x86_64 and native_os == .linux and code == 128) // SI_KERNEL
// x86_64 doesn't have a full 64-bit virtual address space.
@ -1564,7 +1564,7 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:
}
fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) void {
var stderr = io.getStdErr().unbufferedWriter();
var stderr = io.getStdErr().writer().unbuffered();
_ = switch (msg) {
0 => stderr.print("{s}\n", .{label.?}),
1 => stderr.print("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}),

View File

@ -853,7 +853,7 @@ pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintErr
/// Count the characters needed for format.
pub fn count(comptime fmt: []const u8, args: anytype) u64 {
var counting_writer: std.io.CountingWriter = .{ .child_writer = std.io.null_writer };
var bw = counting_writer.unbufferedWriter();
var bw = counting_writer.writer().unbuffered();
bw.print(fmt, args) catch unreachable;
return counting_writer.bytes_written;
}

View File

@ -1602,13 +1602,6 @@ pub fn writer(file: File) std.io.Writer {
};
}
pub fn unbufferedWriter(file: File) std.io.BufferedWriter {
return .{
.buffer = &.{},
.unbuffered_writer = writer(file),
};
}
const interface = struct {
/// Number of slices to store on the stack, when trying to send as many byte
/// vectors through the underlying write calls as possible.

View File

@ -620,13 +620,14 @@ pub fn printValue(
}
if (std.meta.hasMethod(T, "format")) {
if (fmt.len == 0) {
// @deprecated()
// After 0.14.0 is tagged, uncomment this next line:
//@compileError("ambiguous format string; specify {f} to call print method, or {any} to skip it");
return value.format(fmt, options, bw);
} else if (fmt[0] == 'f') {
if (fmt.len > 0 and fmt[0] == 'f') {
return value.format(fmt[1..], options, bw);
} else {
//@deprecated();
// After 0.14.0 is tagged, uncomment this next line:
//@compileError("ambiguous format string; specify {f} to call format method, or {any} to skip it");
//and then delete the `hasMethod` condition
return value.format(fmt, options, bw);
}
}

View File

@ -22,13 +22,6 @@ pub fn writer(cw: *CountingWriter) Writer {
};
}
pub fn unbufferedWriter(cw: *CountingWriter) std.io.BufferedWriter {
return .{
.buffer = &.{},
.unbuffered_writer = writer(cw),
};
}
fn passthru_writeSplat(context: *anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
const cw: *CountingWriter = @alignCast(@ptrCast(context));
const n = try cw.child_writer.writeSplat(data, splat);
@ -52,7 +45,7 @@ fn passthru_writeFile(
test CountingWriter {
var cw: CountingWriter = .{ .child_writer = std.io.null_writer };
var bw = cw.unbufferedWriter();
var bw = cw.writer().unbuffered();
const bytes = "yay";
try bw.writeAll(bytes);
try testing.expect(cw.bytes_written == bytes.len);

View File

@ -86,12 +86,6 @@ pub fn writeAll(w: Writer, bytes: []const u8) anyerror!void {
while (index < bytes.len) index += try w.vtable.writeSplat(w.context, &.{bytes[index..]}, 1);
}
///// Directly calls `writeAll` many times to render the formatted text. To
///// enable buffering, call `std.io.BufferedWriter.print` instead.
//pub fn unbufferedPrint(w: Writer, comptime format: []const u8, args: anytype) anyerror!void {
// return std.fmt.format(w, format, args);
//}
/// The `data` parameter is mutable because this function needs to mutate the
/// fields in order to handle partial writes from `VTable.writev`.
pub fn writevAll(w: Writer, data: [][]const u8) anyerror!void {
@ -106,3 +100,10 @@ pub fn writevAll(w: Writer, data: [][]const u8) anyerror!void {
data[i] = data[i][n..];
}
}
pub fn unbuffered(w: Writer) std.io.BufferedWriter {
return .{
.buffer = &.{},
.unbuffered_writer = w,
};
}

View File

@ -1004,7 +1004,7 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
fn writeIntFd(fd: i32, value: ErrInt) !void {
const file: File = .{ .handle = fd };
var bw = file.unbufferedWriter();
var bw = file.writer().unbuffered();
bw.writeInt(u64, @intCast(value), .little) catch return error.SystemResources;
}

View File

@ -19,7 +19,7 @@ const std = @import("std");
const assert = std.debug.assert;
const testing = std.testing;
pub const writer = @import("tar/writer.zig").writer;
pub const Writer = @import("tar/Writer.zig");
/// Provide this to receive detailed error messages.
/// When this is provided, some errors which would otherwise be returned
@ -604,7 +604,7 @@ fn PaxIterator(comptime ReaderType: type) type {
}
fn readUntil(self: *Self, delimiter: u8) ![]const u8 {
var fbs = std.io.fixedBufferStream(&self.scratch);
var fbs: std.io.FixedBufferStream = .{ .buffer = &self.scratch };
try self.reader.streamUntilDelimiter(fbs.writer(), delimiter, null);
return fbs.getWritten();
}
@ -855,7 +855,7 @@ test PaxIterator {
test {
_ = @import("tar/test.zig");
_ = @import("tar/writer.zig");
_ = Writer;
_ = Diagnostics;
}

View File

@ -1,177 +1,176 @@
const std = @import("std");
const assert = std.debug.assert;
const testing = std.testing;
const Writer = @This();
pub const Writer = struct {
const block_size = @sizeOf(Header);
const empty_block: [block_size]u8 = [_]u8{0} ** block_size;
const block_size = @sizeOf(Header);
const empty_block: [block_size]u8 = [_]u8{0} ** block_size;
/// Options for writing file/dir/link. If left empty 0o664 is used for
/// file mode and current time for mtime.
pub const Options = struct {
/// File system permission mode.
mode: u32 = 0,
/// File system modification time.
mtime: u64 = 0,
};
const Self = @This();
/// Options for writing file/dir/link. If left empty 0o664 is used for
/// file mode and current time for mtime.
pub const Options = struct {
/// File system permission mode.
mode: u32 = 0,
/// File system modification time.
mtime: u64 = 0,
};
const Self = @This();
underlying_writer: *std.io.BufferedWriter,
prefix: []const u8 = "",
mtime_now: u64 = 0,
underlying_writer: *std.io.BufferedWriter,
prefix: []const u8 = "",
mtime_now: u64 = 0,
/// Sets prefix for all other write* method paths.
pub fn setRoot(self: *Self, root: []const u8) !void {
if (root.len > 0)
try self.writeDir(root, .{});
/// Sets prefix for all other write* method paths.
pub fn setRoot(self: *Self, root: []const u8) !void {
if (root.len > 0)
try self.writeDir(root, .{});
self.prefix = root;
self.prefix = root;
}
/// Writes directory.
pub fn writeDir(self: *Self, sub_path: []const u8, opt: Options) !void {
try self.writeHeader(.directory, sub_path, "", 0, opt);
}
/// Writes file system file.
pub fn writeFile(self: *Self, sub_path: []const u8, file: std.fs.File) !void {
const stat = try file.stat();
const mtime: u64 = @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
var header = Header{};
try self.setPath(&header, sub_path);
try header.setSize(stat.size);
try header.setMtime(mtime);
try header.write(self.underlying_writer);
try self.underlying_writer.writeFileAll(file, .{ .len = .init(stat.size) });
try self.writePadding(stat.size);
}
/// Writes file reading file content from `reader`. Number of bytes in
/// reader must be equal to `size`.
pub fn writeFileStream(self: *Self, sub_path: []const u8, size: usize, reader: anytype, opt: Options) !void {
try self.writeHeader(.regular, sub_path, "", @intCast(size), opt);
var counting_reader = std.io.countingReader(reader);
var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
try fifo.pump(counting_reader.reader(), self.underlying_writer);
if (counting_reader.bytes_read != size) return error.WrongReaderSize;
try self.writePadding(size);
}
/// Writes file using bytes buffer `content` for size and file content.
pub fn writeFileBytes(self: *Self, sub_path: []const u8, content: []const u8, opt: Options) !void {
try self.writeHeader(.regular, sub_path, "", @intCast(content.len), opt);
try self.underlying_writer.writeAll(content);
try self.writePadding(content.len);
}
/// Writes symlink.
pub fn writeLink(self: *Self, sub_path: []const u8, link_name: []const u8, opt: Options) !void {
try self.writeHeader(.symbolic_link, sub_path, link_name, 0, opt);
}
/// Writes fs.Dir.WalkerEntry. Uses `mtime` from file system entry and
/// default for entry mode .
pub fn writeEntry(self: *Self, entry: std.fs.Dir.Walker.Entry) !void {
switch (entry.kind) {
.directory => {
try self.writeDir(entry.path, .{ .mtime = try entryMtime(entry) });
},
.file => {
var file = try entry.dir.openFile(entry.basename, .{});
defer file.close();
try self.writeFile(entry.path, file);
},
.sym_link => {
var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
const link_name = try entry.dir.readLink(entry.basename, &link_name_buffer);
try self.writeLink(entry.path, link_name, .{ .mtime = try entryMtime(entry) });
},
else => {
return error.UnsupportedWalkerEntryKind;
},
}
}
/// Writes directory.
pub fn writeDir(self: *Self, sub_path: []const u8, opt: Options) !void {
try self.writeHeader(.directory, sub_path, "", 0, opt);
}
/// Writes file system file.
pub fn writeFile(self: *Self, sub_path: []const u8, file: std.fs.File) !void {
const stat = try file.stat();
const mtime: u64 = @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
var header = Header{};
try self.setPath(&header, sub_path);
try header.setSize(stat.size);
try header.setMtime(mtime);
try header.write(self.underlying_writer);
try self.underlying_writer.writeFileAll(file, .{ .len = .init(stat.size) });
try self.writePadding(stat.size);
}
/// Writes file reading file content from `reader`. Number of bytes in
/// reader must be equal to `size`.
pub fn writeFileStream(self: *Self, sub_path: []const u8, size: usize, reader: anytype, opt: Options) !void {
try self.writeHeader(.regular, sub_path, "", @intCast(size), opt);
var counting_reader = std.io.countingReader(reader);
var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
try fifo.pump(counting_reader.reader(), self.underlying_writer);
if (counting_reader.bytes_read != size) return error.WrongReaderSize;
try self.writePadding(size);
}
/// Writes file using bytes buffer `content` for size and file content.
pub fn writeFileBytes(self: *Self, sub_path: []const u8, content: []const u8, opt: Options) !void {
try self.writeHeader(.regular, sub_path, "", @intCast(content.len), opt);
try self.underlying_writer.writeAll(content);
try self.writePadding(content.len);
}
/// Writes symlink.
pub fn writeLink(self: *Self, sub_path: []const u8, link_name: []const u8, opt: Options) !void {
try self.writeHeader(.symbolic_link, sub_path, link_name, 0, opt);
}
/// Writes fs.Dir.WalkerEntry. Uses `mtime` from file system entry and
/// default for entry mode .
pub fn writeEntry(self: *Self, entry: std.fs.Dir.Walker.Entry) !void {
switch (entry.kind) {
.directory => {
try self.writeDir(entry.path, .{ .mtime = try entryMtime(entry) });
},
.file => {
var file = try entry.dir.openFile(entry.basename, .{});
defer file.close();
try self.writeFile(entry.path, file);
},
.sym_link => {
var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
const link_name = try entry.dir.readLink(entry.basename, &link_name_buffer);
try self.writeLink(entry.path, link_name, .{ .mtime = try entryMtime(entry) });
},
else => {
return error.UnsupportedWalkerEntryKind;
},
}
}
fn writeHeader(
self: *Self,
typeflag: Header.FileType,
sub_path: []const u8,
link_name: []const u8,
size: u64,
opt: Options,
) !void {
var header = Header.init(typeflag);
try self.setPath(&header, sub_path);
try header.setSize(size);
try header.setMtime(if (opt.mtime != 0) opt.mtime else self.mtimeNow());
if (opt.mode != 0)
try header.setMode(opt.mode);
if (typeflag == .symbolic_link)
header.setLinkname(link_name) catch |err| switch (err) {
error.NameTooLong => try self.writeExtendedHeader(.gnu_long_link, &.{link_name}),
else => return err,
};
try header.write(self.underlying_writer);
}
fn mtimeNow(self: *Self) u64 {
if (self.mtime_now == 0)
self.mtime_now = @intCast(std.time.timestamp());
return self.mtime_now;
}
fn entryMtime(entry: std.fs.Dir.Walker.Entry) !u64 {
const stat = try entry.dir.statFile(entry.basename);
return @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
}
/// Writes path in posix header, if don't fit (in name+prefix; 100+155
/// bytes) writes it in gnu extended header.
fn setPath(self: *Self, header: *Header, sub_path: []const u8) !void {
header.setPath(self.prefix, sub_path) catch |err| switch (err) {
error.NameTooLong => {
// write extended header
const buffers: []const []const u8 = if (self.prefix.len == 0)
&.{sub_path}
else
&.{ self.prefix, "/", sub_path };
try self.writeExtendedHeader(.gnu_long_name, buffers);
},
fn writeHeader(
self: *Self,
typeflag: Header.FileType,
sub_path: []const u8,
link_name: []const u8,
size: u64,
opt: Options,
) !void {
var header = Header.init(typeflag);
try self.setPath(&header, sub_path);
try header.setSize(size);
try header.setMtime(if (opt.mtime != 0) opt.mtime else self.mtimeNow());
if (opt.mode != 0)
try header.setMode(opt.mode);
if (typeflag == .symbolic_link)
header.setLinkname(link_name) catch |err| switch (err) {
error.NameTooLong => try self.writeExtendedHeader(.gnu_long_link, &.{link_name}),
else => return err,
};
}
try header.write(self.underlying_writer);
}
/// Writes gnu extended header: gnu_long_name or gnu_long_link.
fn writeExtendedHeader(self: *Self, typeflag: Header.FileType, buffers: []const []const u8) !void {
var len: usize = 0;
for (buffers) |buf|
len += buf.len;
fn mtimeNow(self: *Self) u64 {
if (self.mtime_now == 0)
self.mtime_now = @intCast(std.time.timestamp());
return self.mtime_now;
}
var header = Header.init(typeflag);
try header.setSize(len);
try header.write(self.underlying_writer);
for (buffers) |buf|
try self.underlying_writer.writeAll(buf);
try self.writePadding(len);
}
fn entryMtime(entry: std.fs.Dir.Walker.Entry) !u64 {
const stat = try entry.dir.statFile(entry.basename);
return @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
}
fn writePadding(self: *Self, bytes: u64) !void {
const pos: usize = @intCast(bytes % block_size);
if (pos == 0) return;
try self.underlying_writer.writeAll(empty_block[pos..]);
}
/// Writes path in posix header, if don't fit (in name+prefix; 100+155
/// bytes) writes it in gnu extended header.
fn setPath(self: *Self, header: *Header, sub_path: []const u8) !void {
header.setPath(self.prefix, sub_path) catch |err| switch (err) {
error.NameTooLong => {
// write extended header
const buffers: []const []const u8 = if (self.prefix.len == 0)
&.{sub_path}
else
&.{ self.prefix, "/", sub_path };
try self.writeExtendedHeader(.gnu_long_name, buffers);
},
else => return err,
};
}
/// Tar should finish with two zero blocks, but 'reasonable system must
/// not assume that such a block exists when reading an archive' (from
/// reference). In practice it is safe to skip this finish.
pub fn finish(self: *Self) !void {
try self.underlying_writer.writeAll(&empty_block);
try self.underlying_writer.writeAll(&empty_block);
}
};
/// Writes gnu extended header: gnu_long_name or gnu_long_link.
fn writeExtendedHeader(self: *Self, typeflag: Header.FileType, buffers: []const []const u8) !void {
var len: usize = 0;
for (buffers) |buf|
len += buf.len;
var header = Header.init(typeflag);
try header.setSize(len);
try header.write(self.underlying_writer);
for (buffers) |buf|
try self.underlying_writer.writeAll(buf);
try self.writePadding(len);
}
fn writePadding(self: *Self, bytes: u64) !void {
const pos: usize = @intCast(bytes % block_size);
if (pos == 0) return;
try self.underlying_writer.writeAll(empty_block[pos..]);
}
/// Tar should finish with two zero blocks, but 'reasonable system must
/// not assume that such a block exists when reading an archive' (from
/// reference). In practice it is safe to skip this finish.
pub fn finish(self: *Self) !void {
try self.underlying_writer.writeAll(&empty_block);
try self.underlying_writer.writeAll(&empty_block);
}
/// A struct that is exactly 512 bytes and matches tar file format. This is
/// intended to be used for outputting tar files; for parsing there is
@ -320,7 +319,7 @@ const Header = extern struct {
assert(@sizeOf(Header) == 512);
}
test setPath {
test "setPath" {
const cases = [_]struct {
in: []const []const u8,
out: []const []const u8,

View File

@ -416,7 +416,7 @@ fn formatId(
bytes: []const u8,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
writer: *std.io.BufferedWriter,
) !void {
const allow_primitive, const allow_underscore = comptime parse_fmt: {
var allow_primitive = false;

View File

@ -194,7 +194,7 @@ fn renderErrorMessageToWriter(
) anyerror!void {
const ttyconf = options.ttyconf;
var counting_writer: std.io.CountingWriter = .{ .child_writer = bw.writer() };
var counting_bw = counting_writer.unbufferedWriter();
var counting_bw = counting_writer.writer().unbuffered();
const err_msg = eb.getErrorMessage(err_msg_index);
if (err_msg.src_loc != .none) {
const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));