SwiftPM - Binary target with sub-dependencies

Were you able to find a solution for this problem?

I created a package with a wrapper target, where my binary framework has a dependency on TrustKit. But when I use the swift package in a sample app, the app keeps crashing with the error message - Library not loaded: @rpath/TrustKit.framework/TrustKit

I created a package with a wrapper target, where my binary framework has a dependency on TrustKit. But when I use the swift package in a sample app, the app keeps crashing with the error message - Library not loaded: @rpath/TrustKit.framework/TrustKit

I could not find a solution. Same issue as you.

A binary library depends on other third-party libraries, which can be written like this, and the libraries will be downloaded automatically

// swift-tools-version:5.8

import PackageDescription

let package = Package(
name: "HKSDK",
platforms: [
.iOS(.v13)
],
products: [
.library(
name: "HKSDK",
targets: ["HKSDKTarget"]
),
],
dependencies: [
.package(url: "GitHub - facebook/facebook-ios-sdk: Used to integrate the Facebook Platform with your iOS & tvOS apps.", from: "14.0.0"),
.package(url: "GitHub - adjust/ios_sdk: This is the iOS SDK of", from: "4.33.6")
],
targets: [
.binaryTarget(
name: "HKSDK",
url: "https://7e04-2605-52c0-2-4a0-00.ngrok-free.app/HKSDK.xcframework.zip",
checksum: "684c6dac81ee643c93bf3d645e110c023309ed7daea18e44b577e153e16a8e9d"
),
.target(
name: "HKSDKTarget",
dependencies: [
.target(name: "HKSDK"),
.product(name: "FacebookLogin", package: "facebook-ios-sdk"),
.product(name: "Adjust", package: "ios_sdk"),
]
)
]
)

1 Like

Confirm that this works, I've got a similar setup

Package.swift

// swift-tools-version: 5.8
import PackageDescription

let package = Package(
    name: "Name",
    platforms: [
        .iOS(.v14)
    ],
    products: [
        .library(name: "NameSDK", targets: ["NameSDKTarget"])
    ],
    dependencies: [
        .package(url: "https://github.com/Some/some.git", exact: "1.0.0")
    ],
    targets: [
        .binaryTarget(name: "NameSDK", path: "../../artifacts/NameSDK.xcframework.zip"),
        .target(
            name: "NameSDKTarget",
            dependencies: [
                .target(name: "NameSDK"),
                .product(name: "some", package: "some")
            ])
    ]
)

The files structure should be like this

Package.swift
Sources
|- NameSDKTarget
   |- Sources.swift

In my case once this SPM with binary framework is integrated in HostApp it is giving me duplicate symbols warnings for some, as it is finding it within NameSDK.xcframework as well as in my HostApp.

Here is the snippet of warning:

objc[452]: Class _TtC20FirebaseCoreInternal19HeartbeatController is implemented in both /Users/Some/Library/Developer/Xcode/DerivedData/HostAppWithThirdPartyFrameworks/Build/Products/Debug-iphonesimulator/FrameworkWithThirdParty.framework/FrameworkWithThirdParty (0x104a6) and /Users/Some/Library/Developer/CoreSimulator/Devices/8450F266-DEA2-4BDC-BC33-E46FD7E905D0/data/Containers/Bundle/Application/907819B6-FA4D-42E4-9BCA-9B54F33C2453/HostAppWithThirdPartyFrameworks.app/HostAppWithThirdPartyFrameworks (0x10219bcb8). One of the two will be used. Which one is undefined.

Here FirebaseAnalytics is some, FrameworkWithThirdParty.xcframework is NameSDK.xcframework. HostAppWithThirdPartyFrameworks is the app in which I am integrating xcframework as SPM with binary framework.

Here is the Package.swift of SPM with binary framework:

let package = Package(
    name: "BinarySdkWithThirdParty",
    platforms: [.iOS(.v13)],
    products: [
        // Products define the executables and libraries a package produces, making them visible to other packages.
        .library(
            name: "BinarySdkWithThirdParty",
            targets: ["BinarySdkWithThirdParty"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        .package(url: "https://github.com/highcharts/highcharts-ios", "10.1.0"..<"10.3.2"),
        .package(url: "https://github.com/firebase/firebase-ios-sdk", .exact("10.17.0"))
    ],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .target(
            name: "BinarySdkWithThirdParty",
            dependencies: [
                .target(name: "FrameworkWithThirdParty"),
                .product(name: "Highcharts", package: "highcharts-ios"),
                .product(name: "FirebaseAnalytics", package: "firebase-ios-sdk"),
                .product(name: "FirebaseCrashlytics", package: "firebase-ios-sdk"),
                .product(name: "FirebaseDynamicLinks", package: "firebase-ios-sdk")
            ]
        ),
        .binaryTarget(
            name: "FrameworkWithThirdParty",
            path: "./Sources/FrameworkWithThirdParty.xcframework"
        ),
        .
    ]
)

Please note that FrameworkWithThirdParty also requires these libraries so I linked these as optional under Link Binary with Libraries.

Am I missing anything over here?

FYI I opened a feature request in Swift Github: Support `dependencies` parameter for the binary targets · Issue #71044 · apple/swift · GitHub

1 Like