关于Xcode的Other Linker Flags

背景

在ios开发过程中,有时候会用到第三方的静态库(.a文件),然后导入后发现编译正常但运行时会出现selector not recognized的错误,从而导致app闪退。接着仔细阅读库文件的说明文档,你可能会在文档中发现诸如在Other Linker Flags中加入-ObjC或者-all_load这样的解决方法。

那么,Other Linker Flags到底是用来干什么的呢?还有-ObjC-all_load到底发挥了什么作用呢?

链接器

首先,要说明一下Other Linker Flags到底是用来干嘛的。说白了,就是ld命令除了默认参数外的其他参数。ld命令实现的是链接器的工作,详细说明可以在终端man ld查看。

如果有人不清楚链接器是什么东西的话,我可以作个简单的说明。

一个程序从简单易读的代码到可执行文件往往要经历以下步骤:

源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件

源文件经过一系列处理以后,会生成对应的.obj文件,然后一个项目必然会有许多.obj文件,并且这些文件之间会有各种各样的联系,例如函数调用。链接器做的事就是把这些目标文件和所用的一些库链接在一起形成一个完整的可执行文件。

可能我描述的比较肤浅,因为我自己了解的也不是很深,建议大家读一下这篇文章,可以对链接器做的事情有个大概的了解:链接器做了什么

为什么会闪退

苹果官方Q&A上有这么一段话:

The "selector not recognized" runtime exception occurs due to an issue between the implementation of standard UNIX static libraries, the linker and the dynamic nature of Objective-C. Objective-C does not define linker symbols for each function (or method, in Objective-C) - instead, linker symbols are only generated for each class. If you extend a pre-existing class with categories, the linker does not know to associate the object code of the core class implementation and the category implementation. This prevents objects created in the resulting application from responding to a selector that is defined in the category.

翻译过来,大概意思就是Objective-C的链接器并不会为每个方法建立符号表,而是仅仅为类建立了符号表。这样的话,如果静态库中定义了已存在的一个类的分类,链接器就会以为这个类已经存在,不会把分类和核心类的代码合起来。这样的话,在最后的可执行文件中,就会缺少分类里的代码,这样函数调用就失败了。

解决方法

解决方法在背景那块我就提到了,就是在Other Linker Flags里加上所需的参数,用到的参数一般有以下3个:

  • -ObjC
  • -all_load
  • -force_load

下面来说说每个参数存在的意义和具体做的事情。

首先是-ObjC,一般这个参数足够解决前面提到的问题,苹果官方说明如下:

This flag causes the linker to load every object file in the library that defines an Objective-C class or category. While this option will typically result in a larger executable (due to additional object code loaded into the application), it will allow the successful creation of effective Objective-C static libraries that contain categories on existing classes.

简单说来,加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中,虽然这样可能会因为加载了很多不必要的文件而导致可执行文件变大,但是这个参数很好地解决了我们所遇到的问题。但是事实真的是这样的吗?

如果-ObjC参数真的这么有效,那么事情就会简单多了。

Important: For 64-bit and iPhone OS applications, there is a linker bug that prevents -ObjC from loading objects files from static libraries that contain only categories and no classes. The workaround is to use the -allload or -forceload flags.

当静态库中只有分类而没有类的时候,-ObjC参数就会失效了。这时候,就需要使用-all_load或者-force_load了。

-all_load会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force_load参数。

-force_load所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载。

时间: 2024-08-27 03:35:30

关于Xcode的Other Linker Flags的相关文章

XCODE:<iOS>other linker flags

在工程中导入XMPP第三库时,出现link错误,错误如下: Undefined symbols for architecture i386: "_iconv", referenced from: _mem_cd_iconv in libidn.a(striconv.o) _str_cd_iconv in libidn.a(striconv.o) (maybe you meant: _str_iconv, _str_cd_iconv , _mem_cd_iconv ) "_ic

iOS other linker flags

我是写swift项目的,引入了腾讯云视频的SDK,录制视频,播放视频都正常,但是一点击上传视频,app就crash掉了. 当时项目是在Xcode7下运行,报的错就一句话: libc++abi.dylib: terminating with uncaught exception of type NSException . 只有这句话,在没有任何详细的报错信息下,我把代码断点后,也一直发现不了原因.跟腾讯的技术支持交流,那个人他说他也是第一次见这种错误,最后说可能是oc与swift混编的问题,叫我用

<iOS>关于Xcode上的Other linker flags

<iOS>关于Xcode上的Other linker flags Targets选项下有Other linker flags的设置,用来填写XCode的链接器参数,如:-ObjC -all_load -force_load等.还记得我们在学习C程序的时候,从C代码到可执行文件经历的步骤是:源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件在最后一步需要把.o文件和C语言运行库链接起来,这时候需要用到ld命令.源文件经过一系列

xcode:关于Other Linker Flags

http://blog.csdn.net/tammy_min/article/details/12854595 三.主要参数 这里要说的主要参数是ld工具的参数,也是在Other Linker Flags里常用到的参数. 1.-ObjC 当使用ObjC写的静态类别库(Objective-C static library that contains categories),在程序编译链接时,如果不在Other Linker Flags中填写-ObjC,往往会报错,出现"selector not r

iOS 关于Xcode上的Other linker flags

博客来源  http://www.cnblogs.com/robinkey/archive/2013/05/27/3101095.html Targets选项下有Other linker flags的设置,用来填写XCode的链接器参数,如:-ObjC -all_load -force_load等.还记得我们在学习C程序的时候,从C代码到可执行文件经历的步骤是:源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件在最后一步需要把.o文件和

关于Xcode上的Other linker flags

一.问题说明 之前下了一个第三方的静态库.a,然后在运行时一直提示 2015-06-14 15:38:33.135 BRTExample[5890:695264] -[CBUUID toString]: unrecognized selector sent to instance 0x1742281c0 2015-06-14 15:38:33.135 BRTExample[5890:695264] *** Terminating app due to uncaught exception 'NS

Xcode 编辑器之关于Other Linker Flags相关问题

一,概述 问题场景一 当从网上去下载一些之前的完整的项目的时候,用终端也 pod update了,但一运行,熟悉的linker错误就出来了. 解决办法 在Other Linker Flags(也即 OTHER_LDFLAGS)中添加$(inherited). 在Header/Framework Search Paths(也即HEADER_SEARCH_PATHS和FRAMEWORK_SEARCH_PATHS) 添加$(PODS_ROOT)/Headers. 问题场景二 当从网上下载第三方类库拉到

Targets选项下有Other linker flags的设置

Targets选项下有Other linker flags的设置,用来填写XCode的链接器参数,如:-ObjC -all_load -force_load -allod等. 下面逐个介绍3个常用参数:-ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中-all_load:会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到ld: du

Other Linker Flags

原文出自:http://alloc.sinaapp.com/wp/?p=272 一.关于Other Linker Flags xcode中,在“Targets”选项下有Other Linker Flags选项,在这里可以填写xcode链接器的参数,如:-ObjC.-all_load.-force_load等. 二.xcode链接器 xcode采用的链接器为ld–GNU,ld是GNU工具链中的一个软件,主要用于将obj文件连接成可执行文件.同时你能使用自己的脚本来控制ld的行为,这是你可以通过-T