APP编译过程

栏目: IOS · 发布时间: 5年前

内容简介:LLVM本身并不是编译器,只是一套用于开发编译器、解释器等程序语言相关工具的LLVM1 an umbrella project that hosts and develops a set of close-knit low-level toolchain components (e.g., assemblers, compilers, debuggers, etc.) LLVM 是一个涵盖和开发一系列紧密结合的低级工具链组件(例如,汇编器,编译器,调试器等)的综合项目传统的编译器通常分为三个部分,前端(fr

LLVM本身并不是编译器,只是一套用于开发编译器、解释器等程序语言相关 工具 ,主要聚焦于编译器后端功能,如代码生成、代码优化、JIT等。

LLVM1 an umbrella project that hosts and develops a set of close-knit low-level toolchain components (e.g., assemblers, compilers, debuggers, etc.) LLVM 是一个涵盖和开发一系列紧密结合的低级工具链组件(例如,汇编器,编译器,调试器等)的综合项目

传统的编译器通常分为三个部分,前端(frontEnd),优化器(Optimizer)和后端(backEnd),在编译过程中,前端主要负责词法和语法分析,将源代码转化为 抽象语法树 ;优化器则是在前端的基础上,对得到的中间代码进行优化,使代码更加高效;后端则是将已经优化的中间代码转化为针对各自平台的机器代码。

APP编译过程

Clang

Clang 是一个C、C++、Objective-C和Objective-C++编程语言的编译器前端。它采用了LLVM作为其后端。

Clang是2005年由苹果电脑发起,是LLVM编译器工具集的前端(front-end),目的是输出代码对应的抽象语法树(Abstract Syntax Tree, AST),并将代码编译成LLVM Bitcode。接着在后端(back-end)使用LLVM编译成平台相关的机器语言 。Clang支持C、C++、Objective C。

Clang本身性能优异,其生成的AST所耗用掉的内存仅仅是GCC的20%左右,测试证明Clang编译Objective-C代码时速度为GCC的3倍,还能针对用户发生的编译错误准确地给出建议。

iOS中的编译

Objective C采用Clang作为前端,而Swift则采用swift()作为前端,二者LLVM(Low level vritual machine)作为编译器后端。编译过程如下图

APP编译过程

来看看一个文件的编译过程,新建Test.m

#import <Foundation/Foundation.h>

int main(){
    @autoreleasepool {
        NSLog(@"%@",@"Hello Leo");
    }
    return 0;
}

复制代码

在终端输入: clang -ccc-print-phases -framework Foundation test.m -o test 会看到下列的:

0: input, "Foundation", object 
1: input, "test.m", objective-c
2: preprocessor, {1}, objective-c-cpp-output//预处理
3: compiler, {2}, ir //编译生成IR(中间代码)
4: backend, {3}, assembler//汇编器生成汇编代码
5: assembler, {4}, object//生成机器码
6: linker, {0, 5}, image//链接
7: bind-arch, "x86_64", {6}, image//生成Image,也就是最后的可执行文件
复制代码

编译器前端

编译器前端的任务是进行:语法分析,语义分析,生成中间代码(intermediate representation )。在这个过程中,会进行类型检查,如果发现错误或者警告会标注出来在哪一行。

APP编译过程

编译器优化

LVVM优化器会进行BitCode的生成,链接期优化等等

APP编译过程

编译器后端

LLVM机器码生成器会针对不同的架构,比如arm64等生成不同的机器码

APP编译过程

四、Xcode执行Build的流程

  • 编译信息写入辅助文件,创建编译后的文件架构(name.app)
  • 写入辅助文件:将项目的文件结构对应表、将要执行的脚本、项目依赖库的文件结构对应表写成文件,方便后面使用
  • 运行预设脚本:Cocoapods 会预设一些脚本,当然你也可以自己预设一些脚本来运行。这些脚本都在 Build Phases 中可以看到;
  • 编译文件:针对每一个文件进行编译,生成可执行文件 Mach-O,这过程 LLVM 的完整流程,前端、优化器、后端;使用CompileC和clang命令。
  • 链接库,例如Foundation.framework,AFNetworking.framework…
  • 拷贝资源文件:将项目中的资源文件拷贝到目标包;
  • 编译 storyboard 文件:storyboard 文件也是会被编译的;
  • 链接 storyboard 文件:将编译后的 storyboard 文件链接成一个文件;
  • 编译 Asset 文件:我们的图片如果使用 Assets.xcassets 来管理图片,那么这些图片将会被编译成机器码,除了 icon 和 launchImage;
  • 运行 Cocoapods 脚本:将在编译项目之前已经编译好的依赖库和相关资源拷贝到包中。
  • 创建.app文件和对其签名

dSYM 文件

我们在每次编译过后,都会生成一个dsym文件。dsym文件中,存储了16进制的函数地址映射。

在App实际执行的二进制文件中,是通过地址来调用方法的。在App crash的时候,第三方工具(Fabric,友盟等)会帮我们抓到崩溃的调用栈,调用栈里会包含crash地址的调用信息。然后,通过dSYM文件,我们就可以由地址映射到具体的函数位置。

五、提高项目Build速度

查看编译时间

我们需要一个途径,能够看到编译的时间,这样才能有个对比,知道我们的优化究竟有没有效果。 对于XCode 8,关闭XCode,终端输入以下指令 $ defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES

代码优化-forward declaration

@class CLASSNAME,而不是#import CLASSNAME.h。这样,编译器能大大提高#import的替换速度。

对常用工具类打包

打包成Framework或者静态库,这样编译的时候这部分代码就不需要重新编译了。

常用头文件放到预编译文件里

XCode的pch文件是 预编译文件 ,这里的内容在执行XCode build之前就已经被预编译,并且引入到每一个.m文件里了。

Debug模式下,不生成dsym文件

上文提到了,dysm文件里存储了调试信息,在Debug模式下,我们可以借助XCode和LLDB进行调试。所以,不需要生成额外的dsym文件来降低编译速度。

Debug开启Build Active Architecture Only

在XCode -> Build Settings -> Build Active Architecture Only 改为YES。这样做,可以只编译当前的版本,比如arm7/arm64等等,记得只开启Debug模式。这个选项在高版本的XCode中自动开启了。


以上所述就是小编给大家介绍的《APP编译过程》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

重启

重启

米奇•乔尔 / 曲强 / 中信出版社 / 2014-6-10 / 45.00元

罗振宇、丹尼尔•平克、赛斯•高汀、丹•艾瑞里、谢家华、阿里安娜•赫芬顿强烈推荐! 美国亚马逊2013年年度商业&投资类图书榜前20名! 互联网时代五大剧变让企业和个人无处可逃 进化,或被扔在旧时代? 全球顶尖的数字预言家独特分享 商业转型与思维转型的实践指南 当个人变为互联世界中的一个节点,如何开启新的工作方式? 如何与顾客建立直接关系?如何进行实用主义营......一起来看看 《重启》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具