| ... | @@ -4841,6 +4841,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 | ... | @@ -4841,6 +4841,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 4841 | try argv.appendSlice(&.{ | 4841 | try argv.appendSlice(&.{ |
| 4842 | self_exe_path, | 4842 | self_exe_path, |
| 4843 | "rc", | 4843 | "rc", |
| | 4844 | "--zig-integration", |
| 4844 | "/:no-preprocess", | 4845 | "/:no-preprocess", |
| 4845 | "/x", // ignore INCLUDE environment variable | 4846 | "/x", // ignore INCLUDE environment variable |
| 4846 | "/c65001", // UTF-8 codepage | 4847 | "/c65001", // UTF-8 codepage |
| ... | @@ -4849,31 +4850,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 | ... | @@ -4849,31 +4850,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 4849 | }); | 4850 | }); |
| 4850 | try argv.appendSlice(&.{ "--", in_rc_path, out_res_path }); | 4851 | try argv.appendSlice(&.{ "--", in_rc_path, out_res_path }); |
| 4851 | | 4852 | |
| 4852 | var child = std.ChildProcess.init(argv.items, arena); | 4853 | try spawnZigRc(comp, win32_resource, src_basename, arena, argv.items, &child_progress_node); |
| 4853 | child.stdin_behavior = .Ignore; | | |
| 4854 | child.stdout_behavior = .Ignore; | | |
| 4855 | child.stderr_behavior = .Pipe; | | |
| 4856 | | | |
| 4857 | try child.spawn(); | | |
| 4858 | | | |
| 4859 | const stderr_reader = child.stderr.?.reader(); | | |
| 4860 | const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024); | | |
| 4861 | const term = child.wait() catch |err| { | | |
| 4862 | return comp.failWin32Resource(win32_resource, "unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) }); | | |
| 4863 | }; | | |
| 4864 | | | |
| 4865 | switch (term) { | | |
| 4866 | .Exited => |code| { | | |
| 4867 | if (code != 0) { | | |
| 4868 | log.err("zig rc failed with stderr:\n{s}", .{stderr}); | | |
| 4869 | return comp.failWin32Resource(win32_resource, "zig rc exited with code {d}", .{code}); | | |
| 4870 | } | | |
| 4871 | }, | | |
| 4872 | else => { | | |
| 4873 | log.err("zig rc terminated with stderr:\n{s}", .{stderr}); | | |
| 4874 | return comp.failWin32Resource(win32_resource, "zig rc terminated unexpectedly", .{}); | | |
| 4875 | }, | | |
| 4876 | } | | |
| 4877 | | 4854 | |
| 4878 | break :blk digest; | 4855 | break :blk digest; |
| 4879 | }; | 4856 | }; |
| ... | @@ -4941,79 +4918,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 | ... | @@ -4941,79 +4918,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 4941 | try argv.appendSlice(rc_src.extra_flags); | 4918 | try argv.appendSlice(rc_src.extra_flags); |
| 4942 | try argv.appendSlice(&.{ "--", rc_src.src_path, out_res_path }); | 4919 | try argv.appendSlice(&.{ "--", rc_src.src_path, out_res_path }); |
| 4943 | | 4920 | |
| 4944 | { | 4921 | try spawnZigRc(comp, win32_resource, src_basename, arena, argv.items, &child_progress_node); |
| 4945 | var child = std.ChildProcess.init(argv.items, arena); | | |
| 4946 | child.stdin_behavior = .Ignore; | | |
| 4947 | child.stdout_behavior = .Pipe; | | |
| 4948 | child.stderr_behavior = .Pipe; | | |
| 4949 | | | |
| 4950 | child.spawn() catch |err| { | | |
| 4951 | return comp.failWin32Resource(win32_resource, "unable to spawn {s} rc: {s}", .{ argv.items[0], @errorName(err) }); | | |
| 4952 | }; | | |
| 4953 | | | |
| 4954 | var poller = std.io.poll(comp.gpa, enum { stdout }, .{ | | |
| 4955 | .stdout = child.stdout.?, | | |
| 4956 | }); | | |
| 4957 | defer poller.deinit(); | | |
| 4958 | | | |
| 4959 | const stdout = poller.fifo(.stdout); | | |
| 4960 | | | |
| 4961 | poll: while (true) { | | |
| 4962 | while (stdout.readableLength() < @sizeOf(std.zig.Server.Message.Header)) { | | |
| 4963 | if (!(try poller.poll())) break :poll; | | |
| 4964 | } | | |
| 4965 | const header = stdout.reader().readStruct(std.zig.Server.Message.Header) catch unreachable; | | |
| 4966 | while (stdout.readableLength() < header.bytes_len) { | | |
| 4967 | if (!(try poller.poll())) break :poll; | | |
| 4968 | } | | |
| 4969 | const body = stdout.readableSliceOfLen(header.bytes_len); | | |
| 4970 | | | |
| 4971 | switch (header.tag) { | | |
| 4972 | // We expect exactly one ErrorBundle, and if any error_bundle header is | | |
| 4973 | // sent then it's a fatal error. | | |
| 4974 | .error_bundle => { | | |
| 4975 | const EbHdr = std.zig.Server.Message.ErrorBundle; | | |
| 4976 | const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body)); | | |
| 4977 | const extra_bytes = | | |
| 4978 | body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len]; | | |
| 4979 | const string_bytes = | | |
| 4980 | body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len]; | | |
| 4981 | const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes); | | |
| 4982 | const extra_array = try comp.gpa.alloc(u32, unaligned_extra.len); | | |
| 4983 | @memcpy(extra_array, unaligned_extra); | | |
| 4984 | const error_bundle = .{ | | |
| 4985 | .string_bytes = try comp.gpa.dupe(u8, string_bytes), | | |
| 4986 | .extra = extra_array, | | |
| 4987 | }; | | |
| 4988 | return comp.failWin32ResourceWithOwnedBundle(win32_resource, error_bundle); | | |
| 4989 | }, | | |
| 4990 | else => {}, // ignore other messages | | |
| 4991 | } | | |
| 4992 | | | |
| 4993 | stdout.discard(body.len); | | |
| 4994 | } | | |
| 4995 | | | |
| 4996 | // Just in case there's a failure that didn't send an ErrorBundle (e.g. an error return trace) | | |
| 4997 | const stderr_reader = child.stderr.?.reader(); | | |
| 4998 | const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024); | | |
| 4999 | | | |
| 5000 | const term = child.wait() catch |err| { | | |
| 5001 | return comp.failWin32Resource(win32_resource, "unable to wait for {s} rc: {s}", .{ argv.items[0], @errorName(err) }); | | |
| 5002 | }; | | |
| 5003 | | | |
| 5004 | switch (term) { | | |
| 5005 | .Exited => |code| { | | |
| 5006 | if (code != 0) { | | |
| 5007 | log.err("zig rc failed with stderr:\n{s}", .{stderr}); | | |
| 5008 | return comp.failWin32Resource(win32_resource, "zig rc exited with code {d}", .{code}); | | |
| 5009 | } | | |
| 5010 | }, | | |
| 5011 | else => { | | |
| 5012 | log.err("zig rc terminated with stderr:\n{s}", .{stderr}); | | |
| 5013 | return comp.failWin32Resource(win32_resource, "zig rc terminated unexpectedly", .{}); | | |
| 5014 | }, | | |
| 5015 | } | | |
| 5016 | } | | |
| 5017 | | 4922 | |
| 5018 | // Read depfile and update cache manifest | 4923 | // Read depfile and update cache manifest |
| 5019 | { | 4924 | { |
| ... | @@ -5079,6 +4984,100 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 | ... | @@ -5079,6 +4984,100 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 5079 | }; | 4984 | }; |
| 5080 | } | 4985 | } |
| 5081 | | 4986 | |
| | 4987 | fn spawnZigRc( |
| | 4988 | comp: *Compilation, |
| | 4989 | win32_resource: *Win32Resource, |
| | 4990 | src_basename: []const u8, |
| | 4991 | arena: Allocator, |
| | 4992 | argv: []const []const u8, |
| | 4993 | child_progress_node: *std.Progress.Node, |
| | 4994 | ) !void { |
| | 4995 | var node_name: std.ArrayListUnmanaged(u8) = .{}; |
| | 4996 | defer node_name.deinit(arena); |
| | 4997 | |
| | 4998 | var child = std.ChildProcess.init(argv, arena); |
| | 4999 | child.stdin_behavior = .Ignore; |
| | 5000 | child.stdout_behavior = .Pipe; |
| | 5001 | child.stderr_behavior = .Pipe; |
| | 5002 | |
| | 5003 | child.spawn() catch |err| { |
| | 5004 | return comp.failWin32Resource(win32_resource, "unable to spawn {s} rc: {s}", .{ argv[0], @errorName(err) }); |
| | 5005 | }; |
| | 5006 | |
| | 5007 | var poller = std.io.poll(comp.gpa, enum { stdout }, .{ |
| | 5008 | .stdout = child.stdout.?, |
| | 5009 | }); |
| | 5010 | defer poller.deinit(); |
| | 5011 | |
| | 5012 | const stdout = poller.fifo(.stdout); |
| | 5013 | |
| | 5014 | poll: while (true) { |
| | 5015 | while (stdout.readableLength() < @sizeOf(std.zig.Server.Message.Header)) { |
| | 5016 | if (!(try poller.poll())) break :poll; |
| | 5017 | } |
| | 5018 | const header = stdout.reader().readStruct(std.zig.Server.Message.Header) catch unreachable; |
| | 5019 | while (stdout.readableLength() < header.bytes_len) { |
| | 5020 | if (!(try poller.poll())) break :poll; |
| | 5021 | } |
| | 5022 | const body = stdout.readableSliceOfLen(header.bytes_len); |
| | 5023 | |
| | 5024 | switch (header.tag) { |
| | 5025 | // We expect exactly one ErrorBundle, and if any error_bundle header is |
| | 5026 | // sent then it's a fatal error. |
| | 5027 | .error_bundle => { |
| | 5028 | const EbHdr = std.zig.Server.Message.ErrorBundle; |
| | 5029 | const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body)); |
| | 5030 | const extra_bytes = |
| | 5031 | body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len]; |
| | 5032 | const string_bytes = |
| | 5033 | body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len]; |
| | 5034 | const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes); |
| | 5035 | const extra_array = try comp.gpa.alloc(u32, unaligned_extra.len); |
| | 5036 | @memcpy(extra_array, unaligned_extra); |
| | 5037 | const error_bundle = std.zig.ErrorBundle{ |
| | 5038 | .string_bytes = try comp.gpa.dupe(u8, string_bytes), |
| | 5039 | .extra = extra_array, |
| | 5040 | }; |
| | 5041 | return comp.failWin32ResourceWithOwnedBundle(win32_resource, error_bundle); |
| | 5042 | }, |
| | 5043 | .progress => { |
| | 5044 | node_name.clearRetainingCapacity(); |
| | 5045 | if (body.len > 0) { |
| | 5046 | try node_name.appendSlice(arena, "build 'zig rc'... "); |
| | 5047 | try node_name.appendSlice(arena, body); |
| | 5048 | child_progress_node.setName(node_name.items); |
| | 5049 | } else { |
| | 5050 | child_progress_node.setName(src_basename); |
| | 5051 | } |
| | 5052 | }, |
| | 5053 | else => {}, // ignore other messages |
| | 5054 | } |
| | 5055 | |
| | 5056 | stdout.discard(body.len); |
| | 5057 | } |
| | 5058 | |
| | 5059 | // Just in case there's a failure that didn't send an ErrorBundle (e.g. an error return trace) |
| | 5060 | const stderr_reader = child.stderr.?.reader(); |
| | 5061 | const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024); |
| | 5062 | |
| | 5063 | const term = child.wait() catch |err| { |
| | 5064 | return comp.failWin32Resource(win32_resource, "unable to wait for {s} rc: {s}", .{ argv[0], @errorName(err) }); |
| | 5065 | }; |
| | 5066 | |
| | 5067 | switch (term) { |
| | 5068 | .Exited => |code| { |
| | 5069 | if (code != 0) { |
| | 5070 | log.err("zig rc failed with stderr:\n{s}", .{stderr}); |
| | 5071 | return comp.failWin32Resource(win32_resource, "zig rc exited with code {d}", .{code}); |
| | 5072 | } |
| | 5073 | }, |
| | 5074 | else => { |
| | 5075 | log.err("zig rc terminated with stderr:\n{s}", .{stderr}); |
| | 5076 | return comp.failWin32Resource(win32_resource, "zig rc terminated unexpectedly", .{}); |
| | 5077 | }, |
| | 5078 | } |
| | 5079 | } |
| | 5080 | |
| 5082 | pub fn tmpFilePath(comp: *Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 { | 5081 | pub fn tmpFilePath(comp: *Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 { |
| 5083 | const s = std.fs.path.sep_str; | 5082 | const s = std.fs.path.sep_str; |
| 5084 | const rand_int = std.crypto.random.int(u64); | 5083 | const rand_int = std.crypto.random.int(u64); |