authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-04 14:06:00-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-04 14:06:20-07:00
logd65e248ed130da21e554807c8ce6add9773e0670
tree00b96f6ff10e543266c7cb4f1655ccf2460d460c
parent9c5056788f98396ec461a1a89c4b580efe01fd62

stage2: ELF: improve error reporting when libc is missing

Future improvement: make plain error notes actually render as notes rather than errors, but keep them as errors for the case of sub-compilation errors, e.g. when compiler-rt has compilation errors.

3 files changed, 34 insertions(+), 5 deletions(-)

src/Compilation.zig+30-4
...@@ -2321,7 +2321,12 @@ pub fn update(comp: *Compilation) !void {...@@ -2321,7 +2321,12 @@ pub fn update(comp: *Compilation) !void {
2321}2321}
23222322
2323fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void {2323fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void {
2324 try comp.bin_file.flush(comp, prog_node); // This is needed before reading the error flags.2324 // This is needed before reading the error flags.
2325 comp.bin_file.flush(comp, prog_node) catch |err| switch (err) {
2326 error.FlushFailure => {}, // error reported through link_error_flags
2327 error.LLDReportedFailure => {}, // error reported through log.err
2328 else => |e| return e,
2329 };
2325 comp.link_error_flags = comp.bin_file.errorFlags();2330 comp.link_error_flags = comp.bin_file.errorFlags();
23262331
2327 const use_stage1 = build_options.omit_stage2 or2332 const use_stage1 = build_options.omit_stage2 or
...@@ -2593,10 +2598,11 @@ pub fn totalErrorCount(self: *Compilation) usize {...@@ -2593,10 +2598,11 @@ pub fn totalErrorCount(self: *Compilation) usize {
2593 }2598 }
2594 }2599 }
25952600
2596 // The "no entry point found" error only counts if there are no other errors.2601 // The "no entry point found" error only counts if there are no semantic analysis errors.
2597 if (total == 0) {2602 if (total == 0) {
2598 total += @boolToInt(self.link_error_flags.no_entry_point_found);2603 total += @boolToInt(self.link_error_flags.no_entry_point_found);
2599 }2604 }
2605 total += @boolToInt(self.link_error_flags.missing_libc);
26002606
2601 // Compile log errors only count if there are no other errors.2607 // Compile log errors only count if there are no other errors.
2602 if (total == 0) {2608 if (total == 0) {
...@@ -2693,10 +2699,30 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {...@@ -2693,10 +2699,30 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
2693 }2699 }
2694 }2700 }
26952701
2696 if (errors.items.len == 0 and self.link_error_flags.no_entry_point_found) {2702 if (errors.items.len == 0) {
2703 if (self.link_error_flags.no_entry_point_found) {
2704 try errors.append(.{
2705 .plain = .{
2706 .msg = try std.fmt.allocPrint(arena_allocator, "no entry point found", .{}),
2707 },
2708 });
2709 }
2710 }
2711
2712 if (self.link_error_flags.missing_libc) {
2713 const notes = try arena_allocator.create([2]AllErrors.Message);
2714 notes.* = .{
2715 .{ .plain = .{
2716 .msg = try arena_allocator.dupe(u8, "run 'zig libc -h' to learn about libc installations"),
2717 } },
2718 .{ .plain = .{
2719 .msg = try arena_allocator.dupe(u8, "run 'zig targets' to see the targets for which zig can always provide libc"),
2720 } },
2721 };
2697 try errors.append(.{2722 try errors.append(.{
2698 .plain = .{2723 .plain = .{
2699 .msg = try std.fmt.allocPrint(arena_allocator, "no entry point found", .{}),2724 .msg = try std.fmt.allocPrint(arena_allocator, "libc not available", .{}),
2725 .notes = notes,
2700 },2726 },
2701 });2727 });
2702 }2728 }
src/link.zig+1
...@@ -951,6 +951,7 @@ pub const File = struct {...@@ -951,6 +951,7 @@ pub const File = struct {
951951
952 pub const ErrorFlags = struct {952 pub const ErrorFlags = struct {
953 no_entry_point_found: bool = false,953 no_entry_point_found: bool = false,
954 missing_libc: bool = false,
954 };955 };
955956
956 pub const C = @import("link/C.zig");957 pub const C = @import("link/C.zig");
src/link/Elf.zig+3-1
...@@ -1719,6 +1719,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -1719,6 +1719,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
1719 }1719 }
17201720
1721 // libc dep1721 // libc dep
1722 self.error_flags.missing_libc = false;
1722 if (self.base.options.link_libc) {1723 if (self.base.options.link_libc) {
1723 if (self.base.options.libc_installation != null) {1724 if (self.base.options.libc_installation != null) {
1724 const needs_grouping = self.base.options.link_mode == .Static;1725 const needs_grouping = self.base.options.link_mode == .Static;
...@@ -1739,7 +1740,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -1739,7 +1740,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
1739 .Dynamic => "libc.so",1740 .Dynamic => "libc.so",
1740 }));1741 }));
1741 } else {1742 } else {
1742 unreachable; // Compiler was supposed to emit an error for not being able to provide libc.1743 self.error_flags.missing_libc = true;
1744 return error.FlushFailure;
1743 }1745 }
1744 }1746 }
1745 }1747 }