Link 到 Swift 包内的 fat 静态库
Link to fat Static Library inside Swift Package
我正在尝试构建一个 Swift 包,它包装了一个用 C 编写的胖静态库:libndi_advanced_ios.a 来自 NewTek's Apple Advanced NDI SDK。
我在 link 将预编译库(只有头文件和 .a 二进制包可用)到我的 Swift 包时遇到问题。我做了很多研究并尝试了不同的解决方案,但其中 none 有效。这是一个快速列表:
也不能bundle in an XCFramework because libndi_advanced_ios.a supports multiple platforms (arm_v7, i386, x86_64, arm64) and xcodebuild -create-xcframework
return the error binaries with multiple platforms are not supported
(this solution is discussed on Swift Forums);
按照 SPM Documentation (that is outdated 中的建议在 targets
中使用 .linkedLibrary
给出警告 system packages are deprecated; use system library targets instead
,我什至不记得它是否构建成功;
尝试不同的标志和设置(如 linkerSettings
)并没有成功。也许我只是错过了正确的组合。
我可以 link 几十个 Whosebug 的问题和其他没有帮助的帖子,但它没有用 (a, b, c)。
目前我的配置是这样的:
With Package.swift
包含以下代码:
let package = Package(
name: "swift-ndi",
platforms: [.iOS(.v12)],
products: [
.library(
name: "swift-ndi",
targets: ["swift-ndi"])
],
dependencies: [],
targets: [
.target(name: "CiOSNDI", path: "Libraries"),
.target(
name: "swift-ndi",
dependencies: ["CiOSNDI"]),
.testTarget(
name: "swift-ndiTests",
dependencies: ["swift-ndi"]),
]
)
您可以在 alessionossa/swift-ndi 找到整个项目。
目前唯一的结果是一些警告和模块 CiOSNDI 不构建:
我也尝试 .systemLibrary(name: "CiOSNDI", path: "Libraries/"),
使用此配置:alessionossa/swift-ndi/tree/systemLibrary;但我收到这些错误:
注意
NDI_include
实际上是alias/symboliclink到/Library/NDI Advanced SDK for Apple/include
,而NDI_iOS_lib
指向/Library/NDI Advanced SDK for Apple/lib/iOS
.
我总是在更改 Package.swift
后清理构建文件夹。
更新 10/01/2022:libndi_advanced_ios.a 需要 libc++.tbd.在 Build Phases -> Link Binary With Libraries 的应用程序中 linked 很容易,但我不'知道如何在 Swift 包中 link。
需要用 .binary_target
指定二进制目标。见 docs and example here.
包裹在 .xcframework
中的静态库示例在文件命令中如下所示:
$ file GoogleAppMeasurement.xcframework/ios-arm64_armv7/GoogleAppMeasurement.framework/GoogleAppMeasurement
GoogleAppMeasurement.xcframework/ios-arm64_armv7/GoogleAppMeasurement.framework/GoogleAppMeasurement: Mach-O universal binary with 2 architectures: [arm_v7:current ar archive] [arm64]
GoogleAppMeasurement.xcframework/ios-arm64_armv7/GoogleAppMeasurement.framework/GoogleAppMeasurement (for architecture armv7): current ar archive
GoogleAppMeasurement.xcframework/ios-arm64_armv7/GoogleAppMeasurement.framework/GoogleAppMeasurement (for architecture arm64): current ar archive
创建 .xcframework
文件的一种方法是使用 Firebase 的 ZipBuilder,它从 CocoaPods podspec 文件指定的静态库中创建 .xcframework
文件。
我还需要将 NDI SDK 作为 Swift 包依赖项添加到我的应用程序中。
我发现了一些有效的方法:
您可以通过从通用库中提取瘦 arm64 库来创建 XCFramework 包:
lipo "/Library/NDI SDK for Apple/lib/iOS/libndi_ios.a" -thin arm64 -output "$STAGING_DIRECTORY/libndi.a"
然后创建一个 XCFramework 包:
xcodebuild -create-xcframework -library "$STAGING_DIRECTORY/libndi.a" -headers "/Library/NDI SDK for Apple/include" -output "$STAGING_DIRECTORY/Clibndi.xcframework"
我最终没有使用这种方法,因为在 GitHub 上托管 XCFramework 作为可下载的二进制版本需要我制作我的 repo public(参见 this issue)。
相反,我在 Package.swift:
中使用系统库目标
targets: [
.target(
name: "WrapperLibrary",
dependencies: ["Clibndi"],
linkerSettings: [
.linkedFramework("Accelerate"),
.linkedFramework("VideoToolbox"),
.linkedLibrary("c++")
]),
.systemLibrary(name: "Clibndi")
]
然后,我有 WrapperLibrary/Sources/Clibndi/module.modulemap 看起来像:
module Clibndi {
header "/Library/NDI SDK for Apple/include/Processing.NDI.Lib.h"
link "ndi_ios"
export *
}
最后,我的应用程序目标(Xcode 项目的一部分,而不是 Swift 包)依赖于 WrapperLibrary,我不得不添加“/Library/NDI SDK for Apple/lib/iOS”(包括引号)到“构建设置”选项卡中的“库搜索路径”。
作为修改应用程序目标构建设置的替代方法,您可以将 pkg-config 文件添加到 pkg-config 搜索路径中的目录中。例如,/usr/local/lib/pkgconfig/libndi_ios.pc:
NDI_SDK_ROOT=/Library/NDI\ SDK\ for\ Apple
Name: NDI SDK for iOS
Description: The NDI SDK for iOS
Version: 5.1.1
Cflags: -I${NDI_SDK_ROOT}/include
Libs: -L${NDI_SDK_ROOT}/lib/iOS -lndi_ios
然后在您的包清单中使用 .systemLibrary(name: "Clibndi", pkgconfig: "libndi_ios")
。然而,我发现这对用户来说不如将设置添加到我的应用程序目标方便。
理想情况下,您也可以将 NDI SDK 的依赖库和框架添加到 pkg-config 文件 (Libs: -L${NDI_SDK_ROOT}/lib/iOS -lndi_ios -lc++ -framework Accelerate -framework VideoToolbox
),但 Swift 的 pkg-config 解析 -framework
个参数,所以我提交了一个错误:SR-15933.
我正在尝试构建一个 Swift 包,它包装了一个用 C 编写的胖静态库:libndi_advanced_ios.a 来自 NewTek's Apple Advanced NDI SDK。
我在 link 将预编译库(只有头文件和 .a 二进制包可用)到我的 Swift 包时遇到问题。我做了很多研究并尝试了不同的解决方案,但其中 none 有效。这是一个快速列表:
也不能bundle in an XCFramework because libndi_advanced_ios.a supports multiple platforms (arm_v7, i386, x86_64, arm64) and
xcodebuild -create-xcframework
return the errorbinaries with multiple platforms are not supported
(this solution is discussed on Swift Forums);按照 SPM Documentation (that is outdated 中的建议在
targets
中使用.linkedLibrary
给出警告system packages are deprecated; use system library targets instead
,我什至不记得它是否构建成功;尝试不同的标志和设置(如
linkerSettings
)并没有成功。也许我只是错过了正确的组合。
我可以 link 几十个 Whosebug 的问题和其他没有帮助的帖子,但它没有用 (a, b, c)。
目前我的配置是这样的:
With Package.swift
包含以下代码:
let package = Package(
name: "swift-ndi",
platforms: [.iOS(.v12)],
products: [
.library(
name: "swift-ndi",
targets: ["swift-ndi"])
],
dependencies: [],
targets: [
.target(name: "CiOSNDI", path: "Libraries"),
.target(
name: "swift-ndi",
dependencies: ["CiOSNDI"]),
.testTarget(
name: "swift-ndiTests",
dependencies: ["swift-ndi"]),
]
)
您可以在 alessionossa/swift-ndi 找到整个项目。
目前唯一的结果是一些警告和模块 CiOSNDI 不构建:
我也尝试 .systemLibrary(name: "CiOSNDI", path: "Libraries/"),
使用此配置:alessionossa/swift-ndi/tree/systemLibrary;但我收到这些错误:
注意
NDI_include
实际上是alias/symboliclink到/Library/NDI Advanced SDK for Apple/include
,而NDI_iOS_lib
指向/Library/NDI Advanced SDK for Apple/lib/iOS
.
我总是在更改 Package.swift
后清理构建文件夹。
更新 10/01/2022:libndi_advanced_ios.a 需要 libc++.tbd.在 Build Phases -> Link Binary With Libraries 的应用程序中 linked 很容易,但我不'知道如何在 Swift 包中 link。
需要用 .binary_target
指定二进制目标。见 docs and example here.
包裹在 .xcframework
中的静态库示例在文件命令中如下所示:
$ file GoogleAppMeasurement.xcframework/ios-arm64_armv7/GoogleAppMeasurement.framework/GoogleAppMeasurement
GoogleAppMeasurement.xcframework/ios-arm64_armv7/GoogleAppMeasurement.framework/GoogleAppMeasurement: Mach-O universal binary with 2 architectures: [arm_v7:current ar archive] [arm64]
GoogleAppMeasurement.xcframework/ios-arm64_armv7/GoogleAppMeasurement.framework/GoogleAppMeasurement (for architecture armv7): current ar archive
GoogleAppMeasurement.xcframework/ios-arm64_armv7/GoogleAppMeasurement.framework/GoogleAppMeasurement (for architecture arm64): current ar archive
创建 .xcframework
文件的一种方法是使用 Firebase 的 ZipBuilder,它从 CocoaPods podspec 文件指定的静态库中创建 .xcframework
文件。
我还需要将 NDI SDK 作为 Swift 包依赖项添加到我的应用程序中。
我发现了一些有效的方法:
您可以通过从通用库中提取瘦 arm64 库来创建 XCFramework 包:
lipo "/Library/NDI SDK for Apple/lib/iOS/libndi_ios.a" -thin arm64 -output "$STAGING_DIRECTORY/libndi.a"
然后创建一个 XCFramework 包:
xcodebuild -create-xcframework -library "$STAGING_DIRECTORY/libndi.a" -headers "/Library/NDI SDK for Apple/include" -output "$STAGING_DIRECTORY/Clibndi.xcframework"
我最终没有使用这种方法,因为在 GitHub 上托管 XCFramework 作为可下载的二进制版本需要我制作我的 repo public(参见 this issue)。
相反,我在 Package.swift:
中使用系统库目标 targets: [
.target(
name: "WrapperLibrary",
dependencies: ["Clibndi"],
linkerSettings: [
.linkedFramework("Accelerate"),
.linkedFramework("VideoToolbox"),
.linkedLibrary("c++")
]),
.systemLibrary(name: "Clibndi")
]
然后,我有 WrapperLibrary/Sources/Clibndi/module.modulemap 看起来像:
module Clibndi {
header "/Library/NDI SDK for Apple/include/Processing.NDI.Lib.h"
link "ndi_ios"
export *
}
最后,我的应用程序目标(Xcode 项目的一部分,而不是 Swift 包)依赖于 WrapperLibrary,我不得不添加“/Library/NDI SDK for Apple/lib/iOS”(包括引号)到“构建设置”选项卡中的“库搜索路径”。
作为修改应用程序目标构建设置的替代方法,您可以将 pkg-config 文件添加到 pkg-config 搜索路径中的目录中。例如,/usr/local/lib/pkgconfig/libndi_ios.pc:
NDI_SDK_ROOT=/Library/NDI\ SDK\ for\ Apple
Name: NDI SDK for iOS
Description: The NDI SDK for iOS
Version: 5.1.1
Cflags: -I${NDI_SDK_ROOT}/include
Libs: -L${NDI_SDK_ROOT}/lib/iOS -lndi_ios
然后在您的包清单中使用 .systemLibrary(name: "Clibndi", pkgconfig: "libndi_ios")
。然而,我发现这对用户来说不如将设置添加到我的应用程序目标方便。
理想情况下,您也可以将 NDI SDK 的依赖库和框架添加到 pkg-config 文件 (Libs: -L${NDI_SDK_ROOT}/lib/iOS -lndi_ios -lc++ -framework Accelerate -framework VideoToolbox
),但 Swift 的 pkg-config 解析 -framework
个参数,所以我提交了一个错误:SR-15933.