从的来说编译分几个阶段 预处理->代码解析->汇编->链接->生成可执行文件
一、预处理的中进行的操作是:
1、进行宏替换
2、头文件引入 #include/#import 使用对应.h文件的内容替换这一行,所以我们导入头文件应该尽量写在.m文件里面,避免.h文件过于臃肿
3、处理条件编译指令 #if #else #endif
二、代码解析:包括词法分析,语法分析,静态分析,生成中间代码和优化
1、词法分析:这一步的操作是将代码转换成特殊的标记流、源码被分割成了一个个特殊的字符和单词,在行尾loc都标记了源码所在的对应源文件和行数,方便在具体报错时查找位置。Clang定义的所有Token类型, 可以分为1关键字比如if,else,for,while等;2标识符(变量名);3字面量(值,数字,字符串);4特殊符号(加减加减乘除等符号)
2、语法分析:这一步把语法分析生产的标记流解析生成一个抽象的语法树(abstract syntax tree -- AST
),同样地,在这里面每一节点也都标记了其在源码中的位置。
3、静态分析: 源码被转化成抽象树之后,编译器就可以对这个树进行抽象处理,静态分析会对代码进行错误检查,类型检查,如出现方法调用但是未被调用,定义变量但是未被使用,一次提高代码质量
4、中间代码生成和优化,中间代码文件有三种1.text 便于阅读的文本格式,类似于汇编语言,扩展名.ll 2.memory内存格式 3.二进制格式扩展名为.bc;生成中间文件后llvm会对其进行编译优化,例如全局变量优化,循环优化尾递归优化最后输出汇编代码
三、汇编 这一阶段会将生成的可读的汇编代码转换成机器代码,最终产物是以.o为后缀的目标文件会在xcode构建产生的DerivedData文件中看到该文件
四、链接:这一步操作就是将上述生成的目标文件和静态库链接起来最终生成可执行文件,可执行文件的类型是Mach-O类型,iOS和mac电脑的可执行文件都是这种类型,苹果手机的指令集是ARM,模拟器的一般是X86_64,至此编译流程结束。
下面我们开始走启动流程(冷启动)
1、解析info.plist文件 加载相关信息,例如闪屏,建立沙盒,检查权限
2、dyld(动态链接器)的装载过程,这个过程中dyld将所有的可执行文件进行装载,同时递归加载所有依赖的动态库,当dyld将所有的可执行文件和动态库装载完毕后会通知runtime执行下一步。
3、runtime调用map_images对可执行文件的内容进行解析和处理,load_images中调用call_load_methods(调用所有class和categary的load方法),初始化各种objc对象结构(注册objc类,初始化类对象等等)
4、runtime调用C++初始化器和attribute修饰的函数,到此为止可执行文件和动态库中所有符号(Class,Protocol,Selector,IMP,…)都已经加载到内存中
5、所有初始化流程结束后就可以执行main函数及以后得操作了,依次是main,UIApplicationMain,didFinishLaunch方法