Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Package Manager dynamic library

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: "[email protected]: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?

like image 642
Mark Avatar asked Sep 25 '19 01:09

Mark


People also ask

Is Swift package manager dynamic or static?

For example the Swift Package Manager prefers to use static linking, but Xcode will try to build SPM packages as dynamic dependencies.

Does Swift have a package manager?

The Swift Package Manager is a tool for managing the distribution of Swift code. It's integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.

What is dynamic library in Swift?

Dynamic library - . dylib (aka dynamic shared library, shared object, dynamically linked library[doc]) is dynamically linked with the app's executable at load or runtime, but not copied into it. On practice app's package will contain Frameworks folder with . dylib file. All iOS and macOS system libraries are dynamic .


1 Answers

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:

enter image description here

like image 144
Mark Avatar answered Sep 21 '22 10:09

Mark