可用性
Xcode 12+
何来
问题根本来源:Linker 无法识别库是对于 iOS 的 arm64 架构,还是 Mac 的 arm64 架构
在 M1 的 Mac 前
一个库的 binary file 可能包含的架构(格式
<architecture: target>
):- arm7: iPhone
- arm64: iPhone
- x86-64: Mac
考虑到兼容性的问题,一个库很可能会包含上述所有组合的构建产物,即 fat framework
在 Build 的期间,Linker 会根据 target,选取对应的库构建产物进行链接
由于上述三种组合直接不存在 overlap 的问题,因此 Linker 可以很容易区分出不同 architecture 和 target
在 M1 出来后
一个库的 binary file 可能包含的架构(格式
<architecture: target>
):- arm64: iPhone
- arm64: Mac
问题出现了:对于同一种架构,有两种不同的 target,而不同 target 之间是存在差异的
比如对于 iOS 模拟器来说,就有了 arm64 的模拟器与 x86-64 的模拟器,而不同架构的模拟器,同一个库的编译产物不能共用
而之前的库链接命令
lipo
,并不能处理 the binary framework which contains different code for the same architecture in multiple places解决方法
在 XCFramework 中,不再需要像
lipo
一样,构建一个 framework,其中包含所有的 architecture 和 target 组合取而代之,对同一个代码库,针对不同的 architecture 与 target 的组合,构建一个二进制文件,并存放到 XCFramework 中对应的文件夹
这些文件夹名如:
ios-arm64
ios-arm64-simulator
创建
若要生成 xcframework 的代码库使用了 Cocoapods 进行第三方库集成,即无法生成 xcframework
- 生成所支持平台的 slice,生成产物为
xxx.xcarchive
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
是必须的(这是从 Xcode 11 开始有的选项),要求 Xcode 不要 version-locking(否则,会导致库在新版 Xcode 或新版 Swift 编译器上不可用)- 对于斋 project 而言,参数是
-project 'xxx.xcodeproj'
如以下需要支持 iOS 设备与 iOS 模拟器
# Archive device slice xcodebuild archive \ -workspace 'MyFramework.xcworkspace' \ -scheme 'MyFramework' \ -configuration Release \ -destination 'generic/platform=iOS' \ -archivePath '/path/to/archives/MyFramework-iphoneos' \ SKIP_INSTALL=NO \ BUILD_LIBRARY_FOR_DISTRIBUTION=YES # Archive simulator slice xcodebuild archive \ -workspace 'MyFramework.xcworkspace' \ -scheme 'MyFramework' \ -configuration Release \ -destination 'generic/platform=iOS Simulator' \ -archivePath '/path/to/archives/MyFramework-iphonesimulator' \ SKIP_INSTALL=NO \ BUILD_LIBRARY_FOR_DISTRIBUTION=YES
- 将上述生成的
.xcarchive
合并到一个.xcframework
中
xcodebuild -create-xcframework \ -framework '</path/to/archives/MyFramework-iphoneos.xcarchive/Products/Library/Frameworks/MyFramework.framework>' \ -framework '</path/to/archives/MyFramework-iphonesimulator.xcarchive/Products/Library/Frameworks/MyFramework.framework>' \ -output '<path/to/dest/MyFramework.xcframework>'
lipo
lipo \ -create \ ./path/to/ios-arm64/MyFramework.framework/MyFramework \ ./path/to/ios-x86_64-simulator/MyFramework.framework/MyFramework \ -output ./MyFramework
问题
No 'swiftinterface' files found within
需要到 Xcode → Build Settings → Build Options → Build Libraries for Distribution 修改为
YES
Snippets
# create archives framework_name=<name for sdk> archiveDirectory="$(pwd)/Build" if [ -d "$archiveDirectory" ]; then rm -Rf $archiveDirectory; fi ## Device xcodebuild archive \ -project "${framework_name}.xcodeproj" \ -scheme $framework_name \ -configuration Release \ -destination 'generic/platform=iOS' \ -archivePath "${archiveDirectory}/${framework_name}-iphoneos" \ -SKIP_INSTALL=NO \ -BUILD_LIBRARY_FOR_DISTRIBUTION=YES ## Simulator xcodebuild archive \ -project "${framework_name}.xcodeproj" \ -scheme $framework_name \ -configuration Release \ -destination 'generic/platform=iOS Simulator' \ -archivePath "${archiveDirectory}/${framework_name}-iphoneosimulator" \ -SKIP_INSTALL=NO \ -BUILD_LIBRARY_FOR_DISTRIBUTION=YES # combine archives xcodebuild -create-xcframework \ -framework "${archiveDirectory}/${framework_name}-iphoneos.xcarchive/Products/Library/Frameworks/${framework_name}.framework" \ -framework "${archiveDirectory}/${framework_name}-iphoneosimulator.xcarchive/Products/Library/Frameworks/${framework_name}.framework" \ -output "${archiveDirectory}/${framework_name}.xcframework"