站长统计
iOS静态库动态库依赖问题
⼀、库简介
1.1库的形式
iOS这边库可以分为静态库(StaticLibrary)和静态库(StaticLibrary)和动态库(DynamicLibrary)动态库(DynamicLibrary)
动态库Framework
静态库Framework和.a⽂件
1.2库的区别
下⽂默认读者具有静态链接&动态链接相关知识,如有不明,请翻阅mach-o分析参考
相同点:
两种库在构建的过程中,都需要经过编译,会将对应的.m⽂件编译成.o⽂件。这样也就造成了⼀夏天的活动 个问题,任何编译配置宏等已经被展开后编译
完成。也就是说,⽣成库时使⽤的Debug环境⽣成。即使将来被集成进项⽬中时,项⽬内配置Relea环境出包,不会影响到库的逻辑。因为
库中的代码是在⽣成是已经编译完成的,不随项⽬代码⼀起编译。
不同点:
1.动态库在构建的过程中,需要经过静态链接。这⾥你没有看错,动态库的⽣成需要静态链接。⽽静态库的⽣成,不需要经过静态链接,静态链接。这⾥你没有看错,动态库的⽣成需要静态链接。⽽静态库的⽣成,不需要经过静态链接,
仅仅只是简单的将对应的.o⽂件压缩。所以这⾥也可以通过命令⾏⼯具将.o⽂件重新解压缩出来。
这⾥我们重点说班级日志 ⼀下动态库,动态库和我们项⽬产出的主⼯程可执⾏⽂件对⽐,其编译、链接等过程是完全⼀样的。换句话说,动态库是⼀个
没有main函数的可执⾏⽂件。
2.在使⽤上,动态库是在程序启动运⾏时,被动态链接后执⾏元宵节的英语作文 调⽤的。⽽静态库则参与程序的静态链接,被链⼊主⼯程的⼆进制可执⾏⽂动态链接后执⾏调⽤的。⽽静态库则参与程序的静态链接,被链⼊主⼯程的⼆进制可执⾏⽂
件中。这也就是为什么,动态库需要被拷贝内嵌(embed)到包内,静态库不需要的原因。
同样,动态库A在被程序动态链接后,动态库A如果依赖动态库B,也会动态链接B。所以动态库B也需要被内嵌到包内,否则会报
错“Librarynotloadedxxx”
1.3总结
动态库和静态库,在⽣成时,因为其是否经过静态链接,产⽣了差异。动态库经过静态链接后,会经过符号决议、重定位等流程,会将依赖的静态
库链接进来,也就是说,动态库会吸附静态库。如果依赖的是动态库,则⾛动态链接的流程。
在使⽤时,因为动态库只需要动态链接,所以不会在主⼯程编译阶段报错,但可能在运⾏阶段报找不到库。静态库则需要被主⼯程静态链接,所以
当缺少符号或者符号重复冲突时,会在编译阶段报错。
这⾥注意区分库的⽣成时机、库被主⼯程引⼊编译的时机、主⼯程启动运⾏后的动态链接时机。
下⾯列出了库依赖及冲突的各种场景,尝试不看原因,看看是否能独⽴分析出,出现这种现象的原因。
⼆、库依赖场景下的符号冲突问题
2.1两个静态库
2.1.1两个静态库有相同符号:
场景:静态库A、B均采⽤Framework的⽅式来创建,其中A、B包含同⼀个类
Obj
,然后将A、B同时集成到⼯程中去。
结果:在链接(link)阶段报符号重复。
原因:A、B均需要参与主⼯程的静态链接,会在静态链接的符号决议过程中,发送冲突。
2.1.2静态库A依赖静态库B:
场景:静态库A、B均采⽤Framework(.a类似)的⽅式来创建,其中A依赖B。A库在FrameworkSearchPath中正确设置B库路径
(思考为什么可以不设置LinkBinaryWithLibraries)。A、B库代码如下:
结果:主⼯程中,如果我们A正常使⽤,B仅设置FrameworkSearchPath,让⼯程可以正确搜索到Framework,但是没有设置linker
flag,或者没有设置LinkBinaryWithLibraries。则会在编译的时候报缺少符号。
原因:A静态库⽣成过程,因为并没有经过静态链接,所以并不会包含B库的符号。A、B均需要参与主⼯程的静态链接,但此时B没有设置
LinkBinaryWithLibraries,所以会在静态链接的符号决议过程中,找不到对应的符号,报错。
推⼴:这⾥如果是静态库.a依赖静态库.framework、.a依赖.a也是⼀样的情况。
注意:上述情况有⼀个例外:.framework静态库依赖.a静态库。在这种情况下,如果我们在A库中设置了LibrarySearch
Path或LinkBinaryWithLibraries。会导致静态库的重新压缩,⽣成出来的A库会包含B库的.o⽂件。使⽤A库的时候,
也就不再需要引⼊.a静态库B,否则会报符号冲突。如果不想.a静态库B被压缩进.framework静态库A,则.framework静态
库A仅仅将.a库B的头⽂件引⼊即可,不需要设置LibrarySearchPath或LinkBin蔬菜的英语怎么写 aryWithLibraries。因为A库⽣成时仅仅
压缩,并没有静态链接,所以这样设置不会报错,只要让编译器可以正常校验通过即可。
2.2两个动态库
2.2.1两个动态库包含相同的符号:
场景:动态库A、B,其中A、B包含同⼀个类
Obj
,然后将A、B同时集成到⼯程中去。主⼯程调⽤
[Objtest];
//静态库A
@interfaceObjA:NSObjectwifi网速慢的解决办法
+(void)test;
@end
@implementationObjA
+(voi脚背肿 d)test{
NSLog(@"ObjATest");
[ObjBtest];//依赖B库中的类⽅法
}
@end
//静态库B
@interfaceObjB:NSObject
+(void)test;
@end
@implementationObjB
+(void)test{
NSLog(@"ObjBTest");
}
@end
//主⼯程中调⽤[ObjAtest];
结果:运⾏⽆异常,启动时控制台会输出⼀个警告“ClassObjisimplementedinbothxxxandxxx”。⼤概意思就是ork和
ork的可执⾏⽂件⾥⾯都包含了
Obj
这个类。⾄于选哪个,取决于linkerflag,或者LinkBinaryWithLibraries中的先后顺序,
先被动态链接的会被调⽤到。
原因:A、B均需要参与主⼯程的动态链接,仅会符号绑定(bind)⼀次,所以先绑定的会被调⽤到。
2.2.2动态库A依赖动态库B:
场景:动态库A、B,其中代码同2.1.2。A库在FrameworkSearchPath中正确设置B库路径、LinkBinaryWithLibraries也需要设置
(注意和2.1.2静态库情况的对⽐)。
结果:主⼯程这⾥同样只正确引⼊A,注意动态库需要选embed。B库不引,或者仅设置FrameworkSearchPath。结果buildsuccess,
但是程序启动就crash,控制台报错“Librarynotloadedxxx”
原因:因为A依赖B,所以B也会被动态链接。以为编译时仅仅静态链接,所以编译可以正常通过。但是因为B库没有没内嵌,所以启动时动
态链接,会报错,不能正确的加载B库。
2.3⼀动⼀静
2.3.1静态库和动态库包含相同符号:
场景:静态库A、动态库B,其中A、B包含同⼀个类
Obj
,然后将A、B同时集成到⼯程中去。主⼯程调⽤
[Objtest];
结果:运⾏⽆异常,启动时控制台会输出⼀个警告“ClassObjisimplementedinbothxxxandxxx”。主⼯程中调⽤,会调⼊静态库
A。动态库B的调⽤,会调B库⾃⼰内部的。
原因:因为静态库会在主研究生考试内容 ⼯程静态链接时,被正确的链接进⼆进制可执⾏⽂件。同样,动态库B也会在⽣成时将源码⽣成的.o⽂件正确的静态
链接进去。所以最终各⾃调⽤各⾃的。
2.3.2静态库依赖动态库:
场景及结论:静态库A、动态库B,A依赖B。⽣成A的时候,只需设置FrameworkSearchPath即可,因为⽣成A不需要静态链接,仅仅只
是压缩.o⽂件,只需要编译器不报错即可。主⼯程使⽤时,需要将A、B都引⼊。原因不在赘述,读者⾃⾏思考。
2.3.3动态库依赖静态库:
场景及结论:动态库A、静态库B,A依赖B。⽣成A的时候,不仅要设置FrameworkSearchPath,还需要设置LinkBinaryWith
Libraries,因为A需要静态链接,且会结石通片 将静态库B吸附。主⼯程使⽤时,只需要将A引⼊即可。原因不在赘述,读者⾃⾏思考。
本文发布于:2023-03-22 07:39:03,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/1679441946339125.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:aios.doc
本文 PDF 下载地址:aios.pdf
留言与评论(共有 0 条评论) |