Cocoapods Packager + Xcode14 适配
升级到Xcode14之后,苹果做了一些优化,但有部分优化Cocoapods Packager并没有适配,会导致无法顺利打出包或者打出的包有兼容性问题。
前往 Github repo,会发现Cocoapods Packager的最新发布 1.5.0 在 2016 年, 最新的代码提交在 2019 年,这就是痛苦根源。
Xcode14 的架构变更适配
从 Xcode 14 Release Notes可以看到,目前最低支持版本已经提到了 iOS11,并且自然而然的移除了无法升级到 iOS11 的armv7, armv7s, and i386。
这导致了我们打包遇到的第一个问题:架构报错。
error: The armv7 architecture is deprecated. You should update your ARCHS build setting to remove the armv7 architecture. (in target 'Pods-packager' from project 'Pods')
error: The armv7s architecture is deprecated. You should update your ARCHS build setting to remove the armv7s architecture. (in target 'Pods-packager' from project 'Pods')
报错原因已经在前文提到了,那么参照参考1,通过修改builder.rb
的 ARCHS 为
$(ARCHS_STANDARD)
成功修复了Xcode14打已经被移除的armv7(s)失败的问题,果然这个16年就停更的东西有点没力气了啊
修改后应为:
def ios_build_options
"ARCHS=\'$(ARCHS_STANDARD)\' OTHER_CFLAGS=\'-fembed-bitcode -Qunused-arguments'"
end
需要留意的是,参考中builder.rb
的路径为
/Library/Ruby/Gems/2.6.0/gems/cocoapods-packager-1.5.0/lib/cocoapods-packager
但在我本机的路径实际为
/usr/local/lib/ruby/gems/2.6.0/gems/cocoapods-packager-1.5.0/lib/cocoapods-packager
安装路径不同,供参考
Xcode12 的 arm64 冲突适配
如果是没有修改过这块,仅仅使用ARCHS_STANDARD架构有可能还是无法成功出包的,原因在于,Xcode12 开始增加了 M1 设备支持,模拟器和真机同时包含arm64架构,导致了架构冲突。
对于这一点,参照参考 2能修复Xcode12之后arm64冲突的问题,修改方式为修改cocoapods-packager的源码中的pod_utils.rb
文件(文件路径前文已有,不再重复):
unless static_installer.nil?
static_installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['CLANG_MODULES_AUTOLINK'] = 'NO'
config.build_settings['GCC_GENERATE_DEBUGGING_SYMBOLS'] = 'NO'
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64' // <-- inserted here
end
end
static_installer.pods_project.save
end
看着其实就是设置模拟器不打 arm64 架构,保持只有一份 arm64 架构?
Xcode 14 打的 sdk 适配 Xcode13
按照前文一路解决下来,已经可以通过packager漂亮的打出一个 framework 了。不过,还有一个隐藏问题可能在后面暴露出来:Xcode 14 打的 sdk ,在 Xcode13 上继承会报错,提示大量的找不到_objc_msgSend$xxx。
Undefined symbol: _objc_msgSend$stringByTrimmingCharactersInSet:
Undefined symbol: _objc_msgSendSsize
Undefined symbol: _objc_msgSend$drawInRect:
// balabala
这又是一个坑,不过幸运的是,对于我们来说,这是目前需要解决的最后一个坑了。
这一个特性更新隐藏在WWDC2022 Session 110363 Improve app size and runtime performance中,在 Xcode14 的 release note 里没有提及,更隐蔽了。
特性内容是优化 objc_msgSend,提取为一个 helper func(selector stub),通过这一优化减少了 2%的二进制大小,并且这一优化在 Xcode14 自动启用
虽然这一优化并不限制你的ipa部署版本,在旧版本系统也能使用,但是它没有说的是,这一优化只有 Xcode14+才能理解,这就导致了Xcode 14 打的 sdk , Xcode13无法理解,于是就有了前面提到的找不到_objc_msgSend$xxx。
对于这点,网上的大家说的修改OTHER_CFLAGS
,添加-fno-objc-msgsend-selector-stubs
参数,关闭这项优化。
这个原理是对的,但是实际验证下来都无效,packager打出来的 sdk Xcode13 还是无法理解。
结合这里和 参考1,基本确定主要原因是 packager 就没有使用那些参数去打包,而是用自己的 build options,所以在 pod spec 里配置的都是无法影响打包结果
因此需要在前面的 参考 1 基础上,再追加-fno-objc-msgsend-selector-stubs
。
所以对于 Xcode14 的最终修改是,修改 builder.rb 的ios_build_options
如下:
def ios_build_options
"ARCHS=\'$(ARCHS_STANDARD)\' OTHER_CFLAGS=\'-fembed-bitcode -Qunused-arguments -fno-objc-msgsend-selector-stubs\'"
end
All done, 完美✿✿ヽ(°▽°)ノ✿
更多
在进行前面疑难杂症攻关过程中,发现了fastlane 的一个 action create_xcframework
,可以用来构建xcframework。那么,是不是可以用 fastlane 来打包 sdk 呢?有没有相关资源呢?