Swift 包管理器动态库

Mar*_*ark 17 swift swift-package-manager xcode11

我最近将一堆框架转换为使用 Swift 包管理器。我Package.swift看起来像这样:

// 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"]),
    ]
)
Run Code Online (Sandbox Code Playgroud)

由于该库曾经是一个框架,我想将它作为动态库 ( .dylib)链接到我的应用程序中。根据 Package 文档中的库产品定义,如果我愿意,我可以指定type我的库.dynamic

用于确定如何链接到库的库的可选类型。不指定此参数以让 Swift 包管理器在静态或动态链接之间进行选择(推荐)。如果您不支持这两种链接类型,请为此参数使用 .static 或 .dynamic。

如果我将它保留为nil,当我在我的应用程序项目中链接这个包时,Xcode 默认构建一个静态库,这不是我想要的。

如果我.dynamic在库的 Package.swift中将类型设置为,Xcode 会构建一个.dylib,但它不会嵌入到应用程序中,从而导致链接器错误:

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.
Run Code Online (Sandbox Code Playgroud)

我也看到没有简单的方法可以将其添加.dylib到复制文件构建阶段...

那么,要求 SPM 通过 Xcode 构建和链接动态库的推荐方式是什么?这是尚不支持的东西吗?

Mar*_*ark 16

我想到了!

如果你想创建一个框架库,你需要强制它是Package.swift这样的:

.library(name: "MDFToolbox", type: .dynamic, targets: ["MDFToolbox"])
Run Code Online (Sandbox Code Playgroud)

完成此操作后,您将在链接到库的项目的 Xcode 项目设置中看到一个嵌入选项。选择目标时,向下滚动到该Frameworks, Libraries, and Embedded Content部分。您应该会看到一个选项来嵌入您的动态库依赖项:

在此处输入图片说明

  • 请注意,Xcode 尚不支持链接到 SPM 动态库而不嵌入它,因此如果您有多个使用同一库的目标,您将获得重复的符号。您需要使用不同的依赖项管理器,从存档中删除重复的嵌入式库,或者使用伞式框架来包含所有 SPM 依赖项。 (6认同)
  • 如果您不指定“.dynamic”,那么 Xcode 将在依赖于它的任何地方嵌入框架,从而导致与您描述的必须删除重复的嵌入库相同的问题。如果您确实指定了“.dynamic”,那么(从 Xcode 12.5 开始)您可以手动从嵌入步骤中删除。不过,我强烈建议不要使用 Swift Packages 而不是 Xcode 项目文件来获取本地依赖项,因为这样的错误和限制是一场噩梦。被警告! (3认同)
  • 好吧,我认为项目文件本身并不是一个可扩展的解决方案,如果你有这么多 Swift 包,那么规模就是一个因素,那么你就有太多的包了。话虽这么说,如果您只需单击“构建阶段”中“嵌入框架”上的 X 按钮,删除整个构建阶段,那么嵌入和链接的 Swift 包现在将被链接,无需直接编辑项目文件:D (2认同)