I have an app that links to two dynamic frameworks which both link to the same static library, as follows:
|--App
|--DynamicFramework1
|--StaticLibrary
|--DynamicFramework2
|--StaticLibrary <- the same library that DynamicFramework1 links to
The static library's symbols are included in each framework's binary because of the way dynamic frameworks are built by default. The app therefore finds duplicates of the static library's symbols at runtime.
Is it possible to link a dynamic framework to a static library (and to reference the classes and methods of the static library within the dynamic framework) in a manner that symbols from the static library are excluded from the dynamic framework's binary?
My hope in doing this is that the binary of each of the two dynamic frameworks will exclude the symbols of the static library. I will then make it the responsibility of the app to link to the static library directly.
Notes
- I have tried linking my dynamic framework with the static library in two different ways thus far: (1) I added the static library to my framework's "Link Binary with Libraries" Build Phase; and (2) I referenced the static library in my framework's "Other Linker Flags" Build Setting. Both result in the static library's symbols being included in the framework's binary.
- I am aware that changing a framework target's "Mach-O Type" from "Dynamic Framework" to "Static Library" will build the framework's binary without the symbols of the static libraries that it links to. I want to keep my frameworks as dynamic frameworks so that (1) I can benefit from how Xcode bundles together resources (strings, storyboards etc) automatically for dynamic frameworks; and (2) users of my framework can benefit from Mergeable Libraries in the near future.
- I am aware that I can solve this problem by changing the static library to a dynamic framework. I want to avoid this as much as possible since the static library is a binary from a third-party. I want to avoid forking the static library's source code and messing with its build scripts if I can.
- See here for a minimal Xcode project that demonstrates the problem.
Workaround solution
Let's say you have two dynamic frameworks named
DF1andDF2which both link to the same static library namedSL.I couldn't find a way to build
DF1andDF2in a manner that they link toSLwhilst excluding the symbols ofSLfrom their binaries.The best solution that I've been able to come up with thus far is as follows:
DF– that uses the-all_loadlinker flag and links toSL.1DF1andDF2to link toDFinstead ofSL.2DFas wellDF1andDF2.3In pictorial form, this is:
See here for a minimal Xcode project that demonstrates this workaround.
Addendum
The Benefits of mergeable libraries section of the Meet mergeable libraries talk from WWDC 2023 offered promise. In that talk, the speaker said:
I experimented with it but, sadly, I was not able to get it to solve the problem at hand. This question perfectly summarises my experience.
Footnotes
1The symbols ofSLwill be inDF's binary.2The symbols of
DFwill not be inDF1andDF2's binaries.3The app will now get the symbols of
SLfromDFonly.