复习资料

IOS 编译器做了什么?

2016-08-05  本文已影响0人  TByounger

原地址: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,可以知道源码的起 始位置 

在获得上面的语法标记后,clang会将标记流解析成一棵抽象语法树 (abstract syntax tree -- AST),可以用命令clang -Xclang -ast-dump -fsyntax-only hello.m 查看

总的说来, 在预编译阶段:会做宏替换,会做头文件引入,然后将m文件 符号 化后转换成语法树, 编译器会根据这棵语法树,做一些额外的操作以找出可能存在的错误,包括如下:

a. 类型检查(动态&静态检查):即检查程序中是否有类型错误 , 比如属性和对应的类型是否相同 ,一个对象有没有对应的方法 etc.

b. 检查变量定义了但是未使用 etc, 可能存在的内存问题,就是我们看到的Warning

3. 编译 :将 AST 转换为更低级的中间码 (LLVM IR),对生成的中间码做优化,生成特定目标代码,输出汇编代码

4.汇编: 将汇编代码转换为目标对象文件

5. 链接:  将多个目标对象文件合并为一个可执行文件 (或者一个动态库) 

6. 生成可执行文件 :Mach-O

PS: 更详细的请看开头的原文LINK,该篇只是我看后的个人总结。。

上一篇下一篇

猜你喜欢

热点阅读