ale-gen
ale-gen

Reputation: 49

Can I define my binary framework which has open source dependencies without specifying the 'type' parameter in each of my framework's dependencies?

I'm having a problem defining the Package.swift file for my binary closed-source dynamic framework which depends on a number of non-binary open-source dynamic frameworks.

My Package.swift file looks like this:

// swift-tools-version: 5.8
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
import Foundation

let package = Package(
    name: "MyLibrary",
    platforms: [
        .iOS(.v12)
    ],
    products: [
        .library(
            name: "MyLibrary",
            targets: ["MyLibraryWrapper"]
        ),
    ],
    dependencies: [
        .package(url: "<dependency-url>", branch: "master"),
    ],
    targets: [
        .target(
            name: "MyLibraryWrapper",
            dependencies: [
                .target(name: "MyLibrary"),
                .product(name: "<dependency-product-name>", package: "<dependency-package-name>")
            ],
            path: "MyLibraryWrapper"
        ),
        .binaryTarget(
            name: "MyLibrary",
            url: "<url-to-xcframework-zip>",
            checksum: "<checksum>"
        )
    ]
)

The package builds successfully. However, when I add it to any app, I get the following runtime error:

Library not loaded: @rpath/<dependency-product-name>.framework

The only workaround I know is to fork the source project of each of my framework's dependencies and to declare the type of each library as .dynamic. This requires me to maintain a fork for each of my framework's dependencies. This is not something I'm keen on.

Is there is a better, simpler solution to this problem?

Notes

  1. I need to declare the MyLibraryWrapper target in my Package.swift file because the binaryTarget(name:url:checksum:) method does not offer a dependencies parameter.
  2. The MyLibraryWrapper directory which the MyLibraryWrapper target declares as its path contains a single empty source file and nothing else.
  3. I tried declaring the type of MyLibrary as .dynamic via the library(name:type:targets:) method. I was hoping that Swift Package Manager would do the right thing of dynamically linking MyLibrary and its dependencies. Sadly, declaring the type of MyLibrary as .dynamic results in a "Multiple commands produce MyLibrary.framework" build error.
  4. The non-binary dynamic frameworks which MyLibrary depends on do not specify an explicit type value in their Package.swift files. This is based on Apple's recommendation in the library(name:type:targets:) method documentation: "It’s recommended that you don’t explicitly declare the type of library, so Swift Package Manager can choose between static or dynamic linking based on the preference of the package’s consumer."

Upvotes: 2

Views: 153

Answers (0)

Related Questions