iOS 静态库和动态库相关
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS 静态库和动态库相关相关的知识,希望对你有一定的参考价值。
参考技术A 查看.a静态库和framework支持的架构示例:
终端测试:
iPhone真机和模拟器的CPU架构
静态库和framework真机和模拟器库二合一
首先,分别编译成真机framework和模拟器framework,
接着,利用上面的命令查看各个framework的架构
最后,利用如下命令进行合并:
如果输出的数字不为0,就代表包含bitcode
由于app中二进制和framework中二进制文件与.a文件存在差异,因为需要检查的是__LLVM段,当出现该段的时候,则表示支持bitcdoe,否则不支持。
示例:
这里otool有个bug,当你的framework使用过lipo命令,进行拆解和合并之后,需要指定指令集进行检查才可以。
示例:
终端测试:
1、cd xx.framework
2、file xx 注释:xx为.framwork下的二进制文件
3、判断:
4、查看库所支持的指令集,如arm_v7,x86_64
终端测试:
!!!待完善
ios 终端查看framework和.a的支持架构
检测App、静态库、framework是否支持bitcode,otool分析.o文件
如何检测.a和.framework是否支持bitcode
如何辨别.framework是动态库还是静态库
iOS中的静态库和动态库
什么是库
库
是共享程序代码的方式,库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。
库的类型
一般分为静态库
和动态库
。
静态库一般是xxx.a
的形式,动态库一般在windows下是xxx.dll
、在Linux下是xxx.so
,在Mac下是系统的动态库是xxx.tbd
(以前为.dylib
)的形式。
静态库
利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。
动态库
对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。
静态库与动态库的区别
静态库
:在编译时完整地拷贝至可执行文件中,被多次使⽤就有多份冗余拷贝。
动态库
:在编译时不需要拷贝到可执行文件中,程序运行时由系统动态加载到内存,供程序调用。
共同点
:静态库和动态库都是闭源库,只能拿来满足某个功能的使用,不会暴露内部具体的代码信息。
静态库和动态库的优缺对比
静态库优点
:静态库在编译完成之后,库文件实际上就没有作用了,目标程序没有外部依赖,直接就可以运行。
静态库缺点
:静态库需要拷贝至可执行文件中,所以会使用目标程序的体积增大。如果一次性加载的内容过多,会造成App启动慢。
动态库优点
:系统只加载一次,就可以使多个程序共用,节省内存。
动态库缺点
:动态载入会带来一部分性能损失,使用动态库也会使得程序依赖于外部环境;如果环境缺少动态库或者库的版本不正确,就会导致程序无法运行。
库在iOS中的形式
iOS中静态库形式:xxx.a
和 xxx.framework
。
iOS中动态库形式:xxx.tbd
(或xxx.dylib
)和 xxx.framework
。
.framework和.a的区别
.a
是一个纯二进制文件
,.framework
中除了有二进制文件之外还有资源文件。.a
文件不能直接使用,至少要有.h
文件配合,.framework
文件可以直接使用(.h
等资源已经在其内部,图片资源一般再打一个.bundle
文件)。
所以 .a + .h + sourceFile = .framework。总之,也建议大家使用.framework的形式。
从源码到可执行文件
先来看看编译过程,为我后面说到的做个铺垫。当我们点击了 build 之后,做了什么事情呢?
1.预处理(Pre-process):把宏替换,删除注释,展开头文件,产生 .i 文件。
2.编译(Compliling):把之前的 .i 文件转换成汇编语言,产生 .s文件。
3.汇编(Asembly):把汇编语言文件转换为机器码文件,产生 .o 文件。
4.链接(Link):对.o文件中的对于其他的库的引用的地方进行引用,生成最后的可执行文件(同时也包括多个 .o 文件进行 link)。
以一个简单的sum文件源代码为例,介绍一下从源码到app的过程。
int sum(int a, int b)
return a+b;
首先,先预处理为.i
文件,gcc -E sum.c -o sum.i。
再编译为汇编文件, gcc -S sum.i -o sum.s。
再汇编为二进制的.o
文件,gcc -c sum.s -o sum.o。
.o
文件就是C/C++编译的二进制文件,因为C/C++编译的单元编译。每一个.c/.cpp
文件就是一个编译单元,把所有单元都编译好之后,再连接成一个完整的程序。
静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为.a
。.a
文件实质上就是.o
文件打了个包。
动态库编译链接时,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。
iOS详细过程
Clang的任务:预处理、词法分析、语法分析、语义分析、静态分析、生成中间代码。
预处理:以#开头的代码预处理。包括引入的头文件和自定义宏。
词法分析:每一个.m源文件的声明和定义从string转化为特殊的标记流。
语法分析:将标记流解析成一颗抽象语法树( abstract syntax tree-AST)。
静态分析:包含类型检查和其他检查。
中间代码生成:生成LLVM代码。
LLVM的任务:将代码进行优化并产生汇编代码。
汇编器:将可读的汇编代码转换为机器代码,最终创建一个目标对象.o文件。
链接器的任务:把目标文件和库相连,最终输出可运行文件:a.out。
Mach-O文件
编译链接的结果应该是a.out
文件的,但是有一中Mach-O
文件。Mach-O
是Mach Object文件格式的缩写,是mac上可执行文件的格式,目标代码,动态库,内核转储的文件格式。类似于windows上的PE格式 (Portable Executable ), linux上的elf格式 (Executable and Linking Format)。
它作为a.out
格式的替代,Mach-O
提供了更强的扩展性,并提升了符号表中信息的访问速度。在这里Mach-O
文件其实就是a.out
文件。在制作framework 的时候需要选择Mach-O Type
,下面即将说到。
Mach-O Type
framework既可以是静态库又可以是动态库,gcc在编译时默认使用动态库,而且系统的framework也都是默认动态的,而我们创建的framework
一般都是静态库。在Xcode中可以配置Mach-O type
,为Mach-O
文件设置类型,可以决定framework的类型。如下图:
Mach-O
文件类型分为以下五个,整好对应上面图片中的五个选项:
Executable
:应用的主要二进制。
Dynamic Library
:动态链接库。
Static Library
:静态链接库。
Bundle
:不能被链接的tbd或dylib,只能在运行时使用dlopen()或者NSBundle动态加载,可当做macOS的插件。
Relocatable Object File
:可重定向文件类型,即.m
,.c
等文件编译出来的目标文件,文件后缀是.o
。
设置为Dynamic Library
的framework,需要注意一点。自己编译的动态库和系统动态库在本质上是一样的,只是使用方式不一样。自己编译的动态库由于签名校验限制,只能当作静态库一样使用;系统的动态库不受签名校验限制,可以动态加载。
相关文章:
创建你自己的framework
iOS编译与app启动
以上是关于iOS 静态库和动态库相关的主要内容,如果未能解决你的问题,请参考以下文章