xcode构建系统及编译优化(一)

前言: 主要涉及OC工程中的部分编译相关内容,更多更具体的内容建议查看参考文献

  • (一): 介绍构建系统
  • (二): 规范实践
  • (三): 头文件映射及模块映射
  • (终): 增量构建优化技巧

xcode构建系统

摘要: 注意介绍一下构建系统流程及其有向图,明确编译任务之间的依赖关系

通过一系列有序的任务,将源代码和资源转化为产品app;
常见的任务包括编译,链接,文件操作等等;
build,run,test,profile,analyze,archive都会调用构建系统。

默认情况下,xcode会并行化构建,充分利用系统硬件的优势;
如下位置可查看:xcode -> scheme -> Build -> Paralleliza Build

构建系统工作流

  1. 决定必须构建哪些target
  2. 检索构建配置,设置,阶段,规则列表
  3. 检查对其他目标的依赖关系并构建这些目标
  4. 准备必须执行的构建任务的完整列表
  5. 如果可以进行增量构建,则准备增量构建任务列表
  6. 执行构建任务,这涉及到通过所有构建阶段。 对于每个构建阶段,在必要时应用自定义构建规则
  7. 生产产品

如下流程图:

bs_buildsystemworkflow_diagram.png

准备必须执行的构建任务的完整列表 阶段后,生成如下有向图:

415_behind_the_scenes_of_the_xcode_build_process (dragged).png

  • 构建任务的执行顺序是依照其依赖顺序决定的
  • 建立依赖的根源是任务的input及output
  • 根据依赖选择串行还是并行

有向图可以从4个层次进行抽象分析:

  • app
  • target
  • build phases
  • 源文件依赖(.m)

app:依赖主工程link完毕的可执行文件及相关资源文件,配置;

target:指明target之间的依赖关系,以便构建系统以正确且高效的顺序进行;
xcode提供了2种方式定义target的依赖关系:

  • implicit via Link Binary and Libraries(隐式依赖)
  • explicit via target dependencies (指定依赖)

implicit via Link Binary and Libraries(隐式依赖):如果 scheme设置 Find Implicit Dependencies 勾选,所有添加在当前targetLink Binaries With Libraries构建阶段中的framework or library都会建立与当前target的隐式依赖;

Screen Shot 2022-06-01 at 3.24.51 PM.png

Screen Shot 2022-05-27 at 4.21.08 PM.png

explicit via target dependencies (指定依赖):
target -> Build Phases -> Dependecies 指定当前target的依赖target;

Screen Shot 2022-05-27 at 4.29.08 PM.png

PS: framework and libraries 通过build setting 中 Other Linker Flags不会建立隐式依赖,需要手动指定依赖关系

拿cocoapods举个例子:

11.png

xcode构建系统及编译优化.png

target的编译构建必须等待其依赖的target编译构建之后才能进行;

PS:可通过在target的build phases阶段插入脚本,脚本内容是向同一个文件中追加文本来确认这种依赖顺序;

总结:

  • 通过显式指定依赖或者隐式依赖管理依赖模型,方便编译器高效且正确的运行,充分利用多核并发优势;
  • 制作组件库的时候,考虑粒度职责划分,公共部分单独抽取出来

Build Phases:通常情况下根据各阶段的排列顺序,按组运行,如果有更好的处理方法,也会忽略这个执行顺序,例如link libraries

Screen Shot 2022-05-27 at 5.59.11 PM.png

源文件依赖
target开始编译源(.m)文件之前,已经完成.h文件的检索,并将其路径写入hmap文件中;
源文件的编译是并行的

相关概念:
    增量构建:基于上次对项目的修改,只执行定向图上的相关任务子集
    任务签名:
        1. 构建图中的每个任务都有一个签名
        2. 根据input的统计信息和其他任务元数据计算签名
        3. 构建系统跟踪当前和以前构建的任务签名
        4. 比较以确定是否应运行任务
复制代码

增量构建中的依赖模型

  • oc中增量构建是基于头文件
  • swift中增量构建是基于文件

构建系统编译到源文件的时候,会根据导入的头文件,生成对应的.d文件(dependencies缩写),.d文件中列出源文件在增量构建中的所有依赖;当依赖的文件修改的时候,会触发源文件的rebuild;

.d文件路径:复制.m的编译日志到终端,加上 -v,输入内容中 (-dependency-file) 对应的就是.d文件存储路径;
复制代码

.d文件通常包括如下几种类型:

  • modulemap
  • pch
  • .h
  • self.m

在基于 C 的语言中,导入头文件(递归操作)通常会将头文件的内容复制到您的源文件中;.d文件包含所有导入的依赖;

优化思路:递归操作会导致当前的源文件依赖所有导入的头文件,但其中有部分头文件是当前源文件不需要依赖的,这部分的多余依赖链是应该被优化掉的

2.png

优化实践:

  • .h中通过@class声明, 告诉编译器存在这个类,.m中再导入头文件,这样可以切断多余的依赖链

总结:

  • 理解构建系统流程图及有向图

猜你喜欢

转载自juejin.im/post/7106876052256866335