Search code examples
swiftxcodeswift-package-managerxcframeworkswift-package

Swift Package with dependencies giving error in console


I am trying to create a Swift Package from a custom xcframework that I'm building for a client. The framework has a dependency on a couple of 3rd party frameworks. I've read about how even though binary frameworks don't support dependencies directly, there is way to do this with a 'wrapper' target, so this is what I came up with for Package.swift:

let package = Package(
    name: "SBFramework",
    platforms: [
            .iOS(.v16)
        ],
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "SBFramework",
            targets: ["SBFramework-Target"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        .package(url: "https://github.com/apple/swift-algorithms.git", from: "1.0.0"),
        .package(url: "https://github.com/fakeurl/NumbersKit.git", from: "1.0.0")
    ],
    targets: [
        .target(name: "SBFramework-Target",
                    dependencies: [
                        .target(name: "SBFramework", condition: .when(platforms: [.iOS])),
                        .product(name: "Algorithms", package: "swift-algorithms"),
                        .product(name: "NumbersKit", package: "NumbersKit")
                    ]
                ),
        .binaryTarget(name: "SBFramework", path: "SBFramework.xcframework")
    ]
)

This works, and I can add the package to my test project and import the framework and it links against the dependancies as well, and functionally it all works correctly.

The problem is that every time I run the app, it also shows these messages in the Xcode console:

objc[845]: Class _TtC14NumbersKitP33_0FE53357E470A64027C8F0CAF7B114C812BundleFinder is implemented in both /private/var/containers/Bundle/Application/EEE0C0A6-4FF5-44BC-B81A-F95401219D32/TestSBFrameworkImport.app/Frameworks/SBFramework.framework/SBFramework (0x100f4aaf0) and /private/var/containers/Bundle/Application/EEE0C0A6-4FF5-44BC-B81A-F95401219D32/TestSBFrameworkImport.app/TestSBFrameworkImport (0x10069b778). One of the two will be used. Which one is undefined.

There's multiple lines for different classes that show the "Class X is implemented in both [.../MyApp.app/Frameworks/MyFramework.framework/MyFramework/] and [.../MyApp.app/MyApp]". I'm not sure how to avoid this problem, and whether this could cause a problem down the line. The framework that is the basis for this Swift Package is linked against the two dependencies, because I wouldn't be able to build the framework without them. But they also need to be added to the app target (at least, and if I don't, I get a run-time crash when using the NumbersKit initializer.

Is there a good way to resolve this issue? I'm worried this will could be a problem for the client when they integrate it into their app, and the app is deployed to 1000s of devices.


Solution

  • Yes, this is a real problem, and you should fix it. It can create very subtle errors if the implementation conflict.

    I expect that you're linking NumbersKit both in your framework and also in your app. You must not do this. NumbersKit must be linked exactly one time. This is likely due to mixing SPM with direct linking rather than letting SPM do all the work. If your main app also needs NumbersKit, make sure to add it as a package, just like your framework is doing, so SPM can resolve a single copy to link.