You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

闭源二进制动态框架依赖开源框架,运行时库加载失败如何解决?

Swift Package 动态二进制框架依赖运行时加载问题

我在为依赖多个非二进制开源动态框架的闭源二进制动态框架编写Package.swift文件时遇到了问题。

当前的Package.swift内容如下:

// swift-tools-version: 5.8
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
import Foundation

let package = Package(
    name: "MyLibrary",
    platforms: [
        .iOS(.v12)
    ],
    products: [
        .library(
            name: "MyLibrary",
            targets: ["MyLibraryWrapper"]
        ),
    ],
    dependencies: [
        .package(url: "<dependency-url>", branch: "master"),
    ],
    targets: [
        .target(
            name: "MyLibraryWrapper",
            dependencies: [
                .target(name: "MyLibrary"),
                .product(name: "<dependency-product-name>", package: "<dependency-package-name>")
            ],
            path: "MyLibraryWrapper"
        ),
        .binaryTarget(
            name: "MyLibrary",
            url: "<url-to-xcframework-zip>",
            checksum: "<checksum>"
        )
    ]
)

这个包能编译成功,但添加到任意应用后会出现以下运行时错误:

Library not loaded: @rpath/<dependency-product-name>.framework

我目前知道的解决方法是fork每个依赖的源码项目,然后把每个库的library类型声明为.dynamic,但这样需要维护每个依赖的fork,我不想这么做。有没有更优、更简洁的解决方案?


补充说明

  • 必须声明MyLibraryWrapper target,因为binaryTarget没有提供dependencies参数,无法直接为二进制框架添加依赖。
  • MyLibraryWrapper对应的目录里只有一个空源码文件,没有其他内容。
  • 我试过把MyLibrary的产品类型声明为.dynamic,希望SPM能自动动态链接MyLibrary及其依赖,但会触发"Multiple commands produce MyLibrary.framework"编译错误。
  • MyLibrary所依赖的非二进制动态框架在它们的Package.swift里没有指定明确的type,这符合Apple的建议:建议不要显式声明库类型,让Swift Package Manager根据使用者的偏好选择静态或动态链接。

解决方案

方法1:强制依赖动态链接(适配性稍弱)

在MyLibraryWrapper的target配置中添加编译标记,强制SPM将依赖库以动态方式链接:

.target(
    name: "MyLibraryWrapper",
    dependencies: [
        .target(name: "MyLibrary"),
        .product(name: "<dependency-product-name>", package: "<dependency-package-name>")
    ],
    path: "MyLibraryWrapper",
    swiftSettings: [
        .unsafeFlags(["-Xlinker", "-add_ast_path", "$(TARGET_BUILD_DIR)/<dependency-product-name>.framework/Modules/<dependency-product-name>.swiftmodule/x86_64-apple-ios-simulator.swiftmodule"])
    ]
)

注意:这种方式需要针对不同CPU架构做适配,通用性有限。

方法2:用Package.resolved锁定依赖动态特性(推荐)

  1. 本地创建临时项目,引入你的MyLibrary包和所有依赖,在Xcode中将项目的Build Settings→MACH_O_TYPE设为dynamiclib,强制以动态方式编译所有依赖。
  2. 编译成功后,将临时项目根目录下的Package.resolved文件复制到你的MyLibrary包根目录中。
  3. 其他项目引入MyLibrary时,SPM会遵循Package.resolved的配置,自动以动态方式链接依赖库,避免运行时找不到框架的问题。

方法3:调整产品类型并规避编译冲突

修改products中MyLibrary的类型为.dynamic,同时调整target结构避免重复生成框架:

products: [
    .library(
        name: "MyLibrary",
        type: .dynamic,
        targets: ["MyLibraryWrapper"]
    ),
],

同时在MyLibraryWrapper的编译设置中,将FRAMEWORK_SEARCH_PATHS指向二进制框架的路径,确保编译时不会出现冲突。此方法需保证二进制框架本身的依赖逻辑正确。


内容的提问来源于stack exchange,提问作者ale-gen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 16:46:27