@@ -249,6 +249,7 @@ pub fn link(self: *MachO) !void {
249249 }
250250
251251 try self .parseInputFiles ();
252+ try self .dedupDylibs (resolved_objects .items );
252253 try self .parseDependentDylibs (arena , lib_dirs .items , framework_dirs .items );
253254
254255 if (! self .options .relocatable ) {
@@ -832,6 +833,58 @@ fn isHoisted(self: *MachO, install_name: []const u8) bool {
832833 return false ;
833834}
834835
836+ fn dedupDylibs (self : * MachO , resolved_objects : []const LinkObject ) ! void {
837+ const tracy = trace (@src ());
838+ defer tracy .end ();
839+
840+ var map = std .HashMap (Dylib .Id , void , struct {
841+ pub fn hash (ctx : @This (), id : Dylib .Id ) u64 {
842+ _ = ctx ;
843+ return id .hash ();
844+ }
845+
846+ pub fn eql (ctx : @This (), id : Dylib .Id , other : Dylib .Id ) bool {
847+ _ = ctx ;
848+ return id .eql (other );
849+ }
850+ }, std .hash_map .default_max_load_percentage ).init (self .allocator );
851+ defer map .deinit ();
852+ try map .ensureTotalCapacity (@intCast (self .dylibs .items .len ));
853+
854+ var marked_dylibs = std .ArrayList (bool ).init (self .allocator );
855+ defer marked_dylibs .deinit ();
856+ try marked_dylibs .ensureTotalCapacityPrecise (self .dylibs .items .len );
857+ marked_dylibs .resize (self .dylibs .items .len ) catch unreachable ;
858+ @memset (marked_dylibs .items , false );
859+
860+ for (self .dylibs .items , marked_dylibs .items ) | index , * marker | {
861+ const dylib = self .getFile (index ).dylib ;
862+ const cmd_object = resolved_objects [@intFromEnum (index )];
863+
864+ const gop = map .getOrPutAssumeCapacity (dylib .id .? );
865+
866+ if (! gop .found_existing ) continue ;
867+
868+ if (cmd_object .tag == .lib ) {
869+ self .warn ("ignoring duplicate libraries: {}" , .{cmd_object });
870+ }
871+
872+ marker .* = true ;
873+ }
874+
875+ var i : usize = 0 ;
876+ while (i < self .dylibs .items .len ) {
877+ const index = self .dylibs .items [i ];
878+ const marker = marked_dylibs .items [i ];
879+ if (marker ) {
880+ _ = self .dylibs .orderedRemove (i );
881+ _ = marked_dylibs .orderedRemove (i );
882+ self .files .items (.data )[@intFromEnum (index )].dylib .deinit (self .allocator );
883+ self .files .set (@intFromEnum (index ), .none );
884+ } else i += 1 ;
885+ }
886+ }
887+
835888fn parseDependentDylibs (
836889 self : * MachO ,
837890 arena : Allocator ,
0 commit comments