Duplicate symbols - runtime crash with local SwiftPM package dependencies

I am creating local swift packages to modularize generated GraphQL binding types for my project, but I'm running into a duplicate symbols runtime warning

objc[15506]: Class CommonGraphQL19MyMutation is implemented in both
/Library/Developer/Xcode/DerivedData/MyWorkspace-gkepkcvrwzwxmzcclfsfnzqmndhy/Build/Products/Debug-iphonesimulator/PackageFrameworks/
CommonGraphQL.framework/CommonGraphQL
and
/Library/Developer/Xcode/DerivedData/MyWorkspace-gkepkcvrwzwxmzcclfsfnzqmndhy/Build/Products/Debug-iphonesimulator/PackageFrameworks/
AppAGraphQL.framework/AppAGraphQL. One of the two will be used. Which one is undefined.

I'm also getting a crash in the Apollo library

Could not cast value of type 'Swift.AnyHashable' (0x1f06d4898) to 'ApolloAPI.GraphQLEnum<CommonGraphQL.CommonGraphQL.MyType>' (0x11699a288).

The package set up is like so:

products: [
        .library(name: "CommonGraphQL", type: .dynamic, targets: ["CommonGraphQL"]),
        .library(name: "AppAGraphQL", type: .dynamic, targets: ["AppAGraphQL"]),
        .library(name: "AppBGraphQL", type: .dynamic, targets: ["AppBGraphQL"]),
    ],
  
    targets: [
        .target(
            name: "CommonGraphQL",
            dependencies: [
                .product(name: "Apollo", package: "apollo-ios"),
                .product(name: "ApolloAPI", package: "apollo-ios"),
            ]
        ),
        .target(
            name: "AppAGraphQL",
            dependencies: [
                "CommonGraphQL",
                .product(name: "Apollo", package: "apollo-ios"),
                .product(name: "ApolloAPI", package: "apollo-ios"),
            ]
        ),
        .target(
            name: "AppBGraphQL",
            dependencies: [
                "CommonGraphQL",
                .product(name: "Apollo", package: "apollo-ios"),
                .product(name: "ApolloAPI", package: "apollo-ios"),
            ]
        ),

My project dependency graph is roughly:

Core.framework (dylib)
- links to CommonGraphQL.dylib (not embedded)

CoreUI.framework (dylib)
- links to Core, CommonGraphQL.dylib (not embedded)

AppA
- links to Core, CoreUI, AppAGraphQL.dylib (embedded)

AppB
 - links to Core, CoreUI, AppBGraphQL.dylib (embedded)

I did some background reading on dynamic vs static linking, and so I assumed by making my GQL targets dynamic, I would avoid these duplicate symbols by only embedding my AppAGraphQL and AppBGraphQL packages in my AppA and AppB targets (respectively)

Observations

  • The runtime crashes only seem to occur when I also see the duplicate symbols warning in the logs

Questions

  1. Why would I see duplicate symbol warnings when both my CommonGraphQL and AppXGraphQL targets are dynamically linked?

  2. Am I over-indexing on these duplicate symbol warnings? It's odd to me that my crash is occuring in the Apollo library

Any help would be greatly appreciated!

"AppAGraphQL" and "AppBGraphQL" are linking "CommonGraphQL" statically in your example, since it isn't possible to use products from the same package, only targets.

So in this example, I see that Apollo defines a product Apollo-Dynamic that is listed as type: .dynamic. I'm guessing that if I were to swap out Apollo with Apollo-Dynamic, my target AppAGraphQL would dynamically link to Apollo.

Would I need to create separate packages in my Xcode structure to be able to do something similar with my own local code? I have come across similar issues, although I'm not sure if it maps 1-1 with my situation.

"AppAGraphQL" and "AppBGraphQL" are linking "CommonGraphQL" statically in your example, since it isn't possible to use products from the same package, only targets.

So if we were to use two local packages

// CommonGraphQL Package.swift
.library(name: "CommonGraphQL-Dynamic", type: .dynamic, targets: ["CommonGraphQL"])

and a separate package

// AppGraphQL Package.swift

products: [
    .library(name: "AppAGraphQL", type: .dynamic, targets: ["AppAGraphQL"])
],
...
targets: [
    .target(name: "AppAGraphQL", dependencies: [
        .product(name: "CommonGraphQL-Dynamic", package: "CommonGraphQL"),
    ]
]

we might be able to use a dynamic product to satisfy the dependency on CommonGraphQL instead?

Can confirm that splitting our local packages into two separate modules (two Package.swift), one for CommonGraphQL, and one for AppGraphQL, and marking everything as type: .dynamic seems to resolve the duplicate symbols issue!