原地址:https://objccn.io/issue-6-2/ ,https://objccn.io/issue-6-3/
1. XCODE编译帮我们做了什么事情?
答: 将.h 和.m 文件转换成字节码文件 ,由ios的ARM处理器 or mac上的intel处理器执行
2. 具体过程是怎么样的?
答: xcode 默认 所使用的编译器是clang ,大体过程是
a.对objective-c做代码的分析检查
b. 在正确后转为低级的类汇编代码 (LLVM 中间表达码)
c. 最后LLVM 会根据平台不同转换成对应的字节码
具体的过程可以用命令 clang -ccc-print-phases XX.m 查看,结果如下
0: input, "Income.m", objective-c
1: preprocessor, {0}, objective-c-cpp-output
2: compiler, {1}, ir
3: backend, {2}, assembler
4: assembler, {3}, object
5: linker, {4}, image
6: bind-arch, "x86_64", {5}, image
3. 每个阶段做了些什么事?
0: 读入文件
1: 预处理 (宏替换,词法翻译,import展开)
预处理之宏替换:将源文件的宏展开, #import 文件的展开(#import文件如果有其它的import 也一并展开,一直递归下去),用命令clang -Ehello.c| less 后可以看到预处理的文件:
源文件 :
#define MAX(a,b) a > b ? a : b
int main() {
printf("largest: %d\n", MAX(10,100));
return 0;
}
处理后的文件 :
# 1 "hello.c"# 1 "" 1# 1 "" 3# 329 "" 3# 1 "" 1# 1 "" 2
# 1 "hello.c" 2
int main() {
printf("largest: %d\n", 10 > 100 ? 10 : 100);
return 0;}
ps :可以看到,宏已经被替换掉了。 预处理的文件会在有变化的地方插入#(hash) 来标记 ,#后的数字是源文件位置 ,最后的数字为新文件的位置,这样在出错的时候就可以对应 起来找到出错的地方。
词法解析标记 : 在上一步的预处理完成后,每一个.m文件 里的声明和定义会从 string 转化成特殊的标记 举例如下:
源code:
intmain(){
NSLog(@"hello, %@", @"world");
return 0;}
利用命令 clang -Xclang -dump-tokens hello.m 可以查看到词法解析后的内容如下:按我的理解就是把源代码翻译成了符合编译器语法的源代码,这样编译器就能认识了. 其中 4:1 类似于NSRange,可以知道源码的起 始位置

总的说来, 在预编译阶段:会做宏替换,会做头文件引入,然后将m文件 符号 化后转换成语法树, 编译器会根据这棵语法树,做一些额外的操作以找出可能存在的错误,包括如下:
a. 类型检查(动态&静态检查):即检查程序中是否有类型错误 , 比如属性和对应的类型是否相同 ,一个对象有没有对应的方法 etc.
b. 检查变量定义了但是未使用 etc, 可能存在的内存问题,就是我们看到的Warning
3. 编译 :将 AST 转换为更低级的中间码 (LLVM IR),对生成的中间码做优化,生成特定目标代码,输出汇编代码
4.汇编: 将汇编代码转换为目标对象文件
5. 链接: 将多个目标对象文件合并为一个可执行文件 (或者一个动态库)
6. 生成可执行文件 :Mach-O
PS: 更详细的请看开头的原文LINK,该篇只是我看后的个人总结。。
网友评论