欢迎来真孝善网,为您提供真孝善正能量书籍故事!

深入解析iOS静态库中的类分类及符号冲突解决方案(Xcode其他链接标志)

时间:11-08 现代故事 提交错误

这篇文章给大家聊聊关于深入解析iOS静态库中的类分类及符号冲突解决方案(Xcode其他链接标志),以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。

目标文件生成过程:当我们编写的源代码hello.c经过上述四个步骤:预压、编译、汇编和链接后,就生成了我们的可执行文件。 a. 输出。

注意:可重定位目标文件是(.o),可执行文件是(.out)。以下文章描述均遵循此名称。

了解完什么是可执行文件之后,我们再来看看静态库到底是什么?

静态库定义:

其实静态库可以简单地看成是目标文件(.o)的集合,即很多目标文件压缩打包后形成的文件。

比如我们在Linux中最常用的C语言静态库libc位于/usr/lib/libc.a,它是glibc项目的一部分。 glibc本身是用C语言开发的。它由数百或数千个C语言源代码文件组成。也就是说,编译完成后,会有相同数量的目标文件,例如用于输入和输出的printf.o和scanf.o;文件操作包括fread.o、fwrite.o;时间和日期包括date.o、time.o;内存管理包括malloc.o等,将这些分散的目标文件直接提供给库用户,很大程度上会造成文件传输、管理和组织上的不便,所以人们通常使用ar压缩程序将这些目标文件压缩在一起,并进行压缩编号并建立索引,方便查找和检索,形成静态库文件libc.a。

例如,当我们使用下面的代码时

#includeint main(int argc, const char* argv[] )

{

printf("你好世界");

}我们首先使用编译器和汇编器从上面的代码生成目标文件hello.o。

$gcc -c hello.c示例代码使用了iO函数printf(),而该函数的符号位于printf.o中,因此我们需要让链接器链接printf.o。当然,printf.o还会依赖其他目标文件,printf.o等文件都在静态库libc.a中。

我们需要让链接器(ld)静态链接到静态库libc.a来找到示例代码中需要的目标文件,并生成目标文件hello.out。

$ ld -static -e main hello.o /usr/lib/libc.a -o hello.out我们今天的主题主要在于链接与静态库这一步中

Xcode 中配置链接器(other linker flags)

其他链接器标志是xcode 集成开发环境特有的,旨在允许连接器ld除了默认参数之外,还可以添加其他参数以进行链接。

Object-C 联动功能:

“选择器无法识别”运行时异常的发生是由于标准UNIX 静态库的实现、链接器和Objective-C 的动态特性之间的问题。 Objective-C 不会为每个函数(或方法,在Objective-C 中)定义链接器符号- 相反,仅为每个类生成链接器符号。如果用类别扩展预先存在的类,则链接器不知道将核心类实现的目标代码与类别实现关联起来。这可以防止生成的应用程序中创建的对象响应类别中定义的选择器。

Objective-C 链接器不会为每个方法创建符号表,而是为每个类创建链接符号。在这种情况下,如果静态库中定义了一个现有类的分类,链接器就会认为这个类存在,不会将该分类与核心类代码关联(合并),这样就不会在静态库中找到它了。最终的可执行文件。类别中定义的方法。

例如以下错误:

Snip20170613_4.png 查看日志可以看到NSString的分类方法designByOhterLinker无法实现,而该方法确实是静态库中的分类方法。

Snip20170613_5.png如何解决这个问题?三个链接器参数:

-ObjC-all_load-force_load-dead_strip(在8.27 上更新)

-ObjC :

该标志导致链接器加载库中定义Objective-C 类或类别的每个对象文件。虽然此选项通常会导致更大的可执行文件(由于将额外的目标代码加载到应用程序中),但它将允许成功创建包含现有类类别的有效Objective-C 静态库。

添加此参数后,链接器会将静态库中的每个类和类别加载到最终的可执行文件中。当然,这个参数会导致可执行文件变大,因为可执行文件中会加载更多额外的目标代码,但这会解决Objec-C中静态库中类包含的分类问题。

从上面很明显,-ObjC将解决静态库中已经存在的类的分类问题。那么,如果静态库中存在分类,但静态库中没有该类怎么办?

重要: 对于64 位和iPhone OS 应用程序,存在一个链接器错误,该错误会阻止-ObjC 从仅包含类别而不包含类的静态库加载对象文件。解决方法是使用-allload 或-forceload 标志。

需要明确的是,使用-all_load或-force_load可以解决上述问题。

-all_load:

该参数将所有找到的目标文件加载到可执行文件中,但出现问题。如果两个静态库使用同一个可重定位目标文件(这是一个很常见的问题,例如,如果每个人的目标文件都使用名称base64.o,就会出现ld:重复符号符号冲突问题,所以是不建议使用它。

-force_load:

该参数的作用其实和-all_load一样,只不过-force_load需要指定要完整加载的库文件的路径。在这种情况下,只要一个库文件加载完成,就不会影响其他库的可重定位目标文件。的按需加载。

但还有一个最令人头痛的问题,那就是当两个静态库中使用同一个目标文件时

Snip20170613_1.png 上面两张图中的两个MyClass.o类,libMyOtherStaticLibrary.a和libMyStaticLibrary,存在冲突。

那么,此时的解决方案有两种:

1、使用-force_load让链接器指定编译一个静态库的目标文件,而不加载另一静态库的重复目标文件。

具体方法:

Snip20170613_2.png 但这样做有一个缺点。如果两个静态库同时使用分类(基本上都会使用),那么如果只允许编译器加载其中一个静态库的目标文件(-force_load),而不使用另一个静态库中的分类的话合并加载到目标文件中,也会导致运行时出现上述崩溃问题。但是如果-foce_load两个静态库,就会出现符号冲突,那怎么办呢?

2、简单来说就是把某个静态库中重复的目标文件去掉然后打包

具体方法:

1)使用压缩工具命令ar -t 检查两个静态库文件中是否有冲突的目标文件。

