美文网首页
iOS多工程联编

iOS多工程联编

作者: MoShengLive | 来源:发表于2022-12-27 18:15 被阅读0次

我们讲解多工程联编时,首先要明白为什么要多工程联编,怎么多工程联编,多工程联编的优劣点
一.首先我们介绍一下为什么要多工程联编
因为公司的项目越来越大了,业务端代码都是混乱管理,造成开发有很多痛点无法单测,无法统一管理同功能模块,快速定位bug,维护成本大,效率低,团队成员提交代码冲突机率大,CI配合效果差,功能性代码多端无法复用,编译时间长 等等痛点,所以要将项目进行模块化,组件化管理,同一个模块封装成一个工程,静态库,维护起来就高效多.下次在开发新项目时,就可以把这个工程引入进来,要用里面的功能时就可以直接使用,要我们维护好这个静态库工程,以后开发就会省事不少。
二.怎么创建多工程
对一个项目来说,将封装好的静态库直接拖到主工程里,引入头文件,详细可以网上搜索
三.多工程联编的优劣点
这个是重点,有关编译效率问题,性能问题,如果不好,比之前还慢,那就没有必要了,
1.APP打包运行原理:Objective和Swift都是编译语言,换句话说都是需要编译才能执行的
不管是OC还是Swift,都是采用Clang作为编译器前端,LLVM(Low level vritual machine)作为编译器后端。所以简单的编译过程如图


D42876FB-39BB-4558-B07A-A8A68E922B61.png

编译器前端:编译器前端的任务是进行:语法分析,语义分析,生成中间代码(intermediate representation )。在这个过程中,会进行类型检查,如果发现错误或者警告会标注出来在哪一行

编译器后端:编译器后端会进行机器无关的代码优化,生成机器语言,并且进行机器相关的代码优化

执行一次XCode build的流程:当你在XCode中,选择build的时候(快捷键command+B),会执行如下过程

1),编译信息写入辅助文件,创建编译后的文件架构(name.app)
2),处理文件打包信息
3),执行CocoaPod编译前脚本,例如对于使用CocoaPod的工程会执行CheckPods Manifest.lock
4),编译各个.m文件,使用CompileC和clang命令
5),链接需要的Framework,例如Foundation.framework,AFNetworking.framework,ALiPay.fframework
6),编译xib文件
7),拷贝xib,图片等资源文件到结果目录
8),编译ImageAssets
9),处理info.plist
10),拷贝Swift标准库
11),创建.app文件和对其签名
我们在每次编译过后,都会生成一个dsym文件。dsym文件中,存储了16进制的函数地址映射。在App实际执行的二进制文件中,是通过地址来调用方法的
在APP启动运行时:
系统首先加载可执行文件(自身App的所有.o文件的集合),然后加载动态链接库dyld,dyld是一个专门用来加载动态链接库的库。 执行从dyld开始,dyld从可执行文件的依赖开始, 递归加载所有的依赖动态链接库。
动态链接库包括:iOS 中用到的所有系统 framework,加载OC runtime方法的libobjc,系统级别的libSystem,例如libdispatch(GCD)和libsystem_blocks (Block)。
其实无论对于系统的动态链接库还是对于App本身的可执行文件而言,他们都算是image(镜像),而每个App都是以image(镜像)为单位进行加载的
image究竟包括哪些呢?
1).executable可执行文件 比如.o文件。
2).dylib 动态链接库 framework就是动态链接库和相应资源包含在一起的一个文件夹结构。
3).bundle 资源文件 只能用dlopen加载,不推荐使用这种方式加载。


6C48480E-2FB8-4150-BEFC-E937BA13D2EB.png

如上图所示,不同进程之间共用系统dylib的_TEXT区,但是各自维护对应的_DATA区
所有动态链接库和我们App中的静态库.a和所有类文件编译后的.o文件最终都是由dyld(the dynamic link editor),Apple的动态链接器来加载到内存中。每个image都是由一个叫做ImageLoader的类来负责加载(一一对应)
什么是ImageLoader
image 表示一个二进制文件(可执行文件或 so 文件),里面是被编译过的符号、代码等,所以 ImageLoader 作用是将这些文件加载进内存,且每一个文件对应一个ImageLoader实例来负责加载。
两步走:
在程序运行时它先将动态链接的 image 递归加载 (也就是上面测试栈中一串的递归调用的时刻)。
再从可执行文件 image 递归加载所有符号。
动态链接库加载的具体流程
1).load dylibs image 读取库镜像文件
2).Rebase image
3).Bind image
4).Objc setup
5).initializers
后面会详细介绍,这里不做介绍
总结有一点:减少非系统库的依赖,减少不必要的framework,因为动态链接比较耗时
2,我们进行封装时,可以封装成静态库和动态库
先介绍一下静态库和动态库
动态库形式:.dylib和.framework
静态库形式:.a和.framework
静态库:
1),首先将源文件编译成目标文件:gcc –c a.c b.c,
2),生成静态库:ar –rc libstatic.a a.o b.o
当程序与静态库连接时,库中目标文件所含的所有将被程序使用的函数的机器码被copy到最终的可执行文件中。这就会导致最终生成的可执行代码量相对变多,相当于编译器将代码补充完整了,这样运行起来相对就快些。不过会有个缺点: 占用磁盘和内存空间. 静态库会被添加到和它连接的每个程序中, 而且这些程序运行时, 都会被加载到内存中. 无形中又多消耗了更多的内存空间.
官网文档说明:


