Commit 64deb46859

Andrew Kelley <andrew@ziglang.org>
2020-09-24 00:21:40
stage2: capture LLD stderr into a buffer
1 parent 90b320d
Changed files (2)
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 {
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