| author | |
| committer | |
| log | 4aa4d80ec640b869939111f35d7bf2509a227793 |
| tree | 1908ca29e6ddb56801d0c885ed277e2712c5f0f5 |
| parent | 328ae41468f3514251ac1b0726c41eca9fbc3fb5 |
- Revive some of the removed cache integration logic in `cmdTranslateC` now that `translate-c` can return error bundles
- Fixup inconsistent path separators (on Windows) when building the aro include path
- Move some error bundle logic from resinator into aro.Diagnostics
- Add `ErrorBundle.addRootErrorMessageWithNotes` (extracted from resinator)6 files changed, 275 insertions(+), 131 deletions(-)
lib/compiler/aro/aro/Diagnostics.zig+76| ... | ... | @@ -562,3 +562,79 @@ fn addMessage(d: *Diagnostics, msg: Message) Compilation.Error!void { |
| 562 | 562 | }, |
| 563 | 563 | } |
| 564 | 564 | } |
| 565 | ||
| 566 | const ErrorBundle = std.zig.ErrorBundle; | |
| 567 | ||
| 568 | pub fn toErrorBundle( | |
| 569 | d: *const Diagnostics, | |
| 570 | gpa: std.mem.Allocator, | |
| 571 | fail_msg: ?[]const u8, | |
| 572 | ) !ErrorBundle { | |
| 573 | @branchHint(.cold); | |
| 574 | ||
| 575 | var bundle: ErrorBundle.Wip = undefined; | |
| 576 | try bundle.init(gpa); | |
| 577 | errdefer bundle.deinit(); | |
| 578 | ||
| 579 | if (fail_msg) |msg| { | |
| 580 | try bundle.addRootErrorMessage(.{ | |
| 581 | .msg = try bundle.addString(msg), | |
| 582 | }); | |
| 583 | } | |
| 584 | ||
| 585 | var cur_err: ?ErrorBundle.ErrorMessage = null; | |
| 586 | var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty; | |
| 587 | defer cur_notes.deinit(gpa); | |
| 588 | for (d.output.to_list.messages.items) |msg| { | |
| 589 | switch (msg.kind) { | |
| 590 | // Clear the current error so that notes don't bleed into unassociated errors | |
| 591 | .off, .warning => { | |
| 592 | cur_err = null; | |
| 593 | continue; | |
| 594 | }, | |
| 595 | .note => if (cur_err == null) continue, | |
| 596 | .@"fatal error", .@"error" => {}, | |
| 597 | } | |
| 598 | ||
| 599 | const src_loc = src_loc: { | |
| 600 | if (msg.location) |location| { | |
| 601 | break :src_loc try bundle.addSourceLocation(.{ | |
| 602 | .src_path = try bundle.addString(location.path), | |
| 603 | .line = location.line_no - 1, // 1-based -> 0-based | |
| 604 | .column = location.col - 1, // 1-based -> 0-based | |
| 605 | .span_start = location.width, | |
| 606 | .span_main = location.width, | |
| 607 | .span_end = location.width, | |
| 608 | .source_line = try bundle.addString(location.line), | |
| 609 | }); | |
| 610 | } | |
| 611 | break :src_loc ErrorBundle.SourceLocationIndex.none; | |
| 612 | }; | |
| 613 | ||
| 614 | switch (msg.kind) { | |
| 615 | .@"fatal error", .@"error" => { | |
| 616 | if (cur_err) |err| { | |
| 617 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); | |
| 618 | } | |
| 619 | cur_err = .{ | |
| 620 | .msg = try bundle.addString(msg.text), | |
| 621 | .src_loc = src_loc, | |
| 622 | }; | |
| 623 | cur_notes.clearRetainingCapacity(); | |
| 624 | }, | |
| 625 | .note => { | |
| 626 | cur_err.?.notes_len += 1; | |
| 627 | try cur_notes.append(gpa, .{ | |
| 628 | .msg = try bundle.addString(msg.text), | |
| 629 | .src_loc = src_loc, | |
| 630 | }); | |
| 631 | }, | |
| 632 | .off, .warning => unreachable, | |
| 633 | } | |
| 634 | } | |
| 635 | if (cur_err) |err| { | |
| 636 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); | |
| 637 | } | |
| 638 | ||
| 639 | return try bundle.toOwnedBundle(""); | |
| 640 | } |
lib/compiler/resinator/main.zig+5-85| ... | ... | @@ -671,7 +671,7 @@ const ErrorHandler = union(enum) { |
| 671 | 671 | ) !void { |
| 672 | 672 | switch (self.*) { |
| 673 | 673 | .server => |*server| { |
| 674 | var error_bundle = try aroDiagnosticsToErrorBundle(allocator, fail_msg, comp); | |
| 674 | var error_bundle = try comp.diagnostics.toErrorBundle(allocator, fail_msg); | |
| 675 | 675 | defer error_bundle.deinit(allocator); |
| 676 | 676 | |
| 677 | 677 | try server.serveErrorBundle(error_bundle); |
| ... | ... | @@ -753,7 +753,7 @@ fn cliDiagnosticsToErrorBundle( |
| 753 | 753 | switch (err_details.type) { |
| 754 | 754 | .err => { |
| 755 | 755 | if (cur_err) |err| { |
| 756 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | |
| 756 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); | |
| 757 | 757 | } |
| 758 | 758 | cur_err = .{ |
| 759 | 759 | .msg = try bundle.addString(err_details.msg.items), |
| ... | ... | @@ -771,7 +771,7 @@ fn cliDiagnosticsToErrorBundle( |
| 771 | 771 | } |
| 772 | 772 | } |
| 773 | 773 | if (cur_err) |err| { |
| 774 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | |
| 774 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); | |
| 775 | 775 | } |
| 776 | 776 | |
| 777 | 777 | return try bundle.toOwnedBundle(""); |
| ... | ... | @@ -840,7 +840,7 @@ fn diagnosticsToErrorBundle( |
| 840 | 840 | switch (err_details.type) { |
| 841 | 841 | .err => { |
| 842 | 842 | if (cur_err) |err| { |
| 843 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | |
| 843 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); | |
| 844 | 844 | } |
| 845 | 845 | cur_err = .{ |
| 846 | 846 | .msg = try bundle.addString(msg_buf.written()), |
| ... | ... | @@ -859,20 +859,12 @@ fn diagnosticsToErrorBundle( |
| 859 | 859 | } |
| 860 | 860 | } |
| 861 | 861 | if (cur_err) |err| { |
| 862 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | |
| 862 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); | |
| 863 | 863 | } |
| 864 | 864 | |
| 865 | 865 | return try bundle.toOwnedBundle(""); |
| 866 | 866 | } |
| 867 | 867 | |
| 868 | fn flushErrorMessageIntoBundle(wip: *ErrorBundle.Wip, msg: ErrorBundle.ErrorMessage, notes: []const ErrorBundle.ErrorMessage) !void { | |
| 869 | try wip.addRootErrorMessage(msg); | |
| 870 | const notes_start = try wip.reserveNotes(@intCast(notes.len)); | |
| 871 | for (notes_start.., notes) |i, note| { | |
| 872 | wip.extra.items[i] = @intFromEnum(wip.addErrorMessageAssumeCapacity(note)); | |
| 873 | } | |
| 874 | } | |
| 875 | ||
| 876 | 868 | fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []const u8, args: anytype) !ErrorBundle { |
| 877 | 869 | @branchHint(.cold); |
| 878 | 870 | var bundle: ErrorBundle.Wip = undefined; |
| ... | ... | @@ -883,75 +875,3 @@ fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []con |
| 883 | 875 | }); |
| 884 | 876 | return try bundle.toOwnedBundle(""); |
| 885 | 877 | } |
| 886 | ||
| 887 | fn aroDiagnosticsToErrorBundle( | |
| 888 | gpa: std.mem.Allocator, | |
| 889 | fail_msg: []const u8, | |
| 890 | comp: *aro.Compilation, | |
| 891 | ) !ErrorBundle { | |
| 892 | @branchHint(.cold); | |
| 893 | ||
| 894 | var bundle: ErrorBundle.Wip = undefined; | |
| 895 | try bundle.init(gpa); | |
| 896 | errdefer bundle.deinit(); | |
| 897 | ||
| 898 | try bundle.addRootErrorMessage(.{ | |
| 899 | .msg = try bundle.addString(fail_msg), | |
| 900 | }); | |
| 901 | ||
| 902 | var cur_err: ?ErrorBundle.ErrorMessage = null; | |
| 903 | var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty; | |
| 904 | defer cur_notes.deinit(gpa); | |
| 905 | for (comp.diagnostics.output.to_list.messages.items) |msg| { | |
| 906 | switch (msg.kind) { | |
| 907 | // Clear the current error so that notes don't bleed into unassociated errors | |
| 908 | .off, .warning => { | |
| 909 | cur_err = null; | |
| 910 | continue; | |
| 911 | }, | |
| 912 | .note => if (cur_err == null) continue, | |
| 913 | .@"fatal error", .@"error" => {}, | |
| 914 | } | |
| 915 | ||
| 916 | const src_loc = src_loc: { | |
| 917 | if (msg.location) |location| { | |
| 918 | break :src_loc try bundle.addSourceLocation(.{ | |
| 919 | .src_path = try bundle.addString(location.path), | |
| 920 | .line = location.line_no - 1, // 1-based -> 0-based | |
| 921 | .column = location.col - 1, // 1-based -> 0-based | |
| 922 | .span_start = location.width, | |
| 923 | .span_main = location.width, | |
| 924 | .span_end = location.width, | |
| 925 | .source_line = try bundle.addString(location.line), | |
| 926 | }); | |
| 927 | } | |
| 928 | break :src_loc ErrorBundle.SourceLocationIndex.none; | |
| 929 | }; | |
| 930 | ||
| 931 | switch (msg.kind) { | |
| 932 | .@"fatal error", .@"error" => { | |
| 933 | if (cur_err) |err| { | |
| 934 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | |
| 935 | } | |
| 936 | cur_err = .{ | |
| 937 | .msg = try bundle.addString(msg.text), | |
| 938 | .src_loc = src_loc, | |
| 939 | }; | |
| 940 | cur_notes.clearRetainingCapacity(); | |
| 941 | }, | |
| 942 | .note => { | |
| 943 | cur_err.?.notes_len += 1; | |
| 944 | try cur_notes.append(gpa, .{ | |
| 945 | .msg = try bundle.addString(msg.text), | |
| 946 | .src_loc = src_loc, | |
| 947 | }); | |
| 948 | }, | |
| 949 | .off, .warning => unreachable, | |
| 950 | } | |
| 951 | } | |
| 952 | if (cur_err) |err| { | |
| 953 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | |
| 954 | } | |
| 955 | ||
| 956 | return try bundle.toOwnedBundle(""); | |
| 957 | } |
lib/compiler/translate-c/main.zig+52-10| ... | ... | @@ -13,24 +13,33 @@ pub fn main() u8 { |
| 13 | 13 | const gpa = general_purpose_allocator.allocator(); |
| 14 | 14 | defer _ = general_purpose_allocator.deinit(); |
| 15 | 15 | |
| 16 | var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); | |
| 16 | var arena_instance = std.heap.ArenaAllocator.init(gpa); | |
| 17 | 17 | defer arena_instance.deinit(); |
| 18 | 18 | const arena = arena_instance.allocator(); |
| 19 | 19 | |
| 20 | const args = process.argsAlloc(arena) catch { | |
| 20 | var args = process.argsAlloc(arena) catch { | |
| 21 | 21 | std.debug.print("ran out of memory allocating arguments\n", .{}); |
| 22 | 22 | if (fast_exit) process.exit(1); |
| 23 | 23 | return 1; |
| 24 | 24 | }; |
| 25 | 25 | |
| 26 | var zig_integration = false; | |
| 27 | if (args.len > 1 and std.mem.eql(u8, args[1], "--zig-integration")) { | |
| 28 | zig_integration = true; | |
| 29 | } | |
| 30 | ||
| 26 | 31 | var stderr_buf: [1024]u8 = undefined; |
| 27 | 32 | var stderr = std.fs.File.stderr().writer(&stderr_buf); |
| 28 | var diagnostics: aro.Diagnostics = .{ | |
| 29 | .output = .{ .to_writer = .{ | |
| 33 | var diagnostics: aro.Diagnostics = switch (zig_integration) { | |
| 34 | false => .{ .output = .{ .to_writer = .{ | |
| 30 | 35 | .color = .detect(stderr.file), |
| 31 | 36 | .writer = &stderr.interface, |
| 32 | } }, | |
| 37 | } } }, | |
| 38 | true => .{ .output = .{ .to_list = .{ | |
| 39 | .arena = .init(gpa), | |
| 40 | } } }, | |
| 33 | 41 | }; |
| 42 | defer diagnostics.deinit(); | |
| 34 | 43 | |
| 35 | 44 | var comp = aro.Compilation.initDefault(gpa, arena, &diagnostics, std.fs.cwd()) catch |err| switch (err) { |
| 36 | 45 | error.OutOfMemory => { |
| ... | ... | @@ -47,13 +56,22 @@ pub fn main() u8 { |
| 47 | 56 | var toolchain: aro.Toolchain = .{ .driver = &driver, .filesystem = .{ .real = comp.cwd } }; |
| 48 | 57 | defer toolchain.deinit(); |
| 49 | 58 | |
| 50 | translate(&driver, &toolchain, args) catch |err| switch (err) { | |
| 59 | translate(&driver, &toolchain, args, zig_integration) catch |err| switch (err) { | |
| 51 | 60 | error.OutOfMemory => { |
| 52 | 61 | std.debug.print("ran out of memory translating\n", .{}); |
| 53 | 62 | if (fast_exit) process.exit(1); |
| 54 | 63 | return 1; |
| 55 | 64 | }, |
| 56 | error.FatalError => { | |
| 65 | error.FatalError => if (zig_integration) { | |
| 66 | serveErrorBundle(arena, &diagnostics) catch |bundle_err| { | |
| 67 | std.debug.print("unable to serve error bundle: {}\n", .{bundle_err}); | |
| 68 | if (fast_exit) process.exit(1); | |
| 69 | return 1; | |
| 70 | }; | |
| 71 | ||
| 72 | if (fast_exit) process.exit(0); | |
| 73 | return 0; | |
| 74 | } else { | |
| 57 | 75 | if (fast_exit) process.exit(1); |
| 58 | 76 | return 1; |
| 59 | 77 | }, |
| ... | ... | @@ -63,10 +81,23 @@ pub fn main() u8 { |
| 63 | 81 | return 1; |
| 64 | 82 | }, |
| 65 | 83 | }; |
| 84 | ||
| 85 | assert(comp.diagnostics.errors == 0 or !zig_integration); | |
| 66 | 86 | if (fast_exit) process.exit(@intFromBool(comp.diagnostics.errors != 0)); |
| 67 | 87 | return @intFromBool(comp.diagnostics.errors != 0); |
| 68 | 88 | } |
| 69 | 89 | |
| 90 | fn serveErrorBundle(arena: std.mem.Allocator, diagnostics: *const aro.Diagnostics) !void { | |
| 91 | const error_bundle = try diagnostics.toErrorBundle(arena, "failed during translation"); | |
| 92 | var stdout_buffer: [1024]u8 = undefined; | |
| 93 | var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); | |
| 94 | var server: std.zig.Server = .{ | |
| 95 | .out = &stdout_writer.interface, | |
| 96 | .in = undefined, | |
| 97 | }; | |
| 98 | try server.serveErrorBundle(error_bundle); | |
| 99 | } | |
| 100 | ||
| 70 | 101 | pub const usage = |
| 71 | 102 | \\Usage {s}: [options] file [CC options] |
| 72 | 103 | \\ |
| ... | ... | @@ -79,7 +110,7 @@ pub const usage = |
| 79 | 110 | \\ |
| 80 | 111 | ; |
| 81 | 112 | |
| 82 | fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { | |
| 113 | fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration: bool) !void { | |
| 83 | 114 | const gpa = d.comp.gpa; |
| 84 | 115 | |
| 85 | 116 | const aro_args = args: { |
| ... | ... | @@ -99,6 +130,9 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { |
| 99 | 130 | try stdout.interface.writeAll("0.0.0-dev\n"); |
| 100 | 131 | try stdout.interface.flush(); |
| 101 | 132 | return; |
| 133 | } else if (mem.eql(u8, arg, "--zig-integration")) { | |
| 134 | if (i != 1 or !zig_integration) | |
| 135 | return d.fatal("--zig-integration must be the first argument", .{}); | |
| 102 | 136 | } else { |
| 103 | 137 | i += 1; |
| 104 | 138 | } |
| ... | ... | @@ -116,6 +150,14 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { |
| 116 | 150 | return d.fatal("user provided macro source exceeded max size", .{}); |
| 117 | 151 | } |
| 118 | 152 | |
| 153 | const has_output_file = if (d.output_name) |path| | |
| 154 | !std.mem.eql(u8, path, "-") | |
| 155 | else | |
| 156 | false; | |
| 157 | if (zig_integration and !has_output_file) { | |
| 158 | return d.fatal("--zig-integration requires specifying an output file", .{}); | |
| 159 | } | |
| 160 | ||
| 119 | 161 | const content = try macro_buf.toOwnedSlice(gpa); |
| 120 | 162 | errdefer gpa.free(content); |
| 121 | 163 | |
| ... | ... | @@ -160,7 +202,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { |
| 160 | 202 | defer c_tree.deinit(); |
| 161 | 203 | |
| 162 | 204 | if (d.diagnostics.errors != 0) { |
| 163 | if (fast_exit) process.exit(1); | |
| 205 | if (fast_exit and !zig_integration) process.exit(1); | |
| 164 | 206 | return error.FatalError; |
| 165 | 207 | } |
| 166 | 208 | |
| ... | ... | @@ -212,7 +254,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { |
| 212 | 254 | if (out_writer.err) |write_err| |
| 213 | 255 | return d.fatal("failed to write result to '{s}': {s}", .{ out_file_path, aro.Driver.errorDescription(write_err) }); |
| 214 | 256 | |
| 215 | if (fast_exit) process.exit(0); | |
| 257 | if (fast_exit and !zig_integration) process.exit(0); | |
| 216 | 258 | } |
| 217 | 259 | |
| 218 | 260 | test { |
lib/std/zig/ErrorBundle.zig+12| ... | ... | @@ -416,6 +416,18 @@ pub const Wip = struct { |
| 416 | 416 | wip.root_list.appendAssumeCapacity(try addErrorMessage(wip, em)); |
| 417 | 417 | } |
| 418 | 418 | |
| 419 | pub fn addRootErrorMessageWithNotes( | |
| 420 | wip: *Wip, | |
| 421 | msg: ErrorMessage, | |
| 422 | notes: []const ErrorMessage, | |
| 423 | ) !void { | |
| 424 | try wip.addRootErrorMessage(msg); | |
| 425 | const notes_start = try wip.reserveNotes(@intCast(notes.len)); | |
| 426 | for (notes_start.., notes) |i, note| { | |
| 427 | wip.extra.items[i] = @intFromEnum(wip.addErrorMessageAssumeCapacity(note)); | |
| 428 | } | |
| 429 | } | |
| 430 | ||
| 419 | 431 | pub fn addErrorMessage(wip: *Wip, em: ErrorMessage) Allocator.Error!MessageIndex { |
| 420 | 432 | return @enumFromInt(try addExtra(wip, em)); |
| 421 | 433 | } |
src/Compilation.zig+2-2| ... | ... | @@ -3398,7 +3398,7 @@ fn flush( |
| 3398 | 3398 | /// Linker backends which do not have this requirement can fall back to the simple |
| 3399 | 3399 | /// implementation at the bottom of this function. |
| 3400 | 3400 | /// This function is only called when CacheMode is `whole`. |
| 3401 | fn renameTmpIntoCache( | |
| 3401 | pub fn renameTmpIntoCache( | |
| 3402 | 3402 | cache_directory: Cache.Directory, |
| 3403 | 3403 | tmp_dir_sub_path: []const u8, |
| 3404 | 3404 | o_sub_path: []const u8, |
| ... | ... | @@ -6684,7 +6684,7 @@ pub fn addTranslateCCArgs( |
| 6684 | 6684 | |
| 6685 | 6685 | try argv.appendSlice(&.{ "-x", "c" }); |
| 6686 | 6686 | |
| 6687 | const resource_path = try comp.dirs.zig_lib.join(arena, &.{"compiler/aro/include"}); | |
| 6687 | const resource_path = try comp.dirs.zig_lib.join(arena, &.{ "compiler", "aro", "include" }); | |
| 6688 | 6688 | try argv.appendSlice(&.{ "-isystem", resource_path }); |
| 6689 | 6689 | |
| 6690 | 6690 | try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, owner_mod, .aro); |
src/main.zig+128-34| ... | ... | @@ -4075,7 +4075,7 @@ fn serve( |
| 4075 | 4075 | while (true) { |
| 4076 | 4076 | const hdr = try server.receiveMessage(); |
| 4077 | 4077 | |
| 4078 | // Lock the debug server while hanling the message. | |
| 4078 | // Lock the debug server while handling the message. | |
| 4079 | 4079 | if (comp.debugIncremental()) ids.mutex.lock(); |
| 4080 | 4080 | defer if (comp.debugIncremental()) ids.mutex.unlock(); |
| 4081 | 4081 | |
| ... | ... | @@ -4515,48 +4515,142 @@ fn cmdTranslateC( |
| 4515 | 4515 | prog_node: std.Progress.Node, |
| 4516 | 4516 | ) !void { |
| 4517 | 4517 | dev.check(.translate_c_command); |
| 4518 | _ = file_system_inputs; | |
| 4519 | _ = fancy_output; | |
| 4518 | const color: Color = .auto; | |
| 4520 | 4519 | |
| 4521 | 4520 | assert(comp.c_source_files.len == 1); |
| 4522 | 4521 | const c_source_file = comp.c_source_files[0]; |
| 4523 | 4522 | |
| 4524 | var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{}); | |
| 4525 | defer zig_cache_tmp_dir.close(); | |
| 4523 | const translated_zig_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{comp.root_name}); | |
| 4524 | ||
| 4525 | var man: Cache.Manifest = comp.obtainCObjectCacheManifest(comp.root_mod); | |
| 4526 | man.want_shared_lock = false; | |
| 4527 | defer man.deinit(); | |
| 4526 | 4528 | |
| 4527 | const ext = Compilation.classifyFileExt(c_source_file.src_path); | |
| 4528 | const out_dep_path: ?[]const u8 = blk: { | |
| 4529 | if (comp.disable_c_depfile) break :blk null; | |
| 4530 | const c_src_basename = fs.path.basename(c_source_file.src_path); | |
| 4531 | const dep_basename = try std.fmt.allocPrint(arena, "{s}.d", .{c_src_basename}); | |
| 4532 | const out_dep_path = try comp.tmpFilePath(arena, dep_basename); | |
| 4533 | break :blk out_dep_path; | |
| 4529 | man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects | |
| 4530 | man.hash.add(comp.config.c_frontend); | |
| 4531 | Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| { | |
| 4532 | fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) }); | |
| 4534 | 4533 | }; |
| 4535 | 4534 | |
| 4536 | var argv = std.array_list.Managed([]const u8).init(arena); | |
| 4537 | try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path, comp.root_mod); | |
| 4538 | try argv.append(c_source_file.src_path); | |
| 4539 | if (comp.verbose_cc) Compilation.dump_argv(argv.items); | |
| 4540 | ||
| 4541 | try translateC(comp.gpa, arena, argv.items, prog_node, null); | |
| 4542 | ||
| 4543 | if (out_dep_path) |dep_file_path| { | |
| 4544 | const dep_basename = fs.path.basename(dep_file_path); | |
| 4545 | // Add the files depended on to the cache system. | |
| 4546 | //man.addDepFilePost(zig_cache_tmp_dir, dep_basename) catch |err| switch (err) { | |
| 4547 | // error.FileNotFound => { | |
| 4548 | // // Clang didn't emit the dep file; nothing to add to the manifest. | |
| 4549 | // break :add_deps; | |
| 4550 | // }, | |
| 4551 | // else => |e| return e, | |
| 4552 | //}; | |
| 4553 | // Just to save disk space, we delete the file because it is never needed again. | |
| 4554 | zig_cache_tmp_dir.deleteFile(dep_basename) catch |err| { | |
| 4555 | warn("failed to delete '{s}': {t}", .{ dep_file_path, err }); | |
| 4535 | if (fancy_output) |p| p.cache_hit = true; | |
| 4536 | const bin_digest, const hex_digest = if (try man.hit()) digest: { | |
| 4537 | if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf); | |
| 4538 | const bin_digest = man.finalBin(); | |
| 4539 | const hex_digest = Cache.binToHex(bin_digest); | |
| 4540 | break :digest .{ bin_digest, hex_digest }; | |
| 4541 | } else digest: { | |
| 4542 | if (fancy_output) |p| p.cache_hit = false; | |
| 4543 | ||
| 4544 | const tmp_basename = std.fmt.hex(std.crypto.random.int(u64)); | |
| 4545 | const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename; | |
| 4546 | const cache_dir = comp.dirs.local_cache.handle; | |
| 4547 | var cache_tmp_dir = try cache_dir.makeOpenPath(tmp_sub_path, .{}); | |
| 4548 | defer cache_tmp_dir.close(); | |
| 4549 | ||
| 4550 | const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_zig_basename }); | |
| 4551 | ||
| 4552 | const ext = Compilation.classifyFileExt(c_source_file.src_path); | |
| 4553 | const out_dep_path: ?[]const u8 = blk: { | |
| 4554 | if (comp.disable_c_depfile) break :blk null; | |
| 4555 | const c_src_basename = fs.path.basename(c_source_file.src_path); | |
| 4556 | const dep_basename = try std.fmt.allocPrint(arena, "{s}.d", .{c_src_basename}); | |
| 4557 | const out_dep_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, dep_basename }); | |
| 4558 | break :blk out_dep_path; | |
| 4556 | 4559 | }; |
| 4557 | } | |
| 4558 | 4560 | |
| 4559 | return cleanExit(); | |
| 4561 | var argv = std.array_list.Managed([]const u8).init(arena); | |
| 4562 | try argv.append("--zig-integration"); | |
| 4563 | try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path, comp.root_mod); | |
| 4564 | try argv.appendSlice(&.{ c_source_file.src_path, "-o", translated_path }); | |
| 4565 | if (comp.verbose_cc) Compilation.dump_argv(argv.items); | |
| 4566 | ||
| 4567 | var stdout: []u8 = undefined; | |
| 4568 | try translateC(comp.gpa, arena, argv.items, prog_node, &stdout); | |
| 4569 | ||
| 4570 | if (stdout.len > 0) { | |
| 4571 | var reader: std.Io.Reader = .fixed(stdout); | |
| 4572 | const MessageHeader = std.zig.Server.Message.Header; | |
| 4573 | const header = reader.takeStruct(MessageHeader, .little) catch unreachable; | |
| 4574 | const body = reader.take(header.bytes_len) catch unreachable; | |
| 4575 | switch (header.tag) { | |
| 4576 | .error_bundle => { | |
| 4577 | // TODO: De-dupe this logic | |
| 4578 | const EbHdr = std.zig.Server.Message.ErrorBundle; | |
| 4579 | const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body)); | |
| 4580 | const extra_bytes = | |
| 4581 | body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len]; | |
| 4582 | const string_bytes = | |
| 4583 | body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len]; | |
| 4584 | const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes); | |
| 4585 | const extra_array = try comp.gpa.alloc(u32, unaligned_extra.len); | |
| 4586 | @memcpy(extra_array, unaligned_extra); | |
| 4587 | const error_bundle: std.zig.ErrorBundle = .{ | |
| 4588 | .string_bytes = try comp.gpa.dupe(u8, string_bytes), | |
| 4589 | .extra = extra_array, | |
| 4590 | }; | |
| 4591 | ||
| 4592 | if (fancy_output) |p| { | |
| 4593 | p.errors = error_bundle; | |
| 4594 | return; | |
| 4595 | } else { | |
| 4596 | error_bundle.renderToStdErr(color.renderOptions()); | |
| 4597 | process.exit(1); | |
| 4598 | } | |
| 4599 | ||
| 4600 | return error.AnalysisFail; | |
| 4601 | }, | |
| 4602 | else => unreachable, // No other messagse are sent | |
| 4603 | } | |
| 4604 | } | |
| 4605 | ||
| 4606 | if (out_dep_path) |dep_file_path| { | |
| 4607 | const dep_basename = fs.path.basename(dep_file_path); | |
| 4608 | // Add the files depended on to the cache system. | |
| 4609 | try man.addDepFilePost(cache_tmp_dir, dep_basename); | |
| 4610 | // Just to save disk space, we delete the file because it is never needed again. | |
| 4611 | cache_tmp_dir.deleteFile(dep_basename) catch |err| { | |
| 4612 | warn("failed to delete '{s}': {t}", .{ dep_file_path, err }); | |
| 4613 | }; | |
| 4614 | } | |
| 4615 | ||
| 4616 | const bin_digest = man.finalBin(); | |
| 4617 | const hex_digest = Cache.binToHex(bin_digest); | |
| 4618 | ||
| 4619 | const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; | |
| 4620 | try Compilation.renameTmpIntoCache( | |
| 4621 | comp.dirs.local_cache, | |
| 4622 | tmp_sub_path, | |
| 4623 | o_sub_path, | |
| 4624 | ); | |
| 4625 | ||
| 4626 | man.writeManifest() catch |err| warn("failed to write cache manifest: {t}", .{err}); | |
| 4627 | ||
| 4628 | if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf); | |
| 4629 | ||
| 4630 | break :digest .{ bin_digest, hex_digest }; | |
| 4631 | }; | |
| 4632 | ||
| 4633 | if (fancy_output) |p| { | |
| 4634 | p.digest = bin_digest; | |
| 4635 | p.errors = std.zig.ErrorBundle.empty; | |
| 4636 | } else { | |
| 4637 | const out_zig_path = try fs.path.join(arena, &.{ "o", &hex_digest, translated_zig_basename }); | |
| 4638 | const zig_file = comp.dirs.local_cache.handle.openFile(out_zig_path, .{}) catch |err| { | |
| 4639 | const path = comp.dirs.local_cache.path orelse "."; | |
| 4640 | fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ | |
| 4641 | path, | |
| 4642 | fs.path.sep_str, | |
| 4643 | out_zig_path, | |
| 4644 | @errorName(err), | |
| 4645 | }); | |
| 4646 | }; | |
| 4647 | defer zig_file.close(); | |
| 4648 | var stdout_writer = fs.File.stdout().writer(&stdout_buffer); | |
| 4649 | var file_reader = zig_file.reader(&.{}); | |
| 4650 | _ = try stdout_writer.interface.sendFileAll(&file_reader, .unlimited); | |
| 4651 | try stdout_writer.interface.flush(); | |
| 4652 | return cleanExit(); | |
| 4653 | } | |
| 4560 | 4654 | } |
| 4561 | 4655 | |
| 4562 | 4656 | pub fn translateC( |