像C++,Objective C都是编译语言。编译语言在执行的时候,必须先通过编译器生成机器码,机器码可以直接在CPU上执行,所以执行效率较高。
像JavaScript,Python都是直译式语言。直译式语言不需要经过编译的过程,而是在执行的时候通过一个中间的解释器将代码解释为CPU可以执行的代码。所以,较编译语言来说,直译式语言效率低一些,但是编写的更灵活,也就是为啥JS大法好。
无论oc还是swift,编译工具都是LLVM.
这篇文章主要来讲解一下,XCode的编译过程.
基本的编译过程分为四个步骤:
预处理(Pre-process):把宏替换,删除注释,展开头文件,产生.i文件。
编译(Compliling):把之前的.i文件转换成汇编语言,产生.s文件。
汇编(Asembly):把汇编语言文件转换为机器码文件,产生.o文件。
链接(Link):对.o文件中的对于其他的库的引用的地方进行引用,生成最后的可执行文件(同时也包括多个.o文件进行 link)。
1.预处理
2.插入编译期脚本
3.配置XCode 提高编译速度
编译过程大致为:
1.编译.m文件
2.链接需要的Framework,例如Foundation.framework,AFNetworking.framework,ALiPay.fframework
3.编译xib文件
4.拷贝xib,图片等资源文件到结果目录
5编译ImageAssets
6.处理info.plist
7.执行CocoaPod脚本
8.创建.app文件和对其签名
我们在每次编译过后,都会生成一个dsym文件。dsym文件中,存储了16进制的函数地址映射。
在App实际执行的二进制文件中,是通过地址来调用方法的。在App crash的时候,第三方工具(Fabric,友盟等)会帮我们抓到崩溃的调用栈,调用栈里会包含crash地址的调用信息。然后,通过dSYM文件,我们就可以由地址映射到具体的函数位置。
预处理
所谓预处理,就是在编译之前的处理。预处理能够让你定义编译器变量,实现条件编译。 比如,这样的代码很常见
#ifdef DEBUG
//...
#else
//...
#endif
插入脚本
通常,如果你使用CocoaPod来管理三方库,那么你的Build Phase是这样子的:
其中:[CP]开头的,就是CocoaPod插入的脚本。
Check Pods Manifest.lock,用来检查cocoapod管理的三方库是否需要更新
Embed Pods Framework,运行脚本来链接三方库的静态/动态库
Copy Pods Resources,运行脚本来拷贝三方库的资源文件
到这里,CocoaPod的原理也就大致搞清楚了,通过修改xcodeproject,然后配置编译期脚本,来保证三方库能够正确的编译连接。
同样,我们也可以插入自己的脚本,来做一些额外的事情。比如,每次进行archive的时候,我们都必须手动调整target的build版本,如果一不小心,就会忘记。这个过程,我们可以通过插入脚本自动化。

这段脚本其实很简单,读取当前pist的build版本号,然后对其加一,重新写入。
