Xcode编译流程

xcode,编译,流程 · 浏览次数 : 216

小编点评

**Xcode编译流程概述** Xcode 的构建过程可以分为以下阶段: 1. **编译计划创建**:检查依赖关系,确定编译顺序,并创建编译计划。 2. **创建构建产物目录**:创建 app 包目录,并写入项目文件结构信息到 .hmap 文件中。 3. **运行预设脚本**:运行 Cocoapods 预设脚本。 4. **编译文件**:针对每一个文件进行编译,包括 .swift 和 .m 文件。 5. **链接文件**:将项目中的所有可执行文件合并成一个文件,并链接动态链接和静态链接。 6. **拷贝资源文件**:将项目中的资源文件复制到目标 app 包中。 7. **编译,链接 storyboard 文件**:编译 .storyboard 文件,并链接动画资源。 8. **编译性语言与解释性语言**:根据语言类型编译代码。 **编译性语言** 编译性语言首先会进行词法分析,语法分析,语义分析,生成中间码。然后,优化器处理中间码,生成可执行文件。 **解释性语言** 解释性语言首先会进行代码的亮度分析,语法分析,语义分析,生成可执行的中间码。优化器后,编译器使用中间码生成最终的可执行文件。

正文

 
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编译流程相似的内容:

Xcode编译流程

Xcode的构建过程本质上是执行一系列构建任务。如:代码检测,编译代码,链接目标文件,拷贝资源(图片, plist, nib)文件,代码签名等。大部分任务是执行命令行工具,如(clang编译、 ld链接、 codesign签名, altool上传)。这些工具使用xcode项目的配置信息,根据特定的顺

XCode汇编调试

汇编调试的意义 了解常用的汇编指令和知识,可以知道经过编译器优化后,最终的代码调用,有可能和源码并不相同,如:设置faster,smallest 代码会更短,最终的汇编执行指令与源码不一样。 可以研究代码在二进制层面的执行流程是否和源码的流程一致,从二进制层面研究方法调用的传参,内部调用,方法返回值

iOS使用Run Script提升开发效率

通过在Xcode Run Script添加shell脚本,然后通过脚本来帮助我们在编译阶段完成一下资源的copy,文件替换,修改等繁琐的事件。使Xcode在编译过程中自动完成耗时繁琐的操作提升开发效率。 添加脚本的过程很简单,添加+添加 添加完脚本后可以根据需要调整脚本的执行顺序,如:对应Bundl

Xcode常用环境变量与常见使用场景

在Xcode的工程配置中,与路径相关的都是使用环境变量,这样可以避免使用决定路径时项目移植性差的问题。 Xcode常用宏 __FILE__ 当前文件所在目录 __DATE__ 编译日期的字符串,格式为“mm dd yyyy”(例如:“Sep 16 2015”) __FUNCTION__ 当前函数名称

Xcode调试内存最新理解

前提: Xcode 16.0 beta 设置 Scheme设置中勾选Malloc Scribble、Malloc Stack Logging。 这么做是为了在Memory Graph、Profile中追溯数据在哪句代码生成。 此设置会导致App硬盘占用异常增多,调试完毕之后需要把选项关闭。 Allo

Xcode的Search Paths配置

在Xcode中的文件搜索路径配置有两个地方,一个是Project层的配置,一个是Target的配置。 Project-Build Settings-Search Paths Target-Build Settings-Search Paths 在Target中的配置选项中,可以通过配置$(inher

Instruments中常用Template的使用

Instruments是苹果提供的Xcode套件,可用于分析iOS,MacOS程序的性能数据,进行性能提升。Instruments提供了很多类型的Template,用于特定场景的分析。这里选了3种常用的Template进行使用方法的讲解,对于其他Template的用法则用到时再了解吧,没必要一次把所

使用symbolicatecrash工具符号化Crash日志

对于打包上线的APP,或者打包测试的APP,出现了崩溃并不能方便的把手机链接到电脑使用XCode自动符号化,此时手动符号化就是重要的选项。 1.查找符号化工具symbolicatecrash find /Applications/Xcode.app -name symbolicatecrash -t

WWDC2023 Session系列:探索XCode15新特性

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/44a0e0fd567c4421bc94be83e84f6dce~tplv-k3u1fbpfcp-zoom-1.image) ## 一、版本说明 XCode 15 beta 发布于 2023

iOS测试包的安装方法

iOS测试包根据要安装的机器类型可以分为2种: .app模拟器测试包 .ipa真机测试包 .app模拟器测试包的安装方式 方式一:Xcode生成安装包 1.Xcode运行项目,生成app包 2.将APP包拖到模拟器中 方式二:IPA包下载得到安装包 1.将ipa包的后缀改成.zip, 然后解压 2.