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

目录

被隐藏了的过程

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个过程以下:bash

预处理(预编译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文件。post

  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目标文件的函数或者变量,是不知道地址的,连接就是要解决这个问题。连接过程主要包括地址和空间分配、符号决议和重定位。ui

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

引用

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

相关文章
相关标签/搜索