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

Xcode编译流程的更多相关文章

  1. [Erlang 0113] Elixir 编译流程梳理

    注意:目前Elixir版本还不稳定,代码调整较大,本文随时失效      之前简单演示过如何从elixir ex代码生成并运行Erlang代码,下面仔细梳理一遍elixir文件的编译过程,书接上文,从 ...

  2. 加快XCode的编译链接速度(200%+)—XCode编译速度慢的解决方案

    最近在开发一个大项目的时候遇到一个很头疼的问题,由于项目代码较多,每次都要编译链接1分钟左右,调试的时候很浪费时间,于是研究了一下如何提高编译链接的速度,在这里分享给大家. 提升编译链接的速度主要有以 ...

  3. sqlite使用xcode编译

    使用xcode去开发makefile的project(Building Makefile Projects With Xcode) 新建工程,template选择 external Build Sys ...

  4. XCode编译文件过多导致内存吃紧解决方法

    XCode编译文件过多导致内存吃紧解决方法 /Users/~~/Library/Developer/Xcode/DerivedData 1) 然后 找到编译文件 删除 就好了哦 快去试试看吧

  5. Gcc的编译流程分为了四个步骤:

    http://blog.csdn.net/xiaohouye/article/details/52084770(转) Gcc的编译流程分为了四个步骤: 1.预处理,生成预编译文件(.文件): Gcc ...

  6. 编译流程,C开发常见文件类型名

    编译流程 我们常说的编译是一个整体的概念,是指从源程序到可执行程序的整个过程,实际上,C语言编译的过程可以进一步细分为预编译->编译->汇编->链接 预编译是把include关键字所 ...

  7. iOS——为Xcode编译POCO C++静态库

    一.POCO C++ library简介 POCO C++ library是一个C++编写的跨平台库,主要实现网络连接.数据库管理以及服务器,适用于跨平台.嵌入式. 二.为Xcode编译POCO C+ ...

  8. Nginx模块开发1_明白自定义模块的编译流程

    自定义模块的编译流程 --add-module参数 configure使用--add-module参数指定添加模块目录. config脚本 由--add-module指定的目录保存为$ngx-addo ...

  9. Xcode编译项目出现访问private key提示框

    原因: 在编译时Xcode进行codesign时需要访问"private key"时没有权限,然后让询问是否允许,有三个选项,全部允许.否绝.允许,一次弹出4个(我遇到的) 遇到问 ...

  10. 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编译运行的时候经典的报错了. 这个问题曾经在我的 ...

随机推荐

  1. 【前端样式】关于Element-plus 菜单 unique-opened不生效的问题

    需要保证el-sub-menu 的唯一性,即index得写在el-sub-menu上,否则 unique-opened 属性不生效.

  2. selenium 设置时区

    driver = webdriver.Chrome() tz_params = {'timezoneId': 'America/New_York'} driver.execute_cdp_cmd('E ...

  3. IDEA设置自定义代码模板

    1. 进入IDEA界面,File–>Settings 注:其中, $END$代表打印字符串后光标所处的位置 如: System.out.println($END$); 表示输出后光标在()里面.

  4. c++方便的输出vector和map_重载的应用 【python一样写c++、二】

    写程序,尤其是调试的时候,会想着直接输出一个map或者vector来调错. 但本来的cout<<没有这种功能.我们就会想了,要是c++能和python一样,直接输出一个列表(vector) ...

  5. 解密Prompt系列3. 冻结LM微调Prompt: Prefix-Tuning & Prompt-Tuning & P-Tuning

    这一章我们介绍在下游任务微调中固定LM参数,只微调Prompt的相关模型.这类模型的优势很直观就是微调的参数量小,能大幅降低LLM的微调参数量,是轻量级的微调替代品.和前两章微调LM和全部冻结的pro ...

  6. DVWA-File Inclusion(文件包含)

    文件包含漏洞,当我们在一个代码文件想要引入.嵌套另一个代码文件的时候,就是文件包含. 常见的文件包含函数有include require等函数. 这两个函数的区别就是include在包含文件不存在时p ...

  7. 取出预训练模型中间层的输出(pytorch)

    1 遍历子模块直接提取 对于简单的模型,可以采用直接遍历子模块的方法,取出相应name模块的输出,不对模型做任何改动.该方法的缺点在于,只能得到其子模块的输出,而对于使用nn.Sequensial() ...

  8. day01-2-依赖管理和自动配置

    依赖管理和自动配置 1.依赖管理 1.1什么是依赖管理 spring-boot-starter-parent 中还有父项目,声明了开发中常用的依赖的版本号 并且进行自动版本仲裁,即如果程序员没有指定某 ...

  9. Linux & 标准C语言学习 <DAY2>

    vim文本编辑器:     可以直接在终端下采用纯键盘操作的一款文本编辑器,号称编辑器之神,可以二次升级.可以扩展     基础用法:         1.进入vim:             输入 ...

  10. 用Java代码验证三门问题

    三门问题(Monty Hall problem)亦称为蒙提霍尔问题,出自美国的电视游戏节目Let's Make a Deal. 问题名字来自该节目的主持人蒙提·霍尔(Monty Hall).参赛者会看 ...