AI智能
改变未来

iOS:App 编译和启动原理


编译原理:

将编译过程分为前端和后端两部分处理

Clang(编译器前端):GCC的替代品,Clang的编译速度比GCC快
1.Lexer:读入源文件,并将其转化成字符流。
2.Parser:将字符流转换成AST(抽象语法树)。
3.SemanticAnalysis:对输入的AST进行语法检查。
4. Code Generation:代码生成,将AST转换成低层次的IR指令。

LLVM(编译器后端):底层虚拟机(Low Level Virtual Machine)
1.Optimization:分析IR指令,将其中潜在会拖慢运行速度的指令干掉。
2. AsmPrinter:通过IR(中间码)生成特定CPU架构的汇编代码。
3.Assemble :将汇编代码转化成机器码。
4. Linker:将机器码链接成可执行程序或动态码。

BitCode

当我们提交程序到 App Store 上时,Xcode 会将程序编译为一个中间表现形式( bitcode )。然后 App store 会再将这个 bitcode 编译为可执行的 64 位或 32 位程序

BitCode是什么?

BitCode 类似于一个中间码,被上传到 AppStore 之后,苹果会根据下载应用的用户的手机指令集类型生成只有该指令集的二进制进行下发,从而达到精简安装包体积的目的。

指令集

iOS 模拟器没有 arm 指令集,编译运行的是 x86/i386 指令集

模拟器的指令集:

4S:-5i386
5S以上: X64_86

真机(iOS设备)的默认指令集:
armv6设备: iPhone,iPhone2,iPhone3G
armv7设备: iPhone3GS,iPhone4,iPhone4S
armv7s设备: iPhone5,iPhone5C
arm64设备: iPhone5S 以上

但是我们在编译的时候偶尔会报出 i386,x86_64 的错误?

解决办法:
查看静态库是否支持 i386/x86_64 的方法:

  1. 如果是 .a 文件:
      打开终端,使用 lipo -info 静态包地址 .a 查看
  2. 如果是 framework 文件:
      cd 到 framework 内部,之后在使用 lipo -info xxxFramework 查看

启动原理

Apple 在 2016 年的 WWDC 大会上提到:
建议应用的启动时间控制在 400ms 之下。并且必须在 20s 以内完成启动,否则系统会 kill 掉应用程序。那么话说我们如何知道 app 的在启动到调用 main( ) 方法之前的时间呢?
应用的启动分为 Pre-main 和 mian 两部分:

Pre-main 时间:从在屏幕上点击 app icon 开始,到应用执行到 main() 方法都是属于 Pre-main 时间

以下就是 Pre-main 部分

1. dylib loading time: 载入动态库,包括引用的第三方库和自定义的动态库,Apple官方建议尽量少使用自定义的动态库,或者考虑合并多个动态库。
2. rebase/binding time: 重构和绑定,rebase会修正调整处理图像的指针,并且会设置指向绑定(binding)外部的图像指针。(即Rebase修正内部的指针指向,Bind 修正外部指针指向)
3. ObjC setup time: 在Objective-C的运行时(runtime),需要对类(class),类别(category)进行注册以及选择器分配
4. Initializer time: 是执行+initialize方法的时间

查看 Pre-main 时间的方法:

在 iOS10 之前的系统中,我们无处得知其中的细节。而在 iOS10 系统中,可以通过简单在 Xcode 设置,在控制台就可以打印出 Pre-main 的具体信息细节,见以下两个截图:

  • 点赞
  • 收藏
  • 分享
  • 文章举报

GS-NICE发布了177 篇原创文章 · 获赞 0 · 访问量 2694私信关注

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » iOS:App 编译和启动原理