authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-08 09:38:38+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-09 02:44:15+02:00
log83b57947e328163263bb1e581bdf790bc15e8395
treecdcf93ca148e02f37432b6aa84970cc08bd8a522
parent8e741045bc672858dfe2ca85c8253fb755afd375

link: don't include static libraries in other static libraries

Follow-up to 9aa93a045ebbf7d5c6349eb41e99ca516ab9ba65, which fixed this bug for *shared* library inputs, but not *static* library inputs. Supersedes https://codeberg.org/ziglang/zig/pulls/31383 by fixing the bug at the compiler level instead of working around it in the build system. This seems preferable because it is useful to the compiler to have full information about a compilation's link inputs---for instance this could interact with https://github.com/ziglang/zig/issues/20654 in the future by having the compiler learn about a static library's ABI even if that static library does not ultimately contribute to the link. Resolves: https://codeberg.org/ziglang/zig/issues/35624

3 files changed, 14 insertions(+), 10 deletions(-)

src/link/Elf.zig+7-8
......@@ -714,7 +714,6 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
714714 const target = self.getTarget();
715715 const debug_fmt_strip = comp.config.debug_format == .strip;
716716 const default_sym_version = self.default_sym_version;
717 const is_static_lib = self.base.isStaticLib();
718717
719718 if (comp.verbose_link) {
720719 comp.mutex.lockUncancelable(io); // protect comp.arena
......@@ -733,7 +732,11 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
733732 .res => unreachable,
734733 .dso_exact => @panic("TODO"),
735734 .object => |obj| try parseObject(self, obj),
736 .archive => |obj| try parseArchive(gpa, io, diags, &self.file_handles, &self.files, target, debug_fmt_strip, default_sym_version, &self.objects, obj, is_static_lib),
735 .archive => |obj| if (self.base.isStaticLib()) {
736 // Ignore static library inputs when generating a static library.
737 } else {
738 try parseArchive(gpa, io, diags, &self.file_handles, &self.files, target, debug_fmt_strip, default_sym_version, &self.objects, obj);
739 },
737740 .dso => |dso| try parseDso(gpa, io, diags, dso, &self.shared_objects, &self.files, target),
738741 }
739742}
......@@ -1083,7 +1086,6 @@ fn parseArchive(
10831086 default_sym_version: elf.Versym,
10841087 objects: *std.ArrayList(File.Index),
10851088 obj: link.Input.Object,
1086 is_static_lib: bool,
10871089) !void {
10881090 const tracy = trace(@src());
10891091 defer tracy.end();
......@@ -1092,17 +1094,14 @@ fn parseArchive(
10921094 var archive = try Archive.parse(gpa, io, diags, file_handles, obj.path, fh);
10931095 defer archive.deinit(gpa);
10941096
1095 const init_alive = if (is_static_lib) true else obj.must_link;
1096
10971097 for (archive.objects) |extracted| {
10981098 const index: File.Index = @intCast(try files.addOne(gpa));
10991099 files.set(index, .{ .object = extracted });
11001100 const object = &files.items(.data)[index].object;
11011101 object.index = index;
1102 object.alive = init_alive;
1102 object.alive = obj.must_link;
11031103 try object.parseCommon(gpa, io, diags, obj.path, obj.file, target);
1104 if (!is_static_lib)
1105 try object.parse(gpa, io, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
1104 try object.parse(gpa, io, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
11061105 try objects.append(gpa, index);
11071106 }
11081107}
src/link/Lld.zig+2-2
......@@ -306,8 +306,8 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) link.Error!void {
306306
307307 try object_files.ensureUnusedCapacity(arena, comp.link_inputs.len);
308308 for (comp.link_inputs) |input| switch (input) {
309 .res, .dso, .dso_exact => {}, // shared libraries should not be included in static archives
310 .object, .archive => {
309 .dso, .dso_exact, .archive => {}, // static archives should not contain shared libraries or other static archives
310 .res, .object => {
311311 const path = try input.path().?.toStringZ(arena);
312312 object_files.appendAssumeCapacity(path);
313313 },
src/link/MachO.zig+5
......@@ -992,6 +992,11 @@ fn addArchive(self: *MachO, lib: link.Input.Object, handle: File.HandleIndex, fa
992992 const tracy = trace(@src());
993993 defer tracy.end();
994994
995 if (self.base.isStaticLib()) {
996 // Ignore static library inputs when generating a static library.
997 return;
998 }
999
9951000 const gpa = self.base.comp.gpa;
9961001
9971002 var archive: Archive = .{};