Xcode 15 Duplicate Library Linker Warnings

Apple released Xcode 15 a couple weeks ago, after debuting the beta at WWDC in June, and shipping several beta updates over the summer.

I’ve been using the betas on my main work machine, and for months I’ve been mildly annoyed by warnings such as these:

ld: warning: ignoring duplicate libraries: '-lc++'
ld: warning: ignoring duplicate libraries: '-lz'
ld: warning: ignoring duplicate libraries: '-lxml2'
ld: warning: ignoring duplicate libraries: '-lsqlite3'

You may have run into similar warnings with other libraries, but warnings about these libraries in particular seem to be very widespread among developers. Even though I’ve been seeing them all summer, and have been annoyed by them, I made the same mistake I often make: assuming that the problem was too obvious not to be fixed before Xcode 15 went public. Alas.

So what happened in Xcode 15 to make these suddenly appear, and why haven’t they gone away? The root of the problem is not new. Something about the way Xcode infers library linkage dependencies has, for several years at least, led it to count dependencies from Swift packages separately from each package, and to subsequently pass the pertinent “-l” parameter to the linker redundantly for each such dependency. In other words, if you have three Swift packages that each require “-lc++”, Xcode generates a linker line that literally passes “-lc++ -lc++ -lc++” to the linker.

So why have the warnings only appeared now? One of the major changes in Xcode 15 was the introduction of a “completely rewritten linker”, which has been mostly transparent to me, but which was also to blame for an issue with Xcode 15 that prevented some apps from launching on older macOS (10.12) and iOS (14) systems. That bug has been addressed in the Xcode 15.1 beta 1 release, which was released this week.

Another change in the new linker was the introduction of a new warning flag, on by default: “-warn_duplicate_libraries”. Kinda obvious, isn’t it? It’s the new warning flag on the linker that is leading this old Xcode behavior to suddenly start spewing unwanted warnings.

Suppressing the Warnings

Luckily, in conjunction with the new warning flag, the linker also introduced a negating flag: “-no_warn_duplicate_libraries”. If you pass this flag to the linker, the warnings go away. When Xcode links your target, it actually invokes “clang”, which in turn invokes the linker (“ld”). So to see that the flag gets passed down to the lower lever linker, you need to specify it as a parameter to clang that instructs it to propagate the parameter to ld:

OTHER_LDFLAGS = -Wl,-no_warn_duplicate_libraries

OTHER_LDFLAGS is the raw name for the build setting that appears in Xcode as “Other Linker Flags”. The excerpt above is in the text-based Xcode configuration file (.xcconfig) format. You could also just paste the “-Wl,-no_warn_duplicate_libraries” argument into the Xcode build settings for your target, but generally speaking, using Xcode configuration files is better.

Supporting Multiple Xcode Versions

One problem with pasting the OTHER_LDFLAGS value in to Xcode’s build settings, is you won’t be able to build the project on Xcode 14 or earlier. Maybe that is OK, but if like me, you use an older version of Xcode on your build machine (or your dedicated continuous integration service does), you’ll run into a build error when the older linker fails to recognize the new option:

ld: unknown option: -no_warn_duplicate_libraries

So how can we suppress the warnings while using Xcode 15, while continuing to build without errors on older versions of Xcode? Xcode configuration files to the rescue! Because of the general utility of the method used to conditionalize build settings based on Xcode version, I have written a separate blog post describing this technique. Read Conditional Xcode Build Settings to learn more.

Addressing the Underlying Issue

I’m not going to fret too much about disabling the “warn_duplicate_libraries” option on the linker, because I don’t foresee it protecting me from many real-world pitfalls. However, all else being equal I would leave the warning on, because you never know.

I filed FB13229994 with a sample project demonstrating the problem. Hopefully at some point in the future Apple will update Xcode so that it effectively removes duplicated library names from its list of derived dependencies, alleviating the problem and allowing the warning to be enabled again.