diff --git a/BRANCH_TODO b/BRANCH_TODO index 72e1c78115..e6e88d817a 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,5 +1,4 @@ * musl - * implement proper parsing of LLD stderr/stdout and exposing compile errors * tests passing with -Dskip-non-native * windows CUSTOMBUILD : error : unable to build compiler_rt: FileNotFound [D:\a\1\s\build\zig_install_lib_files.vcxproj] * repair @cImport @@ -23,10 +22,11 @@ (maybe make it an explicit option and have main.zig disable it) * audit the CLI options for stage2 * audit the base cache hash - * implement proper parsing of clang stderr/stdout and exposing compile errors * On operating systems that support it, do an execve for `zig test` and `zig run` rather than child process. * restore error messages for stage2_add_link_lib + * implement proper parsing of clang stderr/stdout and exposing compile errors with the Compilation API + * implement proper parsing of LLD stderr/stdout and exposing compile errors with the Compilation API * support cross compiling stage2 with `zig build` * implement proper compile errors for failing to build glibc crt files and shared libs * implement -fno-emit-bin diff --git a/src/link/Elf.zig b/src/link/Elf.zig index d4900ccb25..88255b5280 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1591,9 +1591,34 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { new_argv[i] = try arena.dupeZ(u8, arg); } + var stderr_context: LLDContext = .{ + .elf = self, + .data = std.ArrayList(u8).init(self.base.allocator), + }; + defer stderr_context.data.deinit(); + var stdout_context: LLDContext = .{ + .elf = self, + .data = std.ArrayList(u8).init(self.base.allocator), + }; + defer stdout_context.data.deinit(); const llvm = @import("../llvm.zig"); - const ok = llvm.Link(.ELF, new_argv.ptr, new_argv.len, append_diagnostic, 0, 0); - if (!ok) return error.LLDReportedFailure; + const ok = llvm.Link(.ELF, new_argv.ptr, new_argv.len, append_diagnostic, + @ptrToInt(&stdout_context), + @ptrToInt(&stderr_context), + ); + if (stderr_context.oom or stdout_context.oom) return error.OutOfMemory; + if (stdout_context.data.items.len != 0) { + std.log.warn("unexpected LLD stdout: {}", .{stdout_context.data.items}); + } + if (!ok) { + // TODO parse this output and surface with the Compilation API rather than + // directly outputting to stderr here. + std.debug.print("{}", .{stderr_context.data.items}); + return error.LLDReportedFailure; + } + if (stderr_context.data.items.len != 0) { + std.log.warn("unexpected LLD stderr: {}", .{stderr_context.data.items}); + } // Update the dangling symlink with the digest. If it fails we can continue; it only // means that the next invocation will have an unnecessary cache miss. @@ -1609,10 +1634,18 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { self.base.lock = ch.toOwnedLock(); } +const LLDContext = struct { + data: std.ArrayList(u8), + elf: *Elf, + oom: bool = false, +}; + fn append_diagnostic(context: usize, ptr: [*]const u8, len: usize) callconv(.C) void { - // TODO collect diagnostics and handle cleanly + const lld_context = @intToPtr(*LLDContext, context); const msg = ptr[0..len]; - std.log.err("LLD: {}", .{msg}); + lld_context.data.appendSlice(msg) catch |err| switch (err) { + error.OutOfMemory => lld_context.oom = true, + }; } fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) void {