What is the recommended approach for distributing an XCFramework that uses common third-party dependencies (like Google Maps) when client apps may also use the same dependencies, resulting in duplicate symbol conflicts?
I'm developing a closed-source SDK distributed as an XCFramework. My SDK internally uses Google Maps for mapping functionality. However, when clients integrate my XCFramework into their apps that also use Google Maps, we encounter duplicate symbol errors.
What I've Tried: Static vs Dynamic Linking: Both approaches result in conflicts
Static linking: Google Maps symbols compiled into my binary
Dynamic linking: GoogleMaps.framework bundled with my XCFramework
Build Configuration:
Set "Build Libraries for Distribution" = YES
Tried various linking strategies
Architecture Changes:
Used @implementation_only import
Wrapped code with #if canImport(GoogleMaps)
However, the dependencies still get linked at build time
There isn’t a great answer to this in the general case. Ignore the build-time issue right now, and focus on the run-time one:
- Imagine an app A which depends on F.
 - It also links to a library L which depends on F.
 - The process running A can’t load two different copies of F [1].
 - Which means L must use a specific version of F, and A must agree to use the same version.
 
If F supports ABI compatibility then you can resolve this conundum by having A embed the newest version of F. But not all frameworks support ABI compatibility.
IMPORTANT ABI compatibility has both technical and social aspects. You can’t tell just by looking at the framework whether it’ll be ABI compatible in the long term. You’ll also need a promise from the framework author.
Coming back to the build side of this, that presents significant practical challenges:
Static linking: Google Maps symbols compiled into my binary
Don’t do that. It’ll result in two copies of the framework being loaded in the client app’s process, and that’s unlikely to end well.
Dynamic linking: GoogleMaps.framework bundled with my XCFramework
That won’t work either, at least on iOS. You can’t nest frameworks on iOS. All frameworks must be present at the top level of the app. So, if your library relies on a framework then you must inform your clients of that so that they can add that framework to their app.
I talk about this stuff in much more detail in this thread.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] In theory this is possible, but the practical concerns means that it’ll only work under very limited circumstances. And even if you get it to work, you’re paying both an on-disk and in-memory cost for having two copies of the framework.