iOS 项目编译流程(OC&Swift)

627 阅读5分钟
  • LLVM 概述

LLVM是架构编译器(compiler)的框架系统,以c++编写而成,用于优化使用任意程序编写的程序的编译时间(compile-time)链接时间(link-time)运行时间(run-time) 以及 空闲时间(idle-time),对开发者保持开放,并兼容已有脚本。

  • Objective-C编译过程

1. 预处理

主要处理文件中以#开头的预编译命令 比如宏定义替换,引入的头文件进行内容替换

2. 词法分析

将代码分解成一个一个独立的词法符号(Token)

3. 语法分析

将词法分析的结果生成对应的抽象语法树,并验证语法的正确性

4. 语义分析

对整个语句进行判别是否有问题

5. 生成中间代码

编译器前端的产物,生成与机器无关的中间代码。

  • Class/Meta Class/Protocol/Category 内存结构生成,并放在指定的section中。

  • Method/Ivar/Property内存结构生成

  • 组成method_list/iva_list/property_list并填入Class

  • 为每个ivar合成偏移量

  • 将语法树中的ObjCMessageExpr翻译成相应版本的objc_msgSend等等

  • 根据修饰符strong、weak、copy、atomic合成@property自动实现的setter/getter

  • 生成block_layout的数据结构

  • block数据结构捕获相应的变量

  • 分析对象引用关系,将objc_storeStrong/objc_storeWeak等ARC代码插入

  • 自动实现调用【super dealloc】

  • 为每个拥有ivar的class合成.cxx_destructor方法来自动释放类的成员变量

  • Bitcode 生成字节码

6. 目标代码生成与优化

Optimizer对前端产物进行优化,再交给后端根据不同的机器指令集生成对应的机器代码,生成对应的Mach-O文件

7. 对Mach-O,静态文件等进行link,生成可执行文件,写入对应的.app包里

8. 拷贝项目中的资源文件到对应的.app包里

9. 编译xib和storyboard

10. link xib和storyboard的产物

11. 如果有自定义的脚本,执行脚本(Build Phase 里的Run Script 可以设置自定义的脚本)

12.处理info.plist文件(具体处理什么,不太清楚)

13.生成DSYM文件

14.如果有混编swift,就会将swift的标准库拷贝到对应的.app包里(所以混编oc和swift会增大包体积)

15.代码签名

出于安全考虑,为了防止代码被篡改,最后的可执行文件会被codeSign进行签名。app运行的时候会去校验签名

苹果 app签名过程:

苹果的要求

1.为了保证系统的安全性,所有iPhone上安装的应用必须是经过苹果授权的 2.安全包不需要上传到App Store也能被安装 (开发调试 企业灰度) 3.防止真能干书权限呗滥用:设备限制、指定APP、iCloud/PUSH/后运行等附加权限控制

苹果的解决方案:双层代码签名+描述文件: 这里有一张图

WechatIMG324.jpeg

在iOS出来之前,主流的操作系统(MacOS/Windows)软件随便从哪里下载都能运行,系统安全存在隐患,盗版软件、病毒入侵、静默安装等等,苹果希望解决类似的问题,保证在iPhone iOS上的APP都是经过苹果官方允许的,怎样保证呢?就是通过代码签名

如果要实现验证,最简单的方式就是苹果官方生成一对RSA公私钥,在iOS系统中内置一个公钥,私钥由苹果后台保存,我们上传APP到App Store时苹果后台用私钥对APP数据进行加密,iPhone下载APP后用公钥验证这个签名就可以确认APP是否经过允许或被三方篡改过。但是,我们安装APP并不仅仅只有App Store这一个方式,比如真机调试、企业包等,所以只靠这个简单的数字签名方式是不够的。

于是苹果设计了双层签名的机制,我们都知道iOS的应用开发必须在Mac系统下进行,正是由于这个依赖关系,双层签名才有了基础:

  1. 在Mac系统中生成一对非对称加密算法的公私钥M(Xcode会帮你做好)
  2. 苹果自己有固定的一对公私钥,正如上述最简单的代码签名中提到的:私钥A在苹果后台,公钥A在每个iOS系统的手机中
  3. 把公钥M以及一些开发者信息(也就是CSR文件)发送给苹果后台,用苹果后台的私钥A对公钥M签名,得到一份包含公钥M以及其签名结果的数据就是证书(.p12)。
  4. 在开发时,当我们打包时会用本地的私钥M(也就是可导出给小伙伴的开发者证书)对这个APP进行签名,同时把第三步得到的证书一起打包进APP里,然后安装到手机上(真机联调)或者提交App Store审核
  5. 安装时,iOS系统取得内置公钥A去验证公钥M的数字签名证书是否正确
  6. 验证公钥M是苹果认证过的后,再用公钥M去验证APP的签名,这样就间接验证了这个APP的安装是经过苹果允许的了(注意这里只验证安装行为,不验证APP是否被改动,因为开发阶段APP内容总是不断变化的)

有了上面的过程已经可以保证开发者的认证和程序的安全了,但是如果只有上述的过程,那岂不是只要申请了一个证书就可以安装到所有的iOS设备了?所以,苹果又增加了授权文件(Provisioning profile)的验证,Provisioning profile一般包括三样东西:证书、APP ID、设备。

 描述文件是在AppleDevelop网站创建的(在Xcode中填上AppleID它会代办创建),Xcode运行时会打包进入APP内。在开发时,编译完一个 APP 后,用本地的私钥M对这个APP进行签名,同时把从苹果服务器得到的 Provisioning Profile 文件打包进APP里,文件名为embedded.mobileprovision,当把APP安装到手机上时,iOS系统会进行验证。

swift编译过程:Swift编译过程

参考: iOSAPP签名机制