iOS BitCode的前世今生

672 阅读3分钟

做iOS开发很多年了,对BitCode这个词很熟悉,但要我说却说不明白这个具体是什么,所以今天就借着看到的两篇介绍文章来做个简单总结。

首先声明,本文是大神文章的汇总,如果你只想对Bitcode有个大概了解,可以阅读本文;如果想有个深入的了解,建议阅读 关于bitcode, 知道这些就够了

一. BitCode是什么

Bitcode是由LLVM引入的一种中间代码IR(Intermediate Representation), 它是源代码被编译为二进制机器码过程中的中间表示形态,它既不是源代码,也不是机器码。 LLVM架构.png

  1. 上图是XCodeLLVM编译器架构图,编译器前端(Frontend),负责把各种类型语言的源代码编译为中间代码,也就是bitcode
  2. 优化器(Optimizer),负责对bitcode进行各种类型的优化,包括进行一些逻辑等价的转换,使得代码的执行效率更高,体积更小。
  3. 编译器后端(Backend),负责把优化后的bitcode编译为指定目标CPU架构的机器码。

通过命令行可将代码生成bitcode,证明了它确实是中间代码。

// test.c文件中的代码
#include <stdio.h>
int main(void) {
    printf("hello, world.\n");
    return 0;
}

// 下面是命令行
$ clang -emit-llvm -c test.c -o test.bc # 将源代码编译为bitcode
$ file test.bc # file命令用来探测给定文件的类型
test.bc: LLVM bitcode, wrapper x86_64 # 可以看到是LLVM的 bitcode文件

二. BitCode开启不开启有何异同

Xode中不开启BitCode编译设置:

首先,打包时bitcode为不开启,导出ipa时也不要勾选包含bitcode。 然后最终ipa包会直接使用Archive时编译出的二进制代码。

开启后:

首先,要以bitcode方式上传app,必须在开启bitcode的状态下,进行Archive打包, 并且在导出ipa时需要勾选包含bitcode

  1. 进行Archive打包时,bitcode会被嵌入到链接后的二进制文件中,用于提交给App Store。从编译日志中可以看出,Archive时多了一个编译参数 -fembed-bitcode,跟不开启的区别就是开启后会将未经任何加密或者压缩的bitcode文件嵌入到.o文件中。
  2. 在XCode进行其他类型的Build(非Archive)时,编译器只会检查是否满足开启bitcode的条件,但并不会真正生成bitcode

三. 为什么苹果要强推bitcode

开发者把bitcode提交到App Store Connect之后,如果苹果发布了使用新芯片的iPhone,支持更高效的指令,开发者不需要做任何操作,App Store Connect自己就可以编译出针对新产品优化过的app,并通过App Store分发给用户,不需要开发者自己重新打包上架,这样一来苹果的Store生态就不需要依赖开发者的积极性了。

但实际上苹果并未使用BitCode的优势。

四. Xcode14弃用Bitcode,导致应用体积大幅增加

上述说到有了bitcode文件,苹果可以根据bitcode来为新的CPU架构自动编译出一个APP,这样做存在缺点:

  • Bitccode不是一个稳定的格式,LLVM每次更新,它也需要更新,但是不能完全向后兼容。
  • 不能使用汇编代码,汇编代码不会发出Bitcode。
  • 不能使用没有bitcode的三方库
  • 即使使用bitcode编译新APP,很难保证兼容性。比如从64位的应用程序应用于32位系统、当苹果从英特尔切换到M1,也没有macOS应用程序神奇地转换为原生ARM

后来Xcode14弃用Bitcode。

弃用后打包出来的二进制文件会更大?实测是原先未开启bitcode的APP包体积没有变化;原先开启了bitcode的APP包体积看下面文章介绍是说会变大。

详情可查看文章: Xcode14弃用Bitcode,导致应用体积大幅增加

xcode14 废弃bitcode的原因