概括:

  1. 文件中重复定义了一个函数、变量(比如全局变量)
  2. 工程中包含同名的文件。

一般的解决方法

  • 1 在使用import 引入头文件时,由于疏忽,误引入.m 文件。
  • 2 同名文件放在不同的文件夹下。
  • 3.在 Targets 的 Build Phrases 设置里,查看下 Complie Sources这一项,看看出现问题的类是不是重复的.如果是重复的,删除掉重新添加也能解决这个问题.
  • 4.文件里面使用C语言定义的全局变量名或是函数名,在导入的时候因为重复产生了冲突。 
    比如:在.m 文件的函数如果是用 C 语言的形式写的时候,程序在编译的时候,只看文件名,而不在乎你后面有多少参数,如果是文件名相同的话也是不行的.
    a.m中
    void drawCircle()
    b.m中
    void drawCircle(CGContextRef ctx, int radius, CGFloat centerX, CGFloat centerY)

引入.a产生冲突

参考文章1:duplicate symbol问题解决方法
参考文章2: iOS 第三方库冲突的处理
参考文章3:iOS 解决一个因三方静态库冲突产生的duplicate symbol的问题 
1. 如果是两个静态库冲突的话,可以将两个.a静态库解压,删除其中一个里面重复的.o文件(编译时产生的临时文件),然后用lipo命令合并两个静态库;比如libx.a文件

