Swift Package Manager dynamic library

2020-07-06 08:56发布

问题:

I've recently converted a bunch of my frameworks to use Swift Package Manager. My Package.swift looks something like this:

// swift-tools-version:5.1
import PackageDescription

let package = Package(
    name: "MDFToolbox",
    platforms: [
        .macOS(.v10_13), .iOS(.v12), .tvOS(.v12), .watchOS(.v3)
    ],
    products: [
        .library(name: "MDFToolbox", targets: ["MDFToolbox"])
    ],
    dependencies: [
        .package(url: "git@github.com:Swinject/Swinject.git", from: "2.7.0"),
    ],
    targets: [
        .target(name: "MDFToolbox", dependencies: ["Swinject"]),
    ]
)

Since the library used to be a framework, I'd like to link it in my app as a dynamic library (.dylib). According to the library product definition in the Package documentation, I can specify the type of my library to be .dynamic if I want:

The optional type of the library that is used to determine how to link to the library. Leave this parameter unspecified to let to let the Swift Package Manager choose between static or dynamic linking (recommended). If you do not support both linkage types, use .static or .dynamic for this parameter.

If I leave it as nil, Xcode defaults to building a static library when I link this package in my app project, which is not what I want.

If I set the type to .dynamic in my library's Package.swift, Xcode builds a .dylib, but it doesn't get embedded in the application, leading to a linker error:

dyld: Library not loaded: @rpath/libMDFToolbox.dylib
  Referenced from: /Users/mpdifran/Library/Developer/Xcode/DerivedData/Remind-eewbkbjpfrqbdwchjrbmrtxzsjew/Build/Products/Debug-maccatalyst/Remind.app/Contents/MacOS/Remind
  Reason: no suitable image found.  Did find:
    /Users/mpdifran/Library/Developer/Xcode/DerivedData/Remind-eewbkbjpfrqbdwchjrbmrtxzsjew/Build/Products/Debug-maccatalyst/libMDFToolbox.dylib: code signature in (/Users/mpdifran/Library/Developer/Xcode/DerivedData/Remind-eewbkbjpfrqbdwchjrbmrtxzsjew/Build/Products/Debug-maccatalyst/libMDFToolbox.dylib) not valid for use in process using Library Validation: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed.

I also see no easy way of adding the .dylib to a Copy Files Build Phase...

So what's the recommended way of asking SPM to build and link a dynamic library through Xcode? Is this something that is not yet supported?

回答1:

I figured it out!

If you want to create a framework library, you need to force it to be one in the Package.swift like so:

.library(name: "MDFToolbox", type: .dynamic, targets: ["MDFToolbox"])

Once you've done that, you'll see an embed option in the Xcode project settings of the project linking to the library. When selecting the target, scroll down to the Frameworks, Libraries, and Embedded Content section. You should see an option to embed your dynamic library dependencies: