Swift包管理器动态库

24

我最近把我的一堆框架转换为使用Swift Package Manager。我的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"]),
    ]
)
由于该库曾经是一个框架,我想将其作为动态库(.dylib)链接到我的应用程序中。根据软件包文档中的库产品定义,如果需要,我可以指定我的库的type.dynamic

库的可选类型用于确定如何链接到库。将此参数留空以让Swift Package Manager选择静态或动态链接(建议)。如果不支持两种链接类型,请使用.static或.dynamic。

如果我将其保留为空,Xcode在将库链接到我的应用程序项目时默认构建一个静态库,这不是我想要的。
如果我在我的库的Package.swift中将类型设置为.dynamic,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.

我也没看到简单的方法来将.dylib添加到复制文件构建阶段中...

那么,要求SPM通过Xcode构建和链接动态库的推荐方法是什么?这是尚未支持的功能吗?

1个回答

24

我搞明白了!

如果你想创建一个框架库,你需要在Package.swift中强制它成为一个框架库,像这样:

.library(name: "MDFToolbox", type: .dynamic, targets: ["MDFToolbox"])
一旦完成上述步骤,您将在链接到库的项目的Xcode项目设置中看到嵌入选项。选择目标时,请向下滚动到“Frameworks、Libraries和Embedded Content”部分。您应该会看到一个选项来嵌入您的动态库依赖项:

enter image description here


9
关于这个问题,需要注意的是,Xcode目前还不支持链接到SPM动态库而不将其嵌入,因此如果您有多个目标使用了同一个库,就会出现重复符号的情况。您可以选择使用其他依赖管理器、从档案中移除重复嵌入的库,或者使用一个包含所有SPM依赖项的Umbrella Framework。 - Mark
1
你说的“Xcode还不支持链接到SPM动态库而不嵌入它”是什么意思?我注意到,如果直接编辑.pbxproj文件,可以删除嵌入步骤,现在它会显示“不要嵌入”,除非你有SwiftUI预览,否则一切似乎都按预期工作。这对我的应用程序真的很有问题,因为如果我们只是不得不制作包装器框架或多次嵌入东西,那使用SPM的意义何在?这似乎是苹果的一个巨大疏忽!为什么? - scaly
是的,你可以直接编辑项目文件,但这并不是一个可扩展的解决方案,显然也存在一些边缘情况。希望苹果能尽快修复这个问题! - Mark
2
我认为项目文件本身并不是可扩展的解决方案,如果你有太多的Swift包需要考虑规模问题,那么你可能有太多的包了。话虽如此,如果你只是在Build Phases中点击“嵌入框架”旁边的X按钮,删除整个构建阶段,那么被嵌入和链接的Swift包现在将只被链接 - 不需要直接编辑项目文件:D - scaly
3
如果您不指定“.dynamic”,那么Xcode将在依赖它的所有地方都嵌入该框架,导致您所描述的有关删除重复嵌入库的问题。如果您确实指定了“.dynamic”(截至Xcode 12.5),则可以手动从嵌入步骤中删除它。但我强烈建议不要使用Swift Packages替代Xcode项目文件来处理本地依赖关系,因为这会带来一系列错误和限制等问题。请注意! - scaly
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接