Swift PM support for binary packages which depends on another open source package

Hi,

We are trying to distribute our binary framework with Swift PM. Swift PM does support distributing binary packages but our scenario is a bit different.

We have 3 different packages

  1. Package A => Swift based open source project
  2. Package B => Another Swift based open source project
  3. Package C => Closed source project distributed as a binary written in ObjC

Package C and Package A both depend on Package B.

I tried different posts here before posting a new one
SwiftPM - Binary target with sub-dependencies - Using Swift - Swift Forums

But in my case the problem is the dependency is on an open source project which my binary relies on Swift PM compiling it.
When Swift PM builds the open source Package B it does not install the bridging header file which the binary framework (written in ObjC) depends on.

It could be because of this in Swift PM source code here

    // We currently deliberately do not support Swift ObjC interface headers.
    settings[.SWIFT_INSTALL_OBJC_HEADER] = "NO"

swift-package-manager/PIFBuilder.swift at main ยท apple/swift-package-manager (github.com)

ObjC header is emitted because this is enabled by SwiftPm -emit-objc-header and -emit-objc-header-path is enabled but not installing it in the correct place ?

This is what my current Package.swift looks like

// swift-tools-version:5.3
import PackageDescription

let package = Package(
    name: "PackageC",
    platforms: [
        .macOS(.v11), .iOS(.v12)
    ],
    products: [
        .library(name: "PackageC", targets: ["PackageCWrapper"])
    ],
    dependencies: [
            .package(name: "PackageB", url: "https://github.com/SwiftPM-PackageB.git", from: "1.0.2")
    ],
    targets: [
        .binaryTarget(
            name: "PackageC",
            url: "https://PackageC-2.2.0.zip",
            checksum: "3dfc0b9e1ae79e1d8df622f39b1c85db8998518d2c02eb1fe6b9ae58333c6de9"
        ),
        .target(
            name: "PackageCWrapper",
            dependencies: [
                .target(name: "PackageC"),
                .product(name: "PackageB", package: "PackageB")
            ],
            path: "PackageCWrapper"
        )
    ],
    swiftLanguageVersions: [.v5]
)

I am assuming Swift PM does not support this scenario yet ?

xcframework doesn't support source dependencies, in that sense when you have a binaryTarget โ€” it cannot have other dependencies in source.

The only thing that comes to mind is to bundle your source dependency with your own source code and make the xcframework out of both (e.g. basically include your dependency with your own source). But, I can't say I've tried that myself โ€” in general using binary targets with SwiftPM seems in a pre-release state to me.

1 Like

I dont think having the dependency inside xcframework is a good idea. Because that kind of goes down another rabit hole :slight_smile: Problem happens when an object from the open source code B passed down to Package C which might have another version of Package A bundled inside Package C.

We work around the binaryTarget dependency limitation by wrapping the binaryTarget in a dedicated "Wrapper" target that provides the dependencies. See an example here.

I did look at that example, but it looks like in your case you do not depend on a Swift open source project where you rely on SwiftPM to compile the source code ?