Xcode的构建过程本质上是执行一系列构建任务。如:代码检测,编译代码,链接目标文件,拷贝资源(图片, plist, nib)文件,代码签名等。大部分任务是执行命令行工具,如(clang编译、 ld链接、 codesign签名, altool上传)。这些工具使用xcode项目的配置信息,根据特定的顺序执行。bulid System的工作就是创建构建任务,并协调这些任务按照正确的顺序执行。
构建任务的顺序是任务之间的依赖关系定的。
如有2个类文件,A文件和B文件, B文件使用了A文件的方法,引入了A文件。那么他们的编译任务是编译A,再编译B,等都编译好,将两个.o文件进行链接。
我们每次构建项目是对一个具体的 Target发起的,每个Target拥有自己的文件和编译规则,在项目里可以存在多个子项目,这导致了在编译的时候如果使用了 Cocoapods 或者拥有多个 target 的项目会先编译依赖库,然后再编辑当前项目。
如果使用的workspace开发,会遍历里面管理的项目,找到Target的依赖进行编译,然后再编译当前项目。这些依赖库的Target的编译过程和我们项目的编译流程是一样的。
Xcode编译流程
编译准备阶段
1.创建编译计划,检查依赖: 检查当前项目中使用的依赖库是否已经安装并能够被正确地引用;确定编译顺序,
如工程A下有子工程B,类C中引用了类D,要根据依赖关系创建编译计划,先编译独立的类,子项目;再编译有依赖的类和主项目。
2.创建构建产物过程中和结束时需要的目录

编译阶段
1.写辅助文件:创建app包目录,后面编译后的文件都会被放入app包目录中;将项目的文件结构写成.hmap映射文件,方便后面引用查询使用;
生成.hmap文件:当编译器处理.h文件时,它会生成一个.hmap文件,包含了所有的.h文件及其对应的目标文件的信息。这些信息将被用来加速下一次编译过程。.hmap文件通常被存储在Derived Data目录下。
2.运行预设脚本:Cocoapods 会预设一些脚本,当然你也可以自己预设一些脚本来运行。这些脚本都在 Build Phases 中可以看到;【'[CP] Check Pods Manifest.lock','Copy Pods Resources'】

3.编译文件:针对每一个文件进行编译,先编译.Swift后编译.m文件,可以查看每个文件的编译时间以及error和warning。
编译源码文件是编译阶段的重点,它会生成 Mach-O类型的.o文件。这过程涉及到了 LLVM三相设计的 的完整流程:编译前端、优化器、编译后端。
4.链接文件:将项目中的多个可执行文件合并成一个文件;链接分为动态链接和静态链接,这2项也是程序员必须要面对的2个重要概念,这个原理衍生了很多重要的应用场景,如:iOS原生代码的热更新,启动性能优化,APP瘦身的符号剪裁等。
5.拷贝资源文件:将项目中的资源文件拷贝到目标app包;
6.编译,链接 storyboard 文件:storyboard 文件也是会被编译的;项目中的 storyboard 会被编译成一个二进制文件,包含了界面的所有信息和结构,这个文件的后缀名为 .storyboardc。.storyboardc 文件会在链接阶段被链接到最终的应用程序中,以展示应用程序的用户界面。
7.编译 xib 文件:。 xib 文件会先解析成 XML 格式的文件,然后编译成二进制格式的文件,即 nib 文件。编译后的 nib 文件会被打包到应用程序的 bundle 中。
8.编译 Asset 文件:我们的图片如果使用 Assets.xcassets 来管理图片,那么这些图片将会被编译成机器码,除了 icon 和 launchImage;
9.运行 Cocoapods 脚本:将在编译项目之前已经编译好的依赖库和相关资源拷贝到包中。
10.将 Swift 标准库拷贝到包中

