mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Report the progress of lazily building zig rc
jitCmd now takes a `server` option that will emit progress/errors via std.zig.Server when enabled.
This commit is contained in:
parent
dc4b05894d
commit
8799f7466d
@ -46,6 +46,12 @@ pub fn main() !void {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (zig_integration) {
|
||||||
|
// Send progress with an empty string to indicate that the building of the
|
||||||
|
// resinator binary is finished and we've moved on to actually compiling the .rc file
|
||||||
|
try error_handler.server.serveStringMessage(.progress, "");
|
||||||
|
}
|
||||||
|
|
||||||
var options = options: {
|
var options = options: {
|
||||||
var cli_diagnostics = cli.Diagnostics.init(allocator);
|
var cli_diagnostics = cli.Diagnostics.init(allocator);
|
||||||
defer cli_diagnostics.deinit();
|
defer cli_diagnostics.deinit();
|
||||||
|
|||||||
@ -4841,6 +4841,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
|
|||||||
try argv.appendSlice(&.{
|
try argv.appendSlice(&.{
|
||||||
self_exe_path,
|
self_exe_path,
|
||||||
"rc",
|
"rc",
|
||||||
|
"--zig-integration",
|
||||||
"/:no-preprocess",
|
"/:no-preprocess",
|
||||||
"/x", // ignore INCLUDE environment variable
|
"/x", // ignore INCLUDE environment variable
|
||||||
"/c65001", // UTF-8 codepage
|
"/c65001", // UTF-8 codepage
|
||||||
@ -4849,31 +4850,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
|
|||||||
});
|
});
|
||||||
try argv.appendSlice(&.{ "--", in_rc_path, out_res_path });
|
try argv.appendSlice(&.{ "--", in_rc_path, out_res_path });
|
||||||
|
|
||||||
var child = std.ChildProcess.init(argv.items, arena);
|
try spawnZigRc(comp, win32_resource, src_basename, arena, argv.items, &child_progress_node);
|
||||||
child.stdin_behavior = .Ignore;
|
|
||||||
child.stdout_behavior = .Ignore;
|
|
||||||
child.stderr_behavior = .Pipe;
|
|
||||||
|
|
||||||
try child.spawn();
|
|
||||||
|
|
||||||
const stderr_reader = child.stderr.?.reader();
|
|
||||||
const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024);
|
|
||||||
const term = child.wait() catch |err| {
|
|
||||||
return comp.failWin32Resource(win32_resource, "unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (term) {
|
|
||||||
.Exited => |code| {
|
|
||||||
if (code != 0) {
|
|
||||||
log.err("zig rc failed with stderr:\n{s}", .{stderr});
|
|
||||||
return comp.failWin32Resource(win32_resource, "zig rc exited with code {d}", .{code});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
log.err("zig rc terminated with stderr:\n{s}", .{stderr});
|
|
||||||
return comp.failWin32Resource(win32_resource, "zig rc terminated unexpectedly", .{});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
break :blk digest;
|
break :blk digest;
|
||||||
};
|
};
|
||||||
@ -4941,79 +4918,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
|
|||||||
try argv.appendSlice(rc_src.extra_flags);
|
try argv.appendSlice(rc_src.extra_flags);
|
||||||
try argv.appendSlice(&.{ "--", rc_src.src_path, out_res_path });
|
try argv.appendSlice(&.{ "--", rc_src.src_path, out_res_path });
|
||||||
|
|
||||||
{
|
try spawnZigRc(comp, win32_resource, src_basename, arena, argv.items, &child_progress_node);
|
||||||
var child = std.ChildProcess.init(argv.items, arena);
|
|
||||||
child.stdin_behavior = .Ignore;
|
|
||||||
child.stdout_behavior = .Pipe;
|
|
||||||
child.stderr_behavior = .Pipe;
|
|
||||||
|
|
||||||
child.spawn() catch |err| {
|
|
||||||
return comp.failWin32Resource(win32_resource, "unable to spawn {s} rc: {s}", .{ argv.items[0], @errorName(err) });
|
|
||||||
};
|
|
||||||
|
|
||||||
var poller = std.io.poll(comp.gpa, enum { stdout }, .{
|
|
||||||
.stdout = child.stdout.?,
|
|
||||||
});
|
|
||||||
defer poller.deinit();
|
|
||||||
|
|
||||||
const stdout = poller.fifo(.stdout);
|
|
||||||
|
|
||||||
poll: while (true) {
|
|
||||||
while (stdout.readableLength() < @sizeOf(std.zig.Server.Message.Header)) {
|
|
||||||
if (!(try poller.poll())) break :poll;
|
|
||||||
}
|
|
||||||
const header = stdout.reader().readStruct(std.zig.Server.Message.Header) catch unreachable;
|
|
||||||
while (stdout.readableLength() < header.bytes_len) {
|
|
||||||
if (!(try poller.poll())) break :poll;
|
|
||||||
}
|
|
||||||
const body = stdout.readableSliceOfLen(header.bytes_len);
|
|
||||||
|
|
||||||
switch (header.tag) {
|
|
||||||
// We expect exactly one ErrorBundle, and if any error_bundle header is
|
|
||||||
// sent then it's a fatal error.
|
|
||||||
.error_bundle => {
|
|
||||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
|
||||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
|
||||||
const extra_bytes =
|
|
||||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
|
||||||
const string_bytes =
|
|
||||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
|
||||||
const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes);
|
|
||||||
const extra_array = try comp.gpa.alloc(u32, unaligned_extra.len);
|
|
||||||
@memcpy(extra_array, unaligned_extra);
|
|
||||||
const error_bundle = .{
|
|
||||||
.string_bytes = try comp.gpa.dupe(u8, string_bytes),
|
|
||||||
.extra = extra_array,
|
|
||||||
};
|
|
||||||
return comp.failWin32ResourceWithOwnedBundle(win32_resource, error_bundle);
|
|
||||||
},
|
|
||||||
else => {}, // ignore other messages
|
|
||||||
}
|
|
||||||
|
|
||||||
stdout.discard(body.len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Just in case there's a failure that didn't send an ErrorBundle (e.g. an error return trace)
|
|
||||||
const stderr_reader = child.stderr.?.reader();
|
|
||||||
const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024);
|
|
||||||
|
|
||||||
const term = child.wait() catch |err| {
|
|
||||||
return comp.failWin32Resource(win32_resource, "unable to wait for {s} rc: {s}", .{ argv.items[0], @errorName(err) });
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (term) {
|
|
||||||
.Exited => |code| {
|
|
||||||
if (code != 0) {
|
|
||||||
log.err("zig rc failed with stderr:\n{s}", .{stderr});
|
|
||||||
return comp.failWin32Resource(win32_resource, "zig rc exited with code {d}", .{code});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
log.err("zig rc terminated with stderr:\n{s}", .{stderr});
|
|
||||||
return comp.failWin32Resource(win32_resource, "zig rc terminated unexpectedly", .{});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read depfile and update cache manifest
|
// Read depfile and update cache manifest
|
||||||
{
|
{
|
||||||
@ -5079,6 +4984,100 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn spawnZigRc(
|
||||||
|
comp: *Compilation,
|
||||||
|
win32_resource: *Win32Resource,
|
||||||
|
src_basename: []const u8,
|
||||||
|
arena: Allocator,
|
||||||
|
argv: []const []const u8,
|
||||||
|
child_progress_node: *std.Progress.Node,
|
||||||
|
) !void {
|
||||||
|
var node_name: std.ArrayListUnmanaged(u8) = .{};
|
||||||
|
defer node_name.deinit(arena);
|
||||||
|
|
||||||
|
var child = std.ChildProcess.init(argv, arena);
|
||||||
|
child.stdin_behavior = .Ignore;
|
||||||
|
child.stdout_behavior = .Pipe;
|
||||||
|
child.stderr_behavior = .Pipe;
|
||||||
|
|
||||||
|
child.spawn() catch |err| {
|
||||||
|
return comp.failWin32Resource(win32_resource, "unable to spawn {s} rc: {s}", .{ argv[0], @errorName(err) });
|
||||||
|
};
|
||||||
|
|
||||||
|
var poller = std.io.poll(comp.gpa, enum { stdout }, .{
|
||||||
|
.stdout = child.stdout.?,
|
||||||
|
});
|
||||||
|
defer poller.deinit();
|
||||||
|
|
||||||
|
const stdout = poller.fifo(.stdout);
|
||||||
|
|
||||||
|
poll: while (true) {
|
||||||
|
while (stdout.readableLength() < @sizeOf(std.zig.Server.Message.Header)) {
|
||||||
|
if (!(try poller.poll())) break :poll;
|
||||||
|
}
|
||||||
|
const header = stdout.reader().readStruct(std.zig.Server.Message.Header) catch unreachable;
|
||||||
|
while (stdout.readableLength() < header.bytes_len) {
|
||||||
|
if (!(try poller.poll())) break :poll;
|
||||||
|
}
|
||||||
|
const body = stdout.readableSliceOfLen(header.bytes_len);
|
||||||
|
|
||||||
|
switch (header.tag) {
|
||||||
|
// We expect exactly one ErrorBundle, and if any error_bundle header is
|
||||||
|
// sent then it's a fatal error.
|
||||||
|
.error_bundle => {
|
||||||
|
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
||||||
|
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
||||||
|
const extra_bytes =
|
||||||
|
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
||||||
|
const string_bytes =
|
||||||
|
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
||||||
|
const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes);
|
||||||
|
const extra_array = try comp.gpa.alloc(u32, unaligned_extra.len);
|
||||||
|
@memcpy(extra_array, unaligned_extra);
|
||||||
|
const error_bundle = std.zig.ErrorBundle{
|
||||||
|
.string_bytes = try comp.gpa.dupe(u8, string_bytes),
|
||||||
|
.extra = extra_array,
|
||||||
|
};
|
||||||
|
return comp.failWin32ResourceWithOwnedBundle(win32_resource, error_bundle);
|
||||||
|
},
|
||||||
|
.progress => {
|
||||||
|
node_name.clearRetainingCapacity();
|
||||||
|
if (body.len > 0) {
|
||||||
|
try node_name.appendSlice(arena, "build 'zig rc'... ");
|
||||||
|
try node_name.appendSlice(arena, body);
|
||||||
|
child_progress_node.setName(node_name.items);
|
||||||
|
} else {
|
||||||
|
child_progress_node.setName(src_basename);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {}, // ignore other messages
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout.discard(body.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just in case there's a failure that didn't send an ErrorBundle (e.g. an error return trace)
|
||||||
|
const stderr_reader = child.stderr.?.reader();
|
||||||
|
const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024);
|
||||||
|
|
||||||
|
const term = child.wait() catch |err| {
|
||||||
|
return comp.failWin32Resource(win32_resource, "unable to wait for {s} rc: {s}", .{ argv[0], @errorName(err) });
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (term) {
|
||||||
|
.Exited => |code| {
|
||||||
|
if (code != 0) {
|
||||||
|
log.err("zig rc failed with stderr:\n{s}", .{stderr});
|
||||||
|
return comp.failWin32Resource(win32_resource, "zig rc exited with code {d}", .{code});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
log.err("zig rc terminated with stderr:\n{s}", .{stderr});
|
||||||
|
return comp.failWin32Resource(win32_resource, "zig rc terminated unexpectedly", .{});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tmpFilePath(comp: *Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
|
pub fn tmpFilePath(comp: *Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
|
||||||
const s = std.fs.path.sep_str;
|
const s = std.fs.path.sep_str;
|
||||||
const rand_int = std.crypto.random.int(u64);
|
const rand_int = std.crypto.random.int(u64);
|
||||||
|
|||||||
54
src/main.zig
54
src/main.zig
@ -291,11 +291,13 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
|||||||
} else if (mem.eql(u8, cmd, "translate-c")) {
|
} else if (mem.eql(u8, cmd, "translate-c")) {
|
||||||
return buildOutputType(gpa, arena, args, .translate_c);
|
return buildOutputType(gpa, arena, args, .translate_c);
|
||||||
} else if (mem.eql(u8, cmd, "rc")) {
|
} else if (mem.eql(u8, cmd, "rc")) {
|
||||||
|
const use_server = cmd_args.len > 0 and std.mem.eql(u8, cmd_args[0], "--zig-integration");
|
||||||
return jitCmd(gpa, arena, cmd_args, .{
|
return jitCmd(gpa, arena, cmd_args, .{
|
||||||
.cmd_name = "resinator",
|
.cmd_name = "resinator",
|
||||||
.root_src_path = "resinator/main.zig",
|
.root_src_path = "resinator/main.zig",
|
||||||
.depend_on_aro = true,
|
.depend_on_aro = true,
|
||||||
.prepend_zig_lib_dir_path = true,
|
.prepend_zig_lib_dir_path = true,
|
||||||
|
.server = use_server,
|
||||||
});
|
});
|
||||||
} else if (mem.eql(u8, cmd, "fmt")) {
|
} else if (mem.eql(u8, cmd, "fmt")) {
|
||||||
return jitCmd(gpa, arena, cmd_args, .{
|
return jitCmd(gpa, arena, cmd_args, .{
|
||||||
@ -5304,6 +5306,8 @@ const JitCmdOptions = struct {
|
|||||||
prepend_zig_exe_path: bool = false,
|
prepend_zig_exe_path: bool = false,
|
||||||
depend_on_aro: bool = false,
|
depend_on_aro: bool = false,
|
||||||
capture: ?*[]u8 = null,
|
capture: ?*[]u8 = null,
|
||||||
|
/// Send progress and error bundles via std.zig.Server over stdout
|
||||||
|
server: bool = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn jitCmd(
|
fn jitCmd(
|
||||||
@ -5449,10 +5453,52 @@ fn jitCmd(
|
|||||||
};
|
};
|
||||||
defer comp.destroy();
|
defer comp.destroy();
|
||||||
|
|
||||||
updateModule(comp, color) catch |err| switch (err) {
|
if (options.server and !builtin.single_threaded) {
|
||||||
error.SemanticAnalyzeFail => process.exit(2),
|
var reset: std.Thread.ResetEvent = .{};
|
||||||
else => |e| return e,
|
var progress: std.Progress = .{
|
||||||
};
|
.terminal = null,
|
||||||
|
.root = .{
|
||||||
|
.context = undefined,
|
||||||
|
.parent = null,
|
||||||
|
.name = "",
|
||||||
|
.unprotected_estimated_total_items = 0,
|
||||||
|
.unprotected_completed_items = 0,
|
||||||
|
},
|
||||||
|
.columns_written = 0,
|
||||||
|
.prev_refresh_timestamp = 0,
|
||||||
|
.timer = null,
|
||||||
|
.done = false,
|
||||||
|
};
|
||||||
|
const main_progress_node = &progress.root;
|
||||||
|
main_progress_node.context = &progress;
|
||||||
|
var server = std.zig.Server{
|
||||||
|
.out = std.io.getStdOut(),
|
||||||
|
.in = undefined, // won't be receiving messages
|
||||||
|
.receive_fifo = undefined, // won't be receiving messages
|
||||||
|
};
|
||||||
|
|
||||||
|
var progress_thread = try std.Thread.spawn(.{}, progressThread, .{
|
||||||
|
&progress, &server, &reset,
|
||||||
|
});
|
||||||
|
defer {
|
||||||
|
reset.set();
|
||||||
|
progress_thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
try comp.update(main_progress_node);
|
||||||
|
|
||||||
|
var error_bundle = try comp.getAllErrorsAlloc();
|
||||||
|
defer error_bundle.deinit(comp.gpa);
|
||||||
|
if (error_bundle.errorMessageCount() > 0) {
|
||||||
|
try server.serveErrorBundle(error_bundle);
|
||||||
|
process.exit(2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updateModule(comp, color) catch |err| switch (err) {
|
||||||
|
error.SemanticAnalyzeFail => process.exit(2),
|
||||||
|
else => |e| return e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const exe_path = try global_cache_directory.join(arena, &.{comp.cache_use.whole.bin_sub_path.?});
|
const exe_path = try global_cache_directory.join(arena, &.{comp.cache_use.whole.bin_sub_path.?});
|
||||||
child_argv.appendAssumeCapacity(exe_path);
|
child_argv.appendAssumeCapacity(exe_path);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user