• 这两个东西都是编译好的二进制文件。就是用法不同而已。为什么要分为动态和静态两种库呢?先看下图:

            

ios 制作静态库 ios 静态库和动态库_动态库

           

ios 制作静态库 ios 静态库和动态库_可执行文件_02

  • 我们可以很清楚的看到:
  • 对于静态库而言,在编译链接的时候,会将静态库所有文件都添加到 目标 app 可执行文件中,并在程序运行之后,静态库app 可执行文件 一起被加载到同一块代码区中。
  • app 可执行文件: 这个目标 app 可执行文件就是 ipa解压缩后,再显示的包内容里面与app同名的文件。
  • 对于动态库而言,在编译链接的时候,只会将动态库被引用的头文件添加到目标** app 可执行文件,区别于静态库动态库** 是在程序运行的时候被添加另外一块内存区域。
  • 下面看下苹果的官方文档中有两句对动态库静态库的解释。
  • A better approach is for an app to load code into its address space when it’s actually needed, either at launch time or at runtime. The type of library that provides this flexibility is called dynamic library.
  • 动态库:可以在 运行 or 启动 的当应用真正需要的时候加载到内存中,加载到一块*独立的于 app * 的内存地址中
  • When an app is launched, the app’s code—which includes the code of the static libraries it was linked with—is loaded into the app’s address space.Applications with large executables suffer from slow launch times and large memory footprints
  • 静态库:当程序在启动的时候,会将 app 的代码(包括静态库的代码)一起在加载到 app 所处的内存地址上。相比于动态库 的方案,使用静态库将花费更多的启动时间和内存消耗。还会增加可执行文件的大小。
  • 举个🌰:假设 UIKit 编译成静态库和动态库的大小都看成 1M , 加载到内存中花销 1s . 现在又 app1 和 app2 两个 app。倘若使用静态库的方式,那么在 app1 启动的时候, 需要花销 2s 同时内存有 2M 分配给了 app1.同样的道理 加上 app2 的启动时间和内存消耗,采用静态库的方案,一共需要花销 4s 启动时间4M 内存大小4M 安装包大小。那么换成动态库的时候,对于启动和 app1 可能花费一样的时间,但是在启动 app2 的时候 不用再加载 UIKit 动态库 了。减少了 UIKit 的重复 使用问题,一共花销 3s启动时间3M 内存大小4M 安装包大小
  • 而很多 app 都会使用很多相同的库,如 UIKit *、 *CFNetwork 等。所以,苹果为了加快 app 启动速度、减少内存消耗、减少安装包体积大小,采用了大量 动态库的形式 来优化系统。dyld 的共享缓存 :在 OS X 和 iOS 上的动态链接器使用了共享缓存,共享缓存存于 /var/db/dyld/。对于每一种架构,操作系统都有一个单独的文件,文件中包含了绝大多数的动态库,这些库都已经链接为一个文件,并且已经处理好了它们之间的符号关系。当加载一个 Mach-O 文件 (一个可执行文件或者一个库) 时,动态链接器首先会检查 共享缓存 看看是否存在其中,如果存在,那么就直接从共享缓存中拿出来使用。每一个进程都把这个共享缓存映射到了自己的地址空间中。这个方法大大优化了 OS X 和 iOS 上程序的启动时间。
  • 两者都是由*.o目标文件链接而成。都是二进制文件,闭源。

 


  • 对于静态库的后缀名是.a,从 libsqlite3.dylib 这里我们可以知道 .dylib 就是动态库的文件的后缀名。细心的朋友都早已发现了从 Xcode7 我们再导入系统提供的动态库的时候,不再有.dylib了,取而代之的是.tbd。而 .tbd 其实是一个YAML本文文件,描述了需要链接的动态库的信息。主要目的是为了减少app 的下载大小
  • a是一个纯二进制文件,不能直接拿来使用,需要配合头文件、资源文件一起使用。在 iOS 中是作为静态库的文件名后缀。

 

小总结

  • 首先,相比较与静态库和动态库,动态库在包体积、启动时间还有内存占比上都是很有优势的。
  • 为了解决 .a 的文件不能直接用,还要配备 .h 和资源文件,苹果推出了一个叫做 .framework 的东西,而且还支持动态库。

 

  • 要开发一个真机和模拟器都可以调试的 Frameworks 需要对Frameworks进行合并。合并命令是 lipolipo

 

关于lipo

 

$ lipo -info /Debug-iphoneos/Someframework.framwork/Someframework

# Architectures in the fat file: Someframework are: armv7 armv7s arm64 

# 合并
$ lipo –create a.framework b.framework –output output.framework

#拆分

$ lipo –create a.framework -thin armv7 -output a-output-armv7.framework

 

  • 如果 app 要上架 appstore 在提交审核之前需要把 Frameworks 中模拟器的架构给去除掉。
  • 个人理解,项目组件化或者做 SDK 的时候,最好以 framework 的形式来做。

 

 


从源代码到app

当我们点击了 build 之后,做了什么事情呢?

  • 预处理(Pre-process):把宏替换,删除注释,展开头文件,产生 .i 文件。
  • 编译(Compliling):把之前的 .i 文件转换成汇编语言,产生 .s文件。
  • 汇编(Asembly):把汇编语言文件转换为机器码文件,产生 .o 文件。
  • 链接(Link):对.o文件中的对于其他的库的引用的地方进行引用,生成最后的可执行文件(同时也包括多个 .o 文件进行 link)。