1 创建临时文件夹,用于存放armv7平台解压后的.o文件:
mkdir armv7 2 取出armv7平台的包:
lipo libx.a -thin armv7 -output armv7/libx-armv7.a 3 查看库中所包含的文件列表:
ar -t armv7/libx-armv7.a 4 进入armv7文件夹,并解压出object file(即.o后缀文件):
cd armv7 && ar xv libx-armv7.a 5 找到冲突的包(比如 JSONKit),删除掉
rm JSONKit.o 6 重新打包,生成libx-armv7.a
object file:cd .. && ar rcs libx-armv7.a armv7/*.o,可以再次使用[3]中命令确认是否已成功将文件去除 7 将其他几个平台(armv7s, i386)包逐一做上述[1-6]操作 8 重新合并为fat file的.a文件libMiPushSDK-new.a:
lipo -create libx-armv7.a libx-armv7s.a libx-i386.a -output libMiPushSDK-new.a 9 拷贝到项目中覆盖源文件:
cp libMiPushSDK-new.a /Users/tony/Desktop/XXXProject/Lib/libMiPushSDK.a

ar总结:

-t  显示库文件中所包含的文件
-x  自库文件中取出成员文件
-v  程序执行时显示详细的信息
-r  将文件插入库文件中
-c  建立库文件
-s  若库文件中包含了对象模式,可利用此参数建立备存文件的符号表。

2.工程文件和静态库冲突的话,报错会显示XXX.o文件。

1 Build Phrase里面搜索这个类名
2 显示出来的那几个 .m文件给remove掉就OK
或者(不建议下边这样)
1 在Xcode左侧,工程文件目录结构中找到.m文件
2 中并将Target Membership的勾选去掉,效果一样
注意:
对工程Add Files to一份拷贝的文件夹之后,默认选中了Target Membership。所以在工程目录的结构简单的整理一下后,有时会出现这种错误。 

拓展

1 拓展:

lipo的一些解释:
lipo 是一个在 Mac OS X 中处理通用程序(Universal Binaries)的工具。现在发售或者提供下载的许多(几乎所有)程序都打上了“Universal”标志,意味着它们同时具有 PowerPC 和 Intel 芯片能够处理的代码。不过既然你可能不在意其中的一个,你就能够使用 lipo 来给你的程序“瘦身” 

1.1 ios中合成静态库:

合成静态库:

将模拟器和设备的静态库文件合并成一个文件输出了,以后在发布可以库的时候不用发一个模拟器版的和一个真机版的了,这样子的一个库可以在编译的时候自动识别需要连接的库

lipo –create Release-iphoneos/libiphone.a Debig-iphonesimulator/libiphone.a –output libiphone.a

1.2 查看A.a中的.m文件:

查看.m文件

  看一下该文件包含几种arch
输入:file A.a
输出:
A.a: Mach-O universal binary with 2 architectures
A.a (for architecture armv7): current ar archive random library
A.a (for architecture arm64): current ar archive random library
结论:
可以看到该文件包含两种arch,分别是armv7和arm64。 2 由于下面抽离object的时候必须是要单一的库,所以这里我们抽出armv7并命名为v7.a:
输入:lipo A.a -thin armv7 -output v7.a
输出:生成一个v7.a文件。
结论:目录下多了一个v7.a文件 3 抽离.a文件的object
输入:ar -x v7.a
输出:生成一些.o文件
结论:目录下多出一些.o文件 4 获取文件,比如:View.o文件
输入:nm View.o > view.m
输出:生成view.m文件
结论:可以查看view.m文件

2 拓展:

2.1 Target membership是什么?

Target membership是指XCode中,一个文件属于哪一个工程,在XCode左侧的工程面板中选中一个文件,在XCode右侧的属性面板中会显示其Target Membership。

注意:
以前遇到一个错误,就是UIImage创建的时候返回nil,仔细查看发现,图片的Target Membership选项没有勾上。这个错误比较难以发现,特此记之。

3 拓展:

Other linker flags

    项目编译时的链接方式

3.1 编译过程:

从C代码到可执行文件经历的步骤是:源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件
在最后一步需要把.o文件和C语言运行库链接起来,这时候需要用到ld命令。源文件经过一系列处理以后,会生成对应的.obj文件,然后一个项目必然会有许多.obj文件,并且这些文件之间会有各种各样的联系,例如函数调用。链接器做的事就是把这些目标文件和所用的一些库链接在一起形成一个完整的可执行文件。
Other linker flags设置的值实际上就是ld命令执行时后面所加的参数

3.2 Xcode里-ObjC, -all_load, -force_load

下面逐个介绍3个常用参数:

-ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中

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

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

引用.a产生“selector not recognized”错误的原因:

1. Unix的标准静态库实现和Objective-C的动态特性之间有一些冲突:Objective-C没有为每个函数(或者方法)定义链接符号,它只为每个类创建链接符号。这样当在一个静态库中使用类别来扩展已有类的时候,链接器不知道如何把类原有的方法和类别中的方法整合起来,就会导致你调用类别中的方法时,出现"selector not recognized",也就是找不到方法定义的错误。为了解决这个问题,引入了-ObjC标志,它的作用就是将静态库中所有的和对象相关的文件都加载进来。

2. 本来这样就可以解决问题了,不过在64位的Mac系统或者iOS系统下,链接器有一个bug,会导致只包含有类别的静态库无法使用-ObjC标志来加载文件。变通方法是使用-all_load 或者-force_load标志,它们的作用都是加载静态库中所有文件,不过all_load作用于所有的库,而-force_load后面必须要指定具体的文件。 

4 拓展:

什么时候该用@class,什么时候该用#import进行声明

    1.一般如果有继承关系的用#import,如B是A的子类那么在B中声明A时用#import

    2. 另外就是如果有循环依赖关系,如:A->B,B->A这样相互依赖时,如果在两个文件的头文件中用#import分别声明对方,那么就会出现头文件循环利用的错误,这时在头文件中用@class声明就不会出错

    3.还有就是自定义代理的时候,如果在头文件中想声明代理的话如@interface SecondViewController:UIViewController时应用#import不然的话会出错误,注意XXXXDelegate是自定义的

Xcode工程编译之duplicate symbol问题引发的一些知识的更多相关文章

  1. xcode工程编译错误:No architectures to compile for

    问题 开发环境:xcode6,iPhone6模拟器 xcode工程编译错误:No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active ...

  2. 关于 xcode 工程编译报错 undefined symbol _res_9_init的解决办法

    将libresolv.dylib 添加到工程引用中(通过build phases中).补充:    _res_9_init定义在resolv.h中,可以参考http://www.opensource. ...

  3. xcode工程编译错误:missing required architecture i386 解决方法

    可能原因一:项目内保存了.framework文件,在复制分发到不同计算机的时候可能会引发该错误 解决方法一:来到Targets->Build Settings->Framework Sea ...

  4. Xcode工程编译错误之iOS开发之Xcode9报错 Compiling IB documents for earlier than iOS7 is no longer supported.

    概要: 在我们升级到Xcode9时,最低的编译版本为iOS8,但是在使用一些SDK的时候就会报出Compiling IB documents for earlier than iOS7 is no l ...

  5. xcode工程编译错误:一般错误总结

    1.Apple LLVM 8.0 Error Group /’all-product-headers.yaml’ not found 最近升级了xcode打包后出现了个BUG,记录解决的方法. 现象: ...

  6. Xcode工程编译错误之iOS开发之The Xcode build system has crashed. Please close and reopen your workspace

    解决方法: . 删除DerivedData . 参照上面的链接设置:File -> Workspace Settings -> Build System -> Legacy Buil ...

  7. Xcode工程编译错误:“Cannot assign to 'self' outside of a method in the init family”

    #import <Foundation/Foundation.h> @interface EOCRectangle : NSObject<NSCoding> @property ...

  8. Xcode工程编译错误之iOS开发之Sending '__strong typeof (xxx)' (aka 'xxxx *__strong') to parameter of incompatible type 'id<xxx>'

    iphone开发出现警告: Sending '__strong typeof (xxx)' (aka 'xxxx *__strong') to parameter of incompatible ty ...

  9. xcode工程编译错误之iOS解决CUICatalog: Invalid asset name supplied问题

    [问题分析]: 这个问题其实是老问题,产生原因就是因为在使用的时候 [UIImage imageNamed:]时,图片不存在或者传入的图片名为nil. [解决方法]: 添加一个系统断点,来判断如果图片 ...

随机推荐

  1. 基于Openresty+的WEB安全防护系统架构--转

    随着时间的推移,我们在实践中也不断的演进我们的服务部署方案,希望WEB防护,不只是单独的云WAF来保护服务,而有其它的相关服务,对WAF进行增强加固的合理配合.我们使用Openresty+系统构建了W ...

  2. adb命令使用总结

    1.启动/停止 启动 adb server 命令: adb start-server (一般无需手动执行此命令,在运行 adb 命令时若发现 adb server 没有启动会自动调起.) 停止 adb ...

  3. COMBINATORIAL TESTING

    COMBINATORIAL TESTING -Test note of “Essential Software Test Design” 2015-09-06 Content 16.1 Coverag ...

  4. 9款最好的JavaScript压缩工具

    削减是一个从源代码中删除不必要的字符的技术使它看起来简单而整洁.这种技术也被称为代码压缩和最小化.在这里,我们为你收集了10个最好的JavaScript压缩工具将帮助您删除不必要的空格,换行符,评论, ...

  5. C#学习笔记(33)——批量修改word标题

    说明(2017-12-22 11:20:44): 1. 因为数学脚本的主标题和副标题没有格式,目录导航里不显示,修改的时候不好定位,所以需要改成下图格式: 2. 问题的难点有两个,一个是word的操作 ...

  6. html5——canvas画布

    一.基本介绍 1,canvas是画布,可以描画线条,图片等,现代的浏览器大部分都支持. canvas的width,height默认为300*150,要指定画布大小,不能用css样式的widh,heig ...

  7. one-to-all及all-to-all网络通信模式

    在这两种模式下,因为 占用的通信通道非常高,形成了一个一对多的通道 甚至是多对多的通道,导致现有的fattree网络结构负载太大.

  8. Android TextView文字空格

     表示全角空格, <string name="aaa">你好      啊</string> http://stackoverflow.com/questi ...

  9. [Tensorflow] Cookbook - CNN

    Convolutional Neural Networks (CNNs) are responsible for the major breakthroughs in image recognitio ...

  10. iOS - UIAlertController三种显示提示框代码

    UIAlertView在IOS 8以上版本已经过时了,官方推荐我们使用UIAlertController代替UIAlertView.UIActionSheet 1、UIAlertController显 ...