对于日常的应用程序开发,咱们不多须要关注编译
和连接
过程。咱们日常Xcode
开发就是集成的的开发环境(IDE)
,这样的IDE通常都将编译
和连接
的过程一步完成,一般将这种编译
和连接
合并在一块儿的过程称为构建
,即便使用命令行来编译一个源代码文件,简单的一句gcc hello.c
命令就包含了很是复杂的过程!前端
正是由于集成开发环境的强大,不少系统软件的
运行机制与机理
被掩盖,其程序的不少莫名其妙的错误让咱们无所适从,面对程序运行时种种性能瓶颈咱们一筹莫展。咱们看到的是这些问题的现象,可是却很难看清本质,全部这些问题的本质就是软件运行背后的机理及支撑软件运行的各类平台和工具
,若是能深刻了解这些机制,那么解决这些问题就可以游刃有余,收放自如了。linux
如今咱们经过一个C语言的经典例子,来具体了解一下这些机制:ios
#include <stdio.h> int main(){ printf("Hello World"); return 0; }
在linux下只须要一个简单的命令(假设源代码文件名为hello.c):c++
$ gcc hello.c $ ./a.out Hello World
其实上述过程能够分解为四步:面试
首先是源代码文件hello.c
和相关的头文件(如stdio.h
等)被预编译器cpp
预编译成一个.i
文件。第一步预编译的过程至关于以下命令(-E 表示只进行预编译):编程
$ gcc –E hello.c –o hello.i
还能够下面的表达后端
$ cpp hello.c > hello.i
预编译过程主要处理源代码文件中以”#”开头的预编译指令。好比#include、#define
等,主要处理规则以下:app
#define
删除,并展开全部的宏定义#if,#ifdef,#elif,#else,#endif
#include
预编译指令,将被包含的文件插入到该预编译指令的位置。//
和/**/
#2 “hello.c” 2。
#pragma
编译器指令截图个你们看看效果工具
通过预编译后的文件(.i文件)
不包含任何宏定义,由于全部的宏已经被展开,而且包含的文件也已经插入到.i文件
中,因此当咱们没法判断宏定义是否正确或头文件包含是否正确时,能够查看预编译后的文件来肯定问题。性能
编译过程就是把预处理完的文件进行一系列的:词法分析
、语法分析
、语义分析
及优化后生产相应的汇编代码文件
,此过程是整个程序构建的核心部分,也是最复杂的部分之一。其编译过程至关于以下命令:
$ gcc –S hello.i –o hello.s
经过上图咱们不可贵出,经过命令获得汇编输出文件hello.s
.
汇编器是将汇编代码转变成机器能够执行的指令,每个汇编语句几乎对应一条机器令。
因此汇编器的汇编过程相对于编译器来说比较简单,它没复杂的语法,也没有语义,也不须要作指令优化,只是根据汇编指令和机器指令的对照表一一翻译就能够了。其汇编过程至关于以下命令:
as hello.s –o hello.o
或者
gcc –c hello.s –o hello.o
或者使用gcc
命令从C源代码文件
开始,通过预编译、编译和汇编直接输出目标文件:
gcc –c hello.c –o hello.o
连接一般是一个让人比较费解的过程,为何汇编器不直接输出可执行文件而是输出一个目标文件呢?为何要连接?下面让咱们来看看怎么样调用ld
才能够产生一个可以正常运行的Hello World
程序:
注意默认状况没有gcc / 记得 : $ brew install gcc
连接相应的库
下面在贴出咱们的写出的源代码是如何变成目标代码的流程图:
主要经过咱们的编译器作了如下任务:扫描、语法分析、语义分析、源代码优化、代码生成和目标代码优化
到这咱们就能够获得如下的文件,不知道你是否有和我一块儿操做,玩得感受仍是不错,继续往下面看
iOS如今为了达到更牛逼的速度和优化效果,采用了LLVM
1.LLVM核心库:
LLVM
提供一个独立的连接代码优化器为许多流行CPU
(以及一些不太常见的CPU
)的代码生成支持。这些库是围绕一个指定良好的代码表示构建的,称为LLVM中间表示(“LLVM IR”)
。LLVM
还能够充当JIT编译器 - 它支持x86 / x86_64和PPC / PPC64程序集生成
,并具备针对编译速度的快速代码优化。。
2.LLVM IR
生成器Clang: Clang是一个“LLVM原生”C / C ++ / Objective-C编译器,
旨在提供惊人的快速编译(例如,在调试配置中编译Objective-C代码时比GCC快3倍),很是有用的错误和警告消息以及提供构建优秀源代码工具的平台。
3.LLDB
项目:
LLDB
项目以LLVM
和Clang
提供的库为基础,提供了一个出色的本机调试器。它使用Clang AST
和表达式解析器
,LLVM JIT,LLVM反汇编程序
等,以便提供“正常工做”的体验。在加载符号时,它也比GDB快速且内存效率更高。
4.libc
和libc++
:
libc
和libc++
ABI项目提供了C ++
标准库的标准符合性和高性能实现,包括对C ++ 11
的彻底支持。
5.lld项目
:
lld项目
旨在成为clang / llvm的内置连接器
。目前,clang必须调用系统连接器来生成可执行文件。
LLVM采用三相设计,前端Clang负责解析,验证和诊断输入代码中的错误,而后将解析的代码转换为LLVM IR,后端LLVM编译把IR经过一系列改进代码的分析和优化过程提供,而后被发送到代码生成器以生成本机机器代码。
编译器前端的任务是进行:
在这个过程当中,会进行类型检查,若是发现错误或者警告会标注出来在哪一行。
以上图解内容所作的是事情和gcc
编译一模模同样样!
.app
包,后面编译后的文件都会被放入包中;Cocoapods
会预设一些脚本,固然你也能够本身预设一些脚原本运行。这些脚本都在 Build Phases
中能够看到;Mach-O
,这过程 LLVM
的完整流程,前端、优化器、后端;storyboard
文件:storyboard
文件也是会被编译的;storyboard
文件:将编译后的 storyboard
文件连接成一个文件;Asset
文件:咱们的图片若是使用 Assets.xcassets
来管理图片,那么这些图片将会被编译成机器码,除了 icon
和 launchImage
;Cocoapods
脚本:将在编译项目以前已经编译好的依赖库和相关资源拷贝到包中。.app
包Swift
标准库拷贝到包中编译过程的确是个比较复杂的过程,还有连接!并非说难就不须要掌握,我我的建议每个进阶路上iOS开发人员,都是要了解一下的。不须要你多么牛逼,可是你能在平时的交流讨论,面试中能点出一个两个相应的点,我相信绝对是逼格满满!