首页 存档 技术 查看内容

iOS 编译过程的原理和应用

2018-3-30 13:00 |来自: 互联网 257 0

摘要: 来源:黄文臣 blog.csdn.net/hello_hwc/article/details/53557308 前言 一般可以将编程语言分为两种,编译语言和直译式语言。 像C ,Objective C都是编译语言。编译语言在执行的时候,必须先通过编译器生成机器码 ...


来源:黄文臣

blog.csdn.net/hello_hwc/article/details/53557308


前言


一般可以将编程语言分为两种,编译语言和直译式语言。


像C ,Objective C都是编译语言。编译语言在执行的时候,必须先通过编译器生成机器码,机器码可以直接在CPU上执行,所以执行效率较高。


像JavaScript,Python都是直译式语言。直译式语言不需要经过编译的过程,而是在执行的时候通过一个中间的解释器将代码解释为CPU可以执行的代码。所以,较编译语言来说,直译式语言效率低一些,但是编写的更灵活,也就是为啥JS**好。


iOS开发目前的常用语言是:Objective和Swift。二者都是编译语言,换句话说都是需要编译才能执行的。二者的编译都是依赖于Clang LLVM. 篇幅**,本文只关注Objective C,因为原理上大同小异。


可能会有同学想问,我不懂编译的过程,写代码也没问题啊?这点我是不否定的。但是,充分理解了编译的过程,会对你的开发大有帮助。本文的最后,会以以下几个例子,来讲解如何合理利用XCode和编译


  • __attribute__

  • Clang警告处理

  • 预处理

  • 插入编译期脚本

  • 提高项目编译速度


对于不想看我里八嗦讲一大堆原理的同学,可以直接跳到本文的最后一个章节。




iOS编译


不管是OC还是Swift,都是采用Clang作为编译器前端,LLVM(Low level vritual machine)作为编译器后端。所以简单的编译过程如图



编译器前端


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



编译器后端


编译器后端会进行机器无关的代码优化,生成机器语言,并且进行机器相关的代码优化。iOS的编译过程,后端的处理如下


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



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





执行一次XCode build的流程


当你在XCode中,选择build的时候(快捷键command B),会执行如下过程


  • 编译信息写入辅助文件,创建编译后的文件架构(name.app)

  • 处理文件打包信息,例如在debug环境下


Entitlements:

{

"application-identifier" = "app的bundleid";

"aps-environment" = development;

}


  • 执行CocoaPod编译前脚本

    • 例如对于使用CocoaPod的工程会执行CheckPods Manifest.lock

  • 编译各个.m文件,使用CompileCclang命令。

CompileC ClassName.o ClassName.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler

export LANG=en_US.US-ASCII

export PATH="..."

clang -x objective-c -arch x86_64 -fmessage-length=0 -fobjc-arc... -Wno-missing-field-initializers ... -DDEBUG=1 ... -isysroot iPhoneSimulator10.1.sdk -fasm-blocks ... -I 上文提到的文件 -F 所需要的Framework -iquote 所需要的Framework ... -c ClassName.c -o ClassName.o


通过这个编译的命令,我们可以看到


clang是实际的编译命令

-x objective-c 指定了编译的语言

-arch x86_64制定了编译的架构,类似还有arm7等

-fobjc-arc 一些列-f开头的,指定了采用arc等信息。这个也就是为什么你可以对单独的一个.m文件采用非ARC编程。

-Wno-missing-field-initializers 一系列以-W开头的,指的是编译的警告选项,通过这些你可以定制化编译选项

-DDEBUG=1 一些列-D开头的,指的是预编译宏,通过这些宏可以实现条件编译

-iPhoneSimulator10.1.sdk 制定了编译采用的iOS SDK版本

-I 把编译信息写入指定的辅助文件

-F 链接所需要的Framework

-c ClassName.c 编译文件

-o ClassName.o 编译产物


  • 链接需要的Framework,例如Foundation.framework,AFNetworking.framework,ALiPay.fframework

  • 编译xib文件

  • 拷贝xib,图片等资源文件到结果目录

  • 编译ImageAssets

  • 处理info.plist

  • 执行CocoaPod脚本

  • 拷贝Swift标准库

  • 创建.app文件和对其签名




IPA包的内容


例如,我们通过iTunes Store下载微信,然后获得ipa安装包,然后实际看看其安装包的内容。



  • 右键ipa,重命名为.zip

  • 双击zip文件,解压缩后会得到一个文件夹。所以,ipa包就是一个普通的压缩包。



  • 右键图中的WeChat,选择显示包内容,然后就能够看到实际的ipa包内容了。




二进制文件的内容


通过XCode的Link Map File,我们可以窥探二进制文件中布局。

在XCode -

声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部