概念
库是程序代码的集合,是共享程序代码的一种方式
开源库
公开源代码,能看到具体实现
比如:SDWebImage
、AFNetworking
闭源库
不公开源代码,是经过编译后的二进制文件,看不到具体实现
主要分为:静态库、动态库
静态库和动态库
静态库和动态库的存在形式
- 静态库:
.a
和.framework
区别:-
.a
是一个纯二进制文件,不能直接拿来使用,需要配合头文件、资源文件一起使用。在 iOS 中是作为静态库的文件名后缀。 -
.framework
中除了有二进制文件之外还有资源文件,可以拿来直接使用。
-
- 动态库:
.dylib
、.tbd
和.framework
-
.dylib
是动态库的文件的后缀名 -
.tbd
是苹果对于.dylib
的优化,为了减少下载大小,xcode7
以后取代.dylib
-
.framework
同样支持动态库
-
静态库和动态库在使用上的区别
- 静态库:链接时,静态库会被完整地复制到可执行文件中,被多次使用就有多份冗余拷贝
- 动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存
理解:
现有静态库lib
,加载时间1s,占运行内存1m,占安装包体积1m。程序A
与程序B
共同使用静态库lib
。则连续启动两程序共需加载时间2s,运行内存2m,安装包体积2m。
如果lib
改为动态库,其他不变。则连续启动两程序共需加载时间1s,运行内存1m,安装包体积2m。
app
都会使用很多相同的库,如UIKit
、CFNetwork
等。所以,苹果采用了大量动态库的形式来优化系统,以共享缓存的机制加快app
启动速度、减少内存花销。
动态库被用于多个app
的公用情况,适用于系统常用库。
被阉割的动态库
动态库本身的设计是用于多个进程,例如系统的 UIKit.Framework 。但是为了安全和主App需要和Extension共享代码,Swift语言机制也需要动态库,于是苹果后来提出了Embedded Framework。这份动态库的生命被限定在一个APP进程内。简单点可以理解为被阉割的动态库。
自定义动态库只能企业不能上传appstore
因为在上传打包的时候,苹果会对我们的代码进行一次Code Singing
,包括app
可执行文件和所有Embedded
的动态库。因此,只要你修改了某个动态库的代码,并重新签名,那么MD5
的哈希值就会不一样,在加载动态库的时候,苹果会检验这个 hash
值,当苹果监测到这个动态库非法时,就会造成Crash
本质为.o文件
解释:当多种编程语言希望混合编译时,就可以通过分别编译成.o文件,再链接(link)成可执行文件。
如何区分一个framework是静态库还是动态库
cd .../Bugly.framework
file Bugly
current ar archive random library : 表示为静态库
Bugly: Mach-O universal binary with 5 architectures: [arm_v7:current ar archive random library] [arm_v7s] [i386] [x86_64] [arm64]
Mach-O dynamically linked shared library: 表示为动态库
SDKIOS: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O dynamically linked shared library arm_v7]
静态库和动态库依赖关系
- 第一种静态库互相依赖,这种情况非常常见,制作静态库的时候只需要有被依赖的静态库头文件在就能编译出来。但是这就意味者你要收到告诉使用者你的依赖关系。
- 第二种动态库依赖动态库,两个动态库是相互隔离的具有隔离性。在制作的静态库的时候需要被依赖动态库参与链接,最终具体的符号决议交给dyld来做。
- 第三种,静态库依赖动态库,也很常见,静态库制作的时候也需要动态库参与链接,但是符号的决议交给dyld来做。
- 第四种,动态库依赖静态库,这种情况就有点特殊。首先我们设想动态库编译的时候需要静态库参与编译,但是静态库交由dyld来做符号决议,这和我们前面说的就矛盾了啊。静态库本质是一堆.o 的打包体,首先并不是二进制可执行文件,再者你无法保证主程序把静态库参与链接共同生成二进制可执行文件。
应用场景
无论是百度地图等sdk
,还是公司内部某些功能的核心代码,当不想暴露时制作成静态库。只暴露接口给外部,不暴露内部代码实现。
使用方式
Link Binary With libraries
我们可以使用Link Binary With libraries
连接系统的动态库、自己开发的静态库、自己开发的动态库。对于这里的静态库而言,会在编译链接阶段连接到app可执行文件中,而对这里的动态库而言,虽然不会链接到app可执行文件中,但是会在启动的时候就去加载这里设置的所有动态库。(ps.理论上应该是这样,但是实际测试中似乎加载不加载都和这个没关系。有待考证。)
Embedded Binaries
有待学习。。。
从源代码到app
当我们点击了 build 之后,做了什么事情呢?
- 预处理(Pre-process):把宏替换,删除注释,展开头文件,产生 .i 文件
- 编译(Compliling):把之前的 .i 文件转换成汇编语言,产生 .s文件。
- 汇编(Asembly):把汇编语言文件转换为机器码文件,产生 .o 文件。
- 链接(Link):对.o文件中的对于其他的库的引用的地方进行引用,生成最后的可执行文件(同时也包括多个 .o 文件进行 link)。
Build phases
主要是用来控制从源文件到可执行文件的整个过程的,所以应该说是面向源文件的,包括编译哪些文件,以及在编译过程中执行一些自定义的脚本什么的。
Build rules
主要是用来控制如何编译某种类型的源文件的,假如说想对某种类型的原文件进行特定的编译,那么就应该在这里进行编辑了。同时这里也会大量的运用一些 xcode 中的环境变量.。
Build settings
对编译工作的细节进行设定,在这个窗口里可以看见大量的设置选项,从编译到打包再到代码签名都有,这里要注意settings
的section
分类,同时一般通过右侧的inspector
就可以很好的理解选项的意义了。
查询链接:
例如Mapkit等框架非默认包括在主框架内,所以部分用到的框架需要手动在Link Binary With libraries
中导入
tbd是dylib的优化版本
libPods-Live.a
CocoaPods管理并生成的静态链接库
网友评论