如下:

-Snip20170613_7.pngSnip20170613_6.png 很明显目标文件MyClass.o存在符号冲突。其实,不这样看也没关系。不管怎样,Clang编译器在编译时会报符号冲突错误,如上图Xcode报错。这是一个很好的例子,你可能会错误地看到那些目标文件是重复的。

2)去掉其中一个静态库中重复的目标文件,然后重新打包成静态库使用

首先,使用lipo命令提取其中一个iOS静态库文件(因为iOS静态库文件是合并了不同CPU架构的静态库的打包文件)。 -Snip20170613_9.png 可以看到libMyOtherStaticLibrary.a包含了armv7和arm64架构的静态库文件

提取两种不同架构的静态库文件- Snip20170613_10.png - Snip20170613_11.png。使用ar压缩工具将这两种不同架构的静态库文件以及另一个冲突的静态库文件中的目标文件去除。 -Snip20170613_12.png 从上面的命令可以看出MyClass.o已经成功从静态库中移除

使用lipo将两个不同架构的静态库重新打包封装成iOS静态库文件——Snip20170613_13.png5cac35f4-a80d-4e91-8d23-137d1d946c47.png。然后将静态库libMyOtherStaticLibraryOut.a放回项目中替换原来的。 libMyOtherStaticLibrary.a

其他链接器标志只需使用-ObjC

编译,成功!

作品,完美!

-dead_strip (2017.8.27 更新)

参数的作用是解决我们上面的可重定位目标文件(.o)中类符号的冲突问题。如果发生这种情况,使用这个参数是一个非常快捷的方法,让Clang 编译器帮助我们。可重定位目标文件问题,删除了重复符号。

但是使用这个参数有一个问题,就是如果我们使用这个参数,我们就不能使用-all_load或者-force_load,因为如果我们指定的话,编译器会帮我们决定哪些目标文件应该链接,哪些不应该链接。链接(-dead_strip),那么我们无法手动强制链接所有目标文件(-all_load或-force_load)。如果是这样的话,我们又回到了最初的问题——ObjC将解决静态库中已经存在的类的分类问题。那么,如果分类随静态库存在,但类不在静态库中怎么办?该怎么办?显然,这种情况下,你还是得用上面的方法

用户评论

短发

我最近在 iOS 项目里遇到这些问题了,好烦躁啊!

    有9位网友表示赞同!

如你所愿

静止库真的太难懂了,搞不清怎么才能把类分好类型。

    有15位网友表示赞同!

江山策

有没有大神能详细讲解一下符号冲突解决方法?

    有20位网友表示赞同!

无所谓

这个Xcode other Link Flags 我有点苦手,需要更多学习。

    有15位网友表示赞同!

漫长の人生

静态库和动态库的区别还是不太明白,希望能有详细解释的教程。

    有7位网友表示赞同!

我家的爱豆是怪比i

遇到类分类问题,真的感觉头疼啊!不知道该怎么处理。

    有16位网友表示赞同!

高冷低能儿

苹果文档里讲得太专业了,我真的看不懂...

    有16位网友表示赞同!

爱你心口难开

学习 iOS 开发好痛苦,这些问题真是让人崩溃啊!

    有7位网友表示赞同!

水波映月

求大神指点,如何在静态库中有效地分类类?

    有5位网友表示赞同!

她最好i

符号冲突处理对我来说就是个噩梦啊!希望有更好的解决方案。

    有9位网友表示赞同!

见朕骑妓的时刻

最近在看 iOS 开发这方面的东西,遇到很多关于静态库的问题,感觉很棘手啊!

    有17位网友表示赞同!

あ浅浅の嘚僾

Xcode 的链接功能真难以把握,希望官方能提供更直观的指导。

    有7位网友表示赞同!

忘故

能不能请教一下大神,如何用 Xcode other Link Flags 解决方案解决符号冲突?

    有16位网友表示赞同!

哭花了素颜

静态库中的类分类问题真的很难弄明白,求解!

    有7位网友表示赞同!

孤岛晴空

iOS 开发真是门槛高啊,静态库就有点让我望而生畏了。

    有15位网友表示赞同!

暖瞳

学习 iOS 就需要遇到各种各样的问题吧!希望可以尽快攻克静态库的问题。

    有13位网友表示赞同!

野兽之美

有没有哪本书或教程专门讲解静态库的开发知识?

    有11位网友表示赞同!

伤离别

在 iOS 开发这条道路上,不断学习和进步,相信能解决这些技术难题!

    有11位网友表示赞同!

愁杀

这个标题说的问题很有针对性,希望看到一些详细的解答方法。

    有11位网友表示赞同!

【深入解析iOS静态库中的类分类及符号冲突解决方案(Xcode其他链接标志)】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活