引用一些三方库后,如果是模拟器运行在编译过程中可能会遇找不到对应指令集文件的错误,以创蓝闪验的SDK为例:
先说解决方案,再说这个错误的原因
如果想继续用模拟器跑项目,就需要用Rosetta版本的模拟运行,打开Rosetta模拟器显示:
模拟器选择Rosetta版本:
这个时候就能成功编译并运行项目了。
但是刚开始运行,除了列表滑动没有惯性交互外没什么大问题,但修改几行代码或者过段时间Command + R,模拟器就会卡死并黑屏,XCode也一直转圈,最终只能重新启动模拟器。
造成这个现象的原因是因为XCode和模拟器运行在不同的指令集下,两者之间通信通过Rosetta转义。
接着再说说上面编译报错的原因,在M系Mac之前,由于用的Intel芯片,模拟器是x86架构,所以在制作静态库时,会编译x86和arm两个指令集版本的二进制文件,并用lipo命令合并成.a或.framework文件。通过lipo -info或file命令查看上述SDK的mach-O文件信息如下:
说明这个SDK同时包含arm64和x86_64两个架构的指令集,这在Intel芯片下跑模拟器是没问题的,但是M系Mac本身是arm架构,所以模拟器版本的SDK就会编译报错(理论上既然包含arm64的文件,M1芯片下的xcode直接去找arm64的文件应该是可以的,所以猜测真机下的arm64跟模拟器下的arm64是不是有区别)
我通过新建一个framework项目,并编译模拟器的静态库:
然后再Products目录下查看framwork文件夹下的二进制文件结构信息如下:
这里看到的信息是跟上面SDK的信息是一样的。
开始动歪脑筋:是不是可以将SDK的arm架构单独抽出一个framework,将arm的framework和包含arm和x86的famework同时打成一个xcframework,就能解决最初的问题?答案是行不通。
由于用lipo命令查看SDK的二进制文件和我测试生成的静态库的二进制文件信息一样,于是尝试直接将SDK打成xcframework,却得到一个错误:
意思二进制文件不能包含多个平台,我自己编译的x86、arm64的二进制是针对模拟器平台,SDK的x86、arm64是模拟器和真机平台的
我用测试静态库生成xcframework,再将测试静态库的二进制文件的arm64抽离成单独的framework,同时生成xcframework,两个文件夹的目录结构分别如下:
生成的文件夹都包含了simulator关键字
而将SDK的二进制的arm64抽离成单独的framework并生成xcframework,文件夹的目录如下:
说明真机和模拟器的arm64架构还不一样?所以想让只支持x86_64模拟器的静态库通过xcframework去兼容M系模拟器想法破灭了=。=
总结:要想静态库支持M系模拟器,必须在静态库出厂的时候编译好所有架构模拟器的静态库,要不然接入方就只能真机调试,或者用Rosetta版本的模拟器(忍受性能损耗和两个架构系统之间通信的bug)。
感谢以下文章的帮助:
M1设备的Xcode编译问题深究
iOS开发 XCFramework
iOS开发之--Architectures详解