iOS正确拆包

上传App Store 报错 ERROR ITMS-90087:”Unsupported Architectures…”

问题原因:

有些第三方提供商为了方便开发者使用,在制作framework的时候经常把i386 x86_64 armv7 arm64 等几个平台合并到一起,但是上传App Store的应用包是不能包含i386 x86_64这两个。所以会出现上述错误。

相关描述

ARM

特点是体积小、低功耗、低成本、高性能,所以几乎所有手机处理器都基于ARM,在嵌入式系统中应用广泛。armv6 | armv7 | armv7s | arm64都是ARM处理器的指令集,这些指令集都是向下兼容的,例如armv7指令集兼容armv6,只是使用armv6的时候无法发挥出armv7的性能,从而会导致程序执行效率没有那么高。

设备指令集

指令集 描述 适用机型
arm64 真机64位处理器 iPhone5S(以及以上)| iPad Air| iPad mini2(iPad mini with Retina Display)
armv7s 真机32位处理器 iPhone5|iPhone5C|iPad4(iPad with Retina Display)
armv7 真机32位处理器 iPhone3GS|iPhone4|iPhone4S|iPad|iPad2|iPad3(The New iPad)|iPad mini|iPod Touch 3G|iPod Touch4
armv6 iPhone, iPhone2, iPhone3G, 第一代、第二代 iPod Touch(一般不需要去支持)
i386 i386是针对intel通用微处理器32架构的 虚拟机: iPhone4s iPhone5
x86_64 针对x86架构的64位处理器 虚拟机: iPhone5S iPhone6 iPhone6S iPhone7

Xcode中指令集相关选项(Build Setting中)

(1) Architectures

指定工程被编译成可支持哪些指令集类型,支持的指令集越多,编译出包含指令集代码的数据包越多,生成二进制包就越大。

(2) Valid Architectures

限制可被支持的指令集的范围,也就是Xcode编译出来的二进制包类型最终从这些类型产生,最终编译出哪种指令集的包,将由Architectures与Valid Architectures 的交集来确定。

ep1

1
2
3
Architectures:  armv7, armv7s, arm64
ValidArchitectures: armv6, armv7s, arm64
生成二进制包支持的指令集: arm64

ep2

1
2
3
Architectures: armv6, armv7, armv7s
Valid Architectures: armv6, armv7s, arm64
生成二进制包支持的指令集: armv7s

ep3

1
2
3
Architectures: armv7, armv7s, arm64
Valid Architectures: armv7,armv7s
这种情况是报错的,因为允许使用指令集中没有arm64。

如果你对ipa安装包大小有要求,可以减少安装包的指令集的数量,这样就可以尽可能的减少包的大小。当然这样做会使部分设备出现性能损失。

在Xcode6里 Valid Architectures 默认为 Standard architectures(armv7,armv7s,arm64)

原因解释如下:

使用上述默认参数,则生成的包里面包含32位、64位两份代码,在iPhone5s( iPhone5s是64位 )下,会首选64位代码包,其余的iPhone( 其余iPhone都是32位的,iPhone5c也是32位 ),只能运行32位,但是包含这两种架构的代码包,只有运行在ios6,ios7系统上。也就是说,这种打包方式,对手机几乎没要求,但是对系统有要求,需要ios6以上。

而使用standard architectures (armv7,armv7s) 参数,则打的包里只有32位代码,iPhone5s的是64位,可兼容32位。但是会降低性能。其余的iPhone对32位代码也更没问题,而32位代码包,对系统也几乎也没什么限制。

要发挥iPhone5s的64位性能,就要包含64位包,那么系统最低要求为ios6。 如果要兼容ios5以及更低的系统,只能打32位的包,系统都能通用,但是会丧失iPhone5s的性能。

(3) Build Active Architecture Only

指是否只编译当前适用的指令集。当其值设置为YES,是为了debug的时候编译速度更快,它只编译当前的architecture版本(编译出的版本是向下兼容的),而设置为no时,会编译所有的版本。

1
2
ep:
此值为yes,用iphone4编译出来的是armv7版本的,iphone5也可以运行,但是armv6的设备就不能运行。

所以,一般debug的时候可以选择设置为yes,release的时候要改为no,以适应不同设备。

如何拆分合并指令集

通过以上信息了解到,当我们做App的时候,为了追求高效率,并且减小包的大小,Build Active Architecture Only设置成YES,Architectures按Xcode默认配置,因为arm64向前兼容。但制作.a静态库就不同了,因为要保证兼容性,包括不同iOS设备以及模拟器运行不出错,所以结合当前行业情况,要做到最大的兼容性。

指令集查看命令

1
2
lipo -info libWeChatSDK.a
输出是:Architectures in the fat file: libWeChatSDK.a are: i386 armv7 armv7s x86_64 arm64

将lib库拆分出armv7、armv7s、i386类型的.a:

1.拆分单个包

1
2
3
4
lipo libWeChatSDK.a -thin armv7 -output libWeChatSDK_armv7_final.a
.
.
lipo libWeChatSDK.a -thin i386 -output libWeChatSDK_i386_final.a

i386类型还可以使用下面命令拆分

1
lipo -extract_family i386 -output libWeChatSDK_i386.a libWeChatSDK.a

下面的命令并不是单独分出armv7版本,而是armv7和armv7s, 可用info命令验证

1
2
3
4
lipo -extract_family armv7 -output libWeChatSDK_arm.a libWeChatSDK.a

lipo -info libWeChatSDK_arm.a
打印出:Architectures in the fat file: libWeChatSDK_arm.a are: armv7 armv7s

2.合并

合并armv7、armv7s、arm64

1
2
3
4
5
lipo -output libWeChatSDK.a -create libWeChatSDK_arm.a libWeChatSDK_arm64_final.a

or

lipo -create -output libWeChatSDK.a libWeChatSDK_arm.a libWeChatSDK_arm64_final.a

3.多个应用的.a文件合并

用上面方法分别拆分处每个应用的armv7、armv7s、arm64等单个类型的.a库

一.分离出每个.a库的目标文件(.o)(在arm64目录下)

1
ar -x ../libWeChatSDK_arm64_final.a

avatar
avatar

二. 把相同类型静态库.o文件移到同一文件中,并合并出新的静态库(在arm64同级目录中执行)

1
libtool -static -o libUniversal-arm64.a arm64/*.o

avatar

其他同理,最终使用2合并命令生成通用静态库

以上内容参考以下文章:

IOS 用lipo ar 拆分 合并 .a