11.生成 .app 包
12.对包进行签名
13.完成打包
XCode中项目的结构关系
Target:表示一种产物类型,它有很多设置可以做细节修改,如:Build Settings, Build Phases, Build Rules。
Configuration: 构建变体,如每个Target下默认就有2个构建变体Debug, Release。 这2个构建变体的设置内容都可以进行修改,如Deubeg下不产生DSYM符号文件加速编译,Release下产生DSYM符号文件用于排查线上问题。
Scheme:产物生成驱动器,定义了产物生成的组成过程,Target和Configuaration是静态的配置定义,Scheme是对这些定义的消费。
Project:是直接容器,它直接管理者代码文件,资源文件,脚本文件等。它可以引入其他Project作为它的依赖。
WorkSpace: 它是管理Project的项目容器,在它下面管理的Project可以通过依赖而使用,如A,B是WorkSpace下的两个Project, A在它的Frameworks,Libraries..下点击“+”添加B的产物就可以使用了。如果使用cocopods时,这些会被自动做。
编译性语言与解释性语言
解释性语言:边解释边运行。特点是调试快,运行慢。
解释器在运行的时候把代码逐行做词法分析,语法分析,语义分析,生成可执行的中间码,然后执行中间码。
编译性语言:先编译成可以在CPU上直接运行的机器码,再执行。特点是运行快,调试慢。
通过编译器(采用三相设计:编译器前端,LLVM IR中间码优化器,编译器后端),将代码字符串做词法分析,语法分析,语义分析,生成中间码IR。
然后把IR中间码交给优化器做优化。
IR优化器处理完后把结果交给编译器后端编译成不同架构(arm64, i386)的可执行文件。
三相设计
假如有N种语言(C、OC、C++、Swift…)的前端,同时也有M个架构(模拟器、arm64、x86…)的Target,是否就需要 N × M 个编译器?
三相架构的价值就体现出来了,通过共享优化器的中转,很好的解决了这个问题。
假如你需要增加一种语言,只需要增加一种前端;假如你需要增加一种处理器架构,也只需要增加一种后端,而其他的地方都不需要改动。
LLVM的组成
在Xcode编译iOS项目的时候,都是使用的LLVM,其实在编写代码以及调试的时候都在接触LLVM提供的功能,例如:代码的亮度(Clang)、实时代码检查(Clang)、代码提示(Clang)、debug断点调试(LLDB)。
LLVM项目是模块化和可重用的编译器和工具链技术的集合。LLVM主要的子项目有一下几个:
1.LLVM核心库:
LLVM提供一个独立的链接代码优化器,为许多流行CPU(以及一些不太常见的CPU)的代码生成支持。
这些库是围绕一个指定良好的代码表示构建的,称为LLVM中间表示(“LLVM IR”)。
LLVM还可以充当JIT编译器 - 它支持x86 / x86_64和PPC / PPC64程序集生成,并具有针对编译速度的快速代码优化。
2.LLVM IR 生成器Clang:
Clang是LLVM的一个前端,它是LLVM的C / C ++ / Objective-C编译器,旨在提供惊人的快速编译(例如,在调试配置中编译Objective-C代码时比GCC快3倍),非常有用的错误和警告消息以及提供构建优秀源代码工具的平台。
3.LLDB项目:
LLDB项目以LLVM和Clang提供的库为基础,提供了一个出色的本机调试器。它使用Clang AST和表达式解析器,LLVM JIT,LLVM反汇编程序等,以便提供“正常工作”的体验。在加载符号时,它也比GDB快速且内存效率更高。
4.lld项目:
lld项目旨在成为clang / llvm的内置链接器。目前,clang必须调用系统链接器来生成可执行文件。
参考文章:
https://blog.csdn.net/dangyalingengjia/article/details/103336421
https://blog.csdn.net/Future_One/article/details/81882359
http://chuquan.me/2021/02/16/understand-ios-xcode-build-process/
https://xilankong.github.io/ios开发基础/2020/07/29/Xcode-build过程都做了什么.html
- [Erlang 0113] Elixir 编译流程梳理
注意:目前Elixir版本还不稳定,代码调整较大,本文随时失效 之前简单演示过如何从elixir ex代码生成并运行Erlang代码,下面仔细梳理一遍elixir文件的编译过程,书接上文,从 ...
- 加快XCode的编译链接速度(200%+)—XCode编译速度慢的解决方案
最近在开发一个大项目的时候遇到一个很头疼的问题,由于项目代码较多,每次都要编译链接1分钟左右,调试的时候很浪费时间,于是研究了一下如何提高编译链接的速度,在这里分享给大家. 提升编译链接的速度主要有以 ...
- sqlite使用xcode编译
使用xcode去开发makefile的project(Building Makefile Projects With Xcode) 新建工程,template选择 external Build Sys ...
- XCode编译文件过多导致内存吃紧解决方法
XCode编译文件过多导致内存吃紧解决方法 /Users/~~/Library/Developer/Xcode/DerivedData 1) 然后 找到编译文件 删除 就好了哦 快去试试看吧
- Gcc的编译流程分为了四个步骤:
http://blog.csdn.net/xiaohouye/article/details/52084770(转) Gcc的编译流程分为了四个步骤: 1.预处理,生成预编译文件(.文件): Gcc ...
- 编译流程,C开发常见文件类型名
编译流程 我们常说的编译是一个整体的概念,是指从源程序到可执行程序的整个过程,实际上,C语言编译的过程可以进一步细分为预编译->编译->汇编->链接 预编译是把include关键字所 ...
- iOS——为Xcode编译POCO C++静态库
一.POCO C++ library简介 POCO C++ library是一个C++编写的跨平台库,主要实现网络连接.数据库管理以及服务器,适用于跨平台.嵌入式. 二.为Xcode编译POCO C+ ...
- Nginx模块开发1_明白自定义模块的编译流程
自定义模块的编译流程 --add-module参数 configure使用--add-module参数指定添加模块目录. config脚本 由--add-module指定的目录保存为$ngx-addo ...
- Xcode编译项目出现访问private key提示框
原因: 在编译时Xcode进行codesign时需要访问"private key"时没有权限,然后让询问是否允许,有三个选项,全部允许.否绝.允许,一次弹出4个(我遇到的) 遇到问 ...
- linker command failed with exit code 1 (use -v to see invocation),经典Xcode编译错误的出现和解决!
linker command failed with exit code 1 (use -v to see invocation)这个肯定是个xcode编译运行的时候经典的报错了. 这个问题曾经在我的 ...
随机推荐
- 微信小程序页面间通的5种方式
PageModel(页面模型)对小程序而言是很重要的一个概念,从app.json中也可以看到,小程序就是由一个个页面组成的. 如上图,这是一个常见结构的小程序:首页是一个双Tab框架PageA和Pag ...
- Java集合框架个人总结
Java集合框架个人总结 集合主要分为两大类:①单列集合Collection ②双列集合Map 集合存储的都是引用类型,不可是基础类型,如果保存基础类型需要用包装类. 1.Collection接口 ...
- Unidbgrid自动调整列宽
UniDBGrid1 -> ClientEvents -> ExtEvents [Ext.data.Store[store] ] add store.load fn: function s ...
- 利用easyExcel生成excel并上传文件服务器(单独设置表头)
结合相关easyExcel的相关信息//上传服务器方法,返回url链接地址public String exportToMinIO(List<aaaDto> list) { String p ...
- XSS(Cross-site Scripting)-跨站脚本
XSS介绍 XSS 是基于 JavaScript 的,因此对该语言有基本的了解会很有帮助.了解XSS需要对客户端-服务器请求和响应有基本的了解 跨站点脚本,在网络安全社区中更广为人知的是 XSS,被归 ...
- 今日Python相关练习
1.计算日期范围内的所有日期 def get_date_list(begin_date,end_date): date_list = [] while begin_date <= end_dat ...
- PicList 现已上架Mac App Store 分享下整个上架过程和遇到的问题
PicList 是一款云存储/图床平台管理和文件上传工具,基于 PicGo 进行了深度二次开发,保留了 PicGo 的所有功能的同时,为相册添加了同步云端删除功能,同时增加了完整的云存储管理功能,包括 ...
- 依图在实时音视频中语音处理的挑战丨RTC Dev Meetup
前言 「语音处理」是实时互动领域中非常重要的一个场景,在声网发起的「RTC Dev Meetup丨语音处理在实时互动领域的技术实践和应用」 活动中,来自百度.寰宇科技和依图的技术专家,围绕该话题进行了 ...
- Spark Catalyst 查询优化器原理
这里我们讲解一下SparkSQL的优化器系统Catalyst,Catalyst本质就是一个SQL查询的优化器,而且和 大多数当前的大数据SQL处理引擎设计基本相同(Impala.Presto.Hive ...
- MyBatis 延迟加载代码详解
在我们的实际开发中,会面临各种各样的查询操作.如果单表查询能满足业务需求.尽量用单表查询,因为单表查询的效率比多表关联查询快. 那么当业务需求需要用到的数据来源于多张表的时候,单表查询无法解决,Myb ...