关于Xcode “Build Setting”中的Architectures详解

09/27/2017 13:16 下午 posted in  Xcode

##基本概念

  • ARM架构,是一种低成本、高性能、低耗电处理器架构,目前广泛的在移动通信领域中使用。

  • ARM处理器指令集
    苹果A7处理器支持两个不同的指令集:32位ARM指令集(armv6|armv7|armv7s)和64位ARM指令集(arm64)。
    i386|x86_64 是Mac处理器的指令集,i386是针对intel通用微处理器32架构的。x86_64是针对x86架构的64位处理器。当使用iOS模拟器的时候会遇到i386|x86_64,iOS模拟器没有arm指令集。

  • 目前iOS移动设备指令集
    ARMv8/ARM64: iPhone 6(Plus), iPhone 5s, iPad Air(2), Retina iPad Mini(2,3)
    ARMv7s: iPhone 5, iPhone 5c, iPad 4
    ARMv7: iPhone 3GS, iPhone 4, iPhone 4S, iPod 3G/4G/5G, iPad, iPad 2, iPad 3, iPad Mini
    ARMv6: iPhone, iPhone 3G, iPod 1G/2G
    “Build Setting” 中Architecture详解

  • Architectures
    指定工程支持的指令集的集合,如果设置多个architecture,则生成的二进制数据包会包含多个指令集代码,体积会变大。

  • Valid Architectures
    有效的指令集集合,Architectures与Valid Architectures 的交集来确定最终的数据包包含的指令集代码。

  • Build Active Architecture Only
    指定是否只对当前连接设备所支持的指令集编译,默认Debug的时候设置为YES,Release的时候设置为NO。设置为YES是只编译当前的architecture版本,生成的包只包含当前连接设备的指令集代码。设置为NO,则生成的包包含所有的指令集代码(上面的Valid Architectures跟Architectures的交集)。因此为了调试速度更快,则Debug应该设置为YES。
    特殊:设置此值为YES,如果连接的设备是arm64的( iPhone 5s,iPhone6(plus)等),则Valid Architecture 中必须包含arm64, 否则编译会报错(报错的内容在下面常见问题中)。
    总结一下,按照新版Xcode6.1.1的默认设置就没有任何问题,之前的Xcode版本开发的项目也建议升级到Xcode6.1.1,同样按照如下配置:

  1. Architectures 默认设置为 Standard architectures(armv7,arm64) 。(之前的Xcode版本中默认设置还包括armv7s,现在去掉了,估计是因为armv7s相较armv7优化不大,能向下兼容,而设置后还会增大二进制包的大小)
  2. Valid Architectures 默认设置为 armv7 armv7s arm64。
  3. Build Active Architecture Only:默认Debug的时候设置为YES,Release的时候设置为NO。
    ##App适配64位
  • 为什么要适配64位?
    1: 苹果官方要求: 2015年2月1日起,提交到AppStore的新应用必须支持64bit,6月1日起,更新的app也必须支持64bit。详见官方文档。
    2: 为了提升性能:目前A7使用的是ARM V8架构,除了使用64位的地址总线和64位的寄存器以外,还增加了寄存器的数量,目前A7中的整数和浮点数寄存器是A6的两倍。寄存器的增加提高了程序的运行速度。详见官方文档。再者,64位系统为了兼容32位的程序,64位的iOS系统中带有两套Framework,一套32位的,一套64位的。当64位的iOS系统运行原来的32位程序时,系统会调用32位的Framework作为底层支撑,当系统运行64位程序时,系统会调用64位的Framework作为底层支撑,所以如果app不做64位适配的话,系统会调用32位Framework,消耗内存增多,运行速度会变慢。
  • 如何适配64位?
    1:Xcode版本号>5.0.1。(建议升级到最新版本)
    2:minimum deployment target > 5.1.1。
    3:按照上述Xcode6的默认配置进行配置,其他Xcode版本最好也进行如此配置。
    4:运行测试代码,解决编译warnings and errors,对照本文档或者官方文档 64-Bit Transition Guide for Cocoa Touch对相应地方做出修改。(编译器不能告诉我们一切)
    5:在真实的64-bit机器上测试。
    6:使用Instruments查看内存使用问题。

此贴只进行简要介绍,具体详见iOS工程如何支持64-bit或者苹果官方文档
##关于Architecture的常见问题

  1. 编译报错 No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VALID_ARCHS=i386).

问题起因:active architecture(当前连接设备的指令集)为64位指令集,但是valid architecture只包含32位指令集
解决方法:valid architecture增加arm64 (常见的一些帖子的解决方案是把Build Active Architecture Only设置为NO,这是个简单粗暴的解决办法,在Debug过程中也会生成包含所有指令集的代码,更何况现在官方强制必须支持64位,故不建议采纳)
2. No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=i386, VALID_ARCHS=x86_64).

问题起因:跟上个问题同理,只不过连接的设备指令集是32位指令集,但是valid architecture只包含64位指令集
解决办法:valid architecture增加armv7
3. App在打包submit到Appstore中,提示需要支持64bit,或者在App提交完成后Apple发Missing 64-bit support 内容的邮件给开发者。

解决办法: App按照上述适配64位的步骤进行适配。
4. 导入静态库后编译报错为

问题起因:1:可能是静态库中不包含这个类。
2:静态库工程可能没有链接到应用。
3:可能是因为静态库(.a)为真机版本,不包含模拟器版本(i386)。
解决办法:1:查看静态库里面是否存在这个类。
2:Build Phases中没有添加Link Binary With Libraries 中添加此静态库。
3:把调试目标换成真机 或者 导入一个模拟器版本跟真机版本合并的版本
同理如果导入的库是模拟器版本而用真机调试也会报错,所以导入一个通用的版本是目前来讲最好的办法。
5. 导入静态库后编译报错为

问题起因:1:可能原因同上,因为静态库不包含报错的类
2:可能原因同上,因为静态库程可能没有链接到应用。
3:可能是因静态库不支持64位
解决办法:排除前两个可能原因后,来看第三个起因的解决办法:查看静态库的提供方是否有更新支持64位,如果最新的静态库依然不支持64位的话,则需要获取其源码重新打包静态库,valid architecture中添加arm64。
详细的解决办法参考stackoverflow。如果不能获得源代码的话,鉴于目前苹果官方需要支持64位,所以只能换别的静态库了,否则联系开发者进行静态库更新。
##参考文档
1: 苹果官方文档对于”Build Setting”的介绍
2: iOS开发~制作同时支持armv7,armv7s,arm64,i386,x86_64的静态库.a
3: iOS工程如何支持64-bit
4: Xcode的Architecture和Valid Architecture的区别
5: 64-bit Transition Guide For Cocoa Touch