5

iOS程序员的自我修养-编译、链接过程(一)

 2 years ago
source link: https://wukaikai.tech/2019/08/12/iOS%E7%A8%8B%E5%BA%8F%E5%91%98%E7%9A%84%E8%87%AA%E6%88%91%E4%BF%AE%E5%85%BB-%E7%BC%96%E8%AF%91%E3%80%81%E9%93%BE%E6%8E%A5%E8%BF%87%E7%A8%8B%EF%BC%88%E4%B8%80%EF%BC%89/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

被隐藏了的过程

OC是用Clang/LLVM来编译的。接下来我将用clang来展开整个过程。main.m文件源码如下:

//main.m文件
#import <stdio.h>

int main(int argc, const char * argv[]) {
printf("hello ~");
return 0;
}

平时用Xcode去Build,一键从源码到程序。这个过程中隐藏了预处理、编译、汇编和链接4个过程如下:

预处理(预编译Prepressing)

clang -E main.m -o main.i

处理源代码文件中的以”#”开头的预编译指令。规则如下:

  1. “#define”删除并展开对应宏定义。
  2. 处理所有的条件预编译指令。如#if/#ifdef/#else/#endif。
  3. “#include/#import”包含的文件递归插入到此处。
  4. 删除所有的注释”//或/**/“。
  5. 添加行号和文件名标识。如“# 1 “main.m””,编译调试会用到。

编译(Compilation)

clang -S main.i -o main.s

编译就是把上面得到的.i文件进行:词法分析、语法分析、静态分析、优化生成相应的汇编代码,得到.s文件。

  1. 词法分析:源代码的字符序列分割成一个个token(关键字、标识符、字面量、特殊符号),比如把标识符放到符号表(静态链接那篇,重点讲符号表)。
  2. 语法分析:生成抽象语法树 AST,此时运算符号的优先级确定了;有些符号具有多重含义也确定了,比如“*”是乘号还是对指针取内容;表达式不合法、括号不匹配等,都会报错。
  3. 静态分析:分析类型声明和匹配问题。比如整型和字符串相加,肯定会报错。
  4. 中间语言生成:CodeGen根据AST自顶向下遍历逐步翻译成 LLVM IR,并且在编译期就可以确定的表达式进行优化,比如代码里t1=2+6,可以优化t1=8。(假如开启了bitcode,)
  5. 目标代码生成与优化:根据中间语言生成依赖具体机器的汇编语言。并优化汇编语言。这个过程中,假如有变量且定义在同一个编译单元里,那给这个变量分配空间,确定变量的地址。假如变量或者函数不定义在这个编译单元,得链接时候,才能确定地址。

汇编(Assembly)

clang -c main.s -o main.o

汇编就是把上面得到的.s文件里的汇编指令一一翻译成机器指令。得到.o文件,也就是目标文件,后面会重点讲的Mach-O文件。

链接(Linking)

clang main.o -o main

远古时代,一个程序只有一个源代码文件,导致程序的维护非常困难。现在程序都是分模块组成,比如一个App,对应有多个源代码文件。每个源代码文件汇编成目标文件,根据上面流程A目标文件访问B目标文件的函数或者变量,是不知道地址的,链接就是要解决这个问题。链接过程主要包括地址和空间分配、符号决议和重定位。

链接就是把目标文件(一个或多个)和需要的库(静态库/动态库)链接成可执行文件。后面会分别讲静态链接和动态链接。

《程序员的自我修养-链接、装载与库》

–EOF– 若无特别说明,本站文章均为原创,转载请保留链接,谢谢


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK