库
什么是库
- 库的本质是一段编译好的二进制代码,加上头文件就可以供别人使用。
- 库从广义上可分为开源库和闭源库, 而闭源库才分为静态库和动态库
- 开源库:对外公开源代码, 能看到具体的代码实现, 例如Github上面的第三方开源库都称之为开源库
- 闭源库:不公开源代码, 文件是经过编译后的二进制文件, 看不到具体实现
为什么要用库
- 保护代码:某些代码需要给别人使用,但是我们不希望别人看到源码,就需要以库的形式进行封装,只暴露出头文件
- 提高编译速度:对于某些不会进行大的改动的代码,我们想减少编译的时间,就可以把它打包成库,因为库是已经编译好的二进制了,编译的时候只需要 Link 一下,不会浪费编译时间
静态库和动态库
上面提到库在使用的时候需要 Link,Link 的方式有两种,静态和动态,于是便产生了静态库和动态库
静态库
静态库即静态链接库(Windows 下的 .lib,Linux 和 Mac 下的 .a)
之所以叫做静态,是因为静态库在编译的时候会被直接拷贝一份,复制到目标程序里,这段代码在目标程序里就不会再改变了
所以如果两个程序都用了某个静态库,那么每个二进制可执行文件里面其实都含有这份静态库的代码
优点是编译完成之后,目标程序不再依赖库文件,直接就可以运行
缺点是会使用目标程序的体积增大
动态库
动态库即动态链接库(Windows 下的 .dll,Linux 下的 .so,Mac 下的 .dylib/.tbd)
与静态库相反,动态库在编译时并不会被拷贝到目标程序中,目标程序中只会存储指向动态库的引用。等到程序运行时,动态库才会被真正加载进来
优点是,不会影响目标程序的体积(不需要拷贝到目标程序中),而且同一份库可以被多个程序共享使用;同时,编译时才载入的特性,也可以让我们随时对库进行替换,而不需要重新编译代码
缺点是,动态载入会带来一部分性能损失,使用动态库也会使得程序依赖于外部环境。如果环境缺少动态库或者库的版本不正确,就会导致程序无法运行(Linux 下喜闻乐见的 lib not found 错误)
Framework
什么是 Framework
Framework 是Cocoa/Cocoa Touch程序中使用的一种资源打包方式,可以将代码文件(.a)、头文件、资源文件、说明文档等集中在一起,方便开发者使用
系统的 Framework 是动态库,开发者自己开发的 Framework 是静态库
其实是资源打包的方式,和静态库动态库的本质是没有关系的
苹果在iOS平台上规定不允许存在动态库,但是为了 App 和 Extension 能够共享代码,提出了 Embedded Framework
.a与.framework的区别
- .a是一个纯二进制文件不能直接使用,必须要有.h文件才能使用,.h文件对外提供接口
- .framework中除了有二进制文件之外还有资源文件,可以直接使用
所以开发中建议使用.framework
.a、.dylib 和 .tbd
.a:静态库的后缀名
.dylib:动态库的后缀名
.tbd:text-based stub libraries
,本质上就是一个YAML描述的文本文件。iOS 7 之后取代 .dylib。具体请看这里
动态 Framework 和静态 Framework
使用 file
命令可以判断 .framework 中的可执行文件是动态还是静态
1 | file GPUImage.framework/GPUImage |
1 | file TVKPlayer.framework/TVKPlayer |
可以看到 GPUImage 有 dynamic
,它是动态 framework,而 TVKPlayer 是静态的
如果是动态的 Framework,添加到工程的时候需要在 Embedded Binaries
下面手动添加,意思是嵌入,并不是嵌入 app 可执行文件,而是嵌入 app 的 bundle 文件。当一个 app 通过 Embedded 的方式嵌入一个 app 后,在打包之后解压 ipa 可以在包内看到一个 framework 的文件夹,下面都是与这个应用相关的动态 framework
如果是静态的 Framework,添加到工程的时候需要在 Linked Frameworks and Libraries
添加,这些 Framework 将会被拷贝到 App 的可执行文件中
架构
1 | // 1. 模拟器使用的CPU架构: |
1 | // 2. 真机使用的CPU架构: |
命令
查看 .a 支持的架构
lipo -info xxx.a
合并成通用架构
lipo -create 模拟器架构.a 真机架构.a -output 目标通用架构.a