421ABA36-81A9-432F-86CF-D4FDE4622125.png
动态库:

1),同静态库一样编译成目标文件:gcc –c a.c b.c

2),生成共享库:gcc –fPIC –shared –o libshared.so a.o b.o

由此可见静态库和动态库都是对目标文件的处理,也可以说库文件已经是机器码文件了

与共享库连接的可执行文件只包含它需要的函数的引用表,而不是所有的函数代码,只有在程序执行时, 那些需要的函数代码才被拷贝到内存中。这样就使可执行文件比较小, 节省磁盘空间,更进一步,操作系统使用虚拟内存,使得一份共享库驻留在内存中被多个程序使用,也同时节约了内存。不过由于运行时要去链接库会花费一定的时间,执行速度相对会慢一些,总的来说静态库是牺牲了空间效率,换取了时间效率,共享库是牺牲了时间效率换取了空间效率.

官网文档说明:


E64F092B-00E1-4A72-B226-781E8C710D64.png

2,编译分析,性能问题
上面讲到了打包的原理,包括Apple提供的静态库和动态库解析原理,多工程联编无非我们关心是编译时间,效率问题,及封装成库的之间相互调用效率问题
1),在编译效率上,打包成Framework或者 static library,这样编译的时候这部分代码就不需要重新编译了,从这里可以看出封装成framework,编译时间跟之前是一样,有时会更少


image.png

2),封装成静态库调用效率,性能问题

image.png
而动态库,在调用时比较耗时,上面介绍动态库有官网文档截图
注意:Apple对待第三方开发者使用动态库的态度却是极端的否定,所以在iOS 7之前如果使用动态库是肯定会被reject的,reason。但在2014年Xcode6和iOS 8发布时却开放了这个禁地,应该主要是为了App Extension
Swift 与 Framework 的关系
在Xcode 6.0 Beta 4的 Release Notes 中,可以找到这句话:
B74B1C47-6818-448A-A177-1A1F977EBC1F.png
共享可执行文件 iOS 有沙箱机制,不能跨App间共享共态库,但Apple开放了App Extension,可以在App和Extension间共间动态库(这也许是Apple开放动态链接库的唯一原因了)

这个就引入必须要用到动态库,嵌入式动态库Embedded Framework

官网文档说明:

A82AEE92-CADB-4554-8B70-07A2F3DC42B8.png

一般我们项目都是cocoapod管理第三方,cocoapod必须use_frameworks,
cocoapods 会生成相应的 .frameworks文件(动态链接库:实际内容为 Header + 动态链接库 + 资源文件),使用 dynamicframeworks 来取代 staticlibraries 方式
3,总结,封装模块,静态库/动态库在编译效率会快点,但是在相互之间调用效率没有直接调用快,封装成静态库调用,效率相差不大,由于swift项目里,必须是动态链接库,所以调用效率方面会略差一点,而且封装成库也会引入依赖库,也会影响效率,这是一个取舍问题,封装成库,便于管理,定位bug,维护起来成本也低

相关文章

  • IOS组件化-多工程联编

    当一个工程随着时间的推移,开发人员的增加,工程变得硕大且不好维护,提交代码冲突重重,是时候考虑项目的组件化了。若从...

  • OC多工程联编

    1.主工程是:YYTDemo 平级的子工程是:YYTLIb2.主工程引用子工程3.新建 一个workspace之...

  • xcode 多工程联编

    多工程联编一般用于测试 SDK工程,可以将多个SDK放入一个工程,或者多个工程来测试一个SDK。这里说一下我遇到的...

  • 【转】iOS 组件化 多工程联编

    https://www.jianshu.com/p/a8359ef03d7f[https://www.jiansh...

  • workspace多工程联编设置

    自行搜索https://blog.csdn.net/qiuyinthree/article/details/510...

  • 多工程联编的坑

    主工程的设置 设置Header Search Path 2.Link Binary With Libraies 3...

  • 项目实现多工程联编

    在一个Xcode工作空间(.xcworkspace)建立多个工程(.xcodeproj)。目的是为了加快编译(bu...

  • iOS Framework工程中添加测试工程,多工程联调

    iOS Framework工程中添加测试工程,多工程联调 需求描述 在一个工程中同时包含Frameweork工程、...

  • iOS开发之多工程联编

    在iOS应用开发中,随着开发 的深入,项目的规范也越来越高,为了更加方便的管理自定义静态库与pods之间的联系,我...

  • iOS开发之多工程联编

    在iOS应用开发中,为了开发的规范性,在当前的项目工程文件中引入静态库或者其他工程,并与Cocoapods 配合使...

网友评论

      本文标题:iOS多工程联编

      本文链接:https://www.haomeiwen.com/subject/pixaqdtx.html