通俗来讲,库就是一段编译好的二进制代码,加上头文件可供别人使用。
库在使用的时候需要链接(Link),链接的方式有两种:静态和动态。
定义:静态库即静态链接库:可以简单看做一组目标文件的集合,即很多目标文件经过压缩打包后形成的文件。例如Windows下的lib,Linux和Mac下的.a以及Mac独有的.framework。
缺点:浪费内存和磁盘空间,模块更新困难。
静态库常见的文件格式:
xcframework:xcframework和传统framework相比:
刚刚有说过静态库就是目标文件的集合,那么到底是这样吗?
这里就拿我们最熟悉的AFNetWorking来做分析,拿到其中的.a文件
使用命令filelibAFNetworking.a查看,表明这个就是一个归档文件
刚有提到ar,通过终端来查看ar命令
使用命令ar-tlibAFNetworking.a来查看其中的文件
得以验证的确静态库是一系列目标文件的合集。
先在.m中写出对AFNetWorking的使用,然后看看如何用clang对其进行链接
可以看到clang是针对C、C++、Objc的编译器,其中包括预处理、解析、优化、代码生成、汇编化、链接。
若要链接,首先将test.m编译成为目标文件test.o
使用clang-xobjective-c\-targetarm64-apple-macos12.0.1\-fobjc-arc\-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk\-ctest.m-otest.o但是发现了报错
对于头文件找不到,我们需要告诉它路径,即HeaderSearchPath,那么对于clang来讲则是-I参数
使用命令:
clang-xobjective-c\-targetarm64-apple-macos12.0.1\-fobjc-arc\-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk\-I./AFNetworking\-ctest.m-otest.o
这时就成功生成了test.o文件
再使用命令:
clang-targetarm64-apple-macos12.0.1\-fobjc-arc\-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk\-L./AFNetworking\-lAFNetworking\test.o-otest
链接成功,得到可执行文件
clang:
1.将TestExample.m编译生成目标文件
clang-xobjective-c\-targetarm64-apple-macos12.0\-fobjc-arc\-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk\-cTestExample.m-oTestExample.o
2.把TestExample.o改名为libTestExample.dylib后再将.dylib去掉,并使用file命令查看
3.将Test.m生成目标问价Test.o
clang-xobjective-c\-targetarm64-apple-macos12.0\-fobjc-arc\-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk\-I./StaticLibrary\-ctest.m-otest.o
4.链接库生成可执行文件
clang-targetarm64-apple-macos12.0\-fobjc-arc\-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk\-L./StaticLibrary\-lTestExample\test.o-otest
5.利用lldb运行可执行文件,进入lldb环境后,使用命令filetest、run
静态库合并有两种方案,使用ar或者libtool
现在列出两个静态库文件
使用ar-xlibAFNetworking.a和ar-xlibSDWebImage.a先将两个静态库解压出所有文件
利用ar-vrcombinelib.a*.o__.SYMDEF将所有目标文件打包成combinelib.a,此时可以使用file或者ar-t命令看看合并的文件格式是否正确
先看一下libtool的文档简介
使用命令libtool-static-ocombinelib.alibAFNetworking.alibSDWebImage.a
同样完成了合并静态库,显然libtool更为简便
对于MacOS和iOS平台来说还可以使用Framework。Framework实际是一种打包方式,将库的二进制文件,头文件和有关的资源文件打包在一起,方便管理和分发。系统的Framework不需要拷贝到目标程序中,而我们自己制作的Framework哪怕是动态的也需要拷贝到目标程序中,因此这种Framework又被称为EmbeddedFramework。
Framework组成:
使用命令得到.o文件:clang-xobjective-c\-targetarm64-apple-macos12.0\-fobjc-arc\-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk\-cTestExample.m-oTestExample.o使用命令ar-rcTestExampleTestExample.o
至此Header+.a均已得到
创建Framework文件夹后并在其中创建Headers文件夹,内容如下
同样现将test.m编译为目标文件后去链接framwork
clang-xobjective-c\-targetarm64-apple-macos12.0\-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk\-fobjc-arc\-I./Frameworks/TestExample.framework/Headers\-ctest.m-otest.o
clang-targetarm64-apple-macos12.0\-fobjc-arc\-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk\-F./Frameworks\-frameworkTestExample\test.o-otest
进入lldb运行,链接成功
如果主程序对链接的静态库中的方法并未使用,那么未使用的方法是否会出现在可执行程序的代码段?
可以看到在注释的情况下静态库的代码不会出现在可执行程序的代码段。这样看起来好像并没有什么影响,反而是剥离了无用代码,但是如果链接的静态库中调用了分类的代码,这里会出现问题,因为deadcodestrip是在链接的过程中就生效了,但是分类是程序运行过程中才动态创建的。
这种情况如图所示,程序运行后会报错
那么既然是在链接过程中剥离的,可以配置参数告诉链接器如何剥离或者不剥离
默认参数时不都加载
传给链接器全部加载的参数
这样即可运行成功,但是全部链接也是duck不必,只需要保留自己需要的即可
三种方法:-all_load、-Objc、-force_load
-Objc:只保留OC方法
-force_load:对指定的全部加载
注意:-all_load、-Objc、-force_load只针对于静态库
-dead_strip是移除没有被入口或者导出符号表使用的数据和方法。