这是一个经典的编译报错问题。相信大部分做iOS开发的同学都遇到过。刚开始遇到这个问题时,我会先尝试去改改build settings里面的配置,或者寄希望于clean,实在搞不定的时候,就到网上去搜,搜到的解决方法确实很多,但是能够解决问题的却很少,那是因为导致该问题的原因非常多,别人的方法不一定适用。后来认识到这样的解决问题思路是错误的。不应该没有目的地去尝试,而应该从关键的提示"symbols not found for architecture xxx"入手,分析出可能导致该问题的原因,然后再有目的地去解决问题,做到对症下药,这样效率才会高。
"symbols not found for architecture xxx",意思是二进制代码中缺少xxx(如arm64,下文以arm64为例)架构。编译器的错误提示肯定不会错,那么为什么二进制代码中会缺少xxx呢?在解决问题之前,不妨先分析一下。
项目中的二进制代码一般有两个来源,一是项目build实时编译出来的,二是引入的第三方库(这里指已经编译成二进制的第三方库,如.a或.framework文件)。对于第一种情况,毫无疑问,肯定是编译时遇到某种问题,导致编译不成功,因而缺少arm64;对于第二种情况,因为是已经编译完成的,则有两种可能。第一种可能是第三方库本身就不包含arm64,第二种可能是,虽然第三方库包含了arm64,但是编译器却没有找到。总结一下,导致该问题的本质原因大概有三种:
- 确实不存在arm64
- 存在arm64但是找不到
- 因为某种原因编译不成功
抓住这三种本质原因,是解决问题的关键。下面逐一举一些这几种原因的例子和解决方案。
一、二进制中确实不存在arm64
可以通过在终端中使用如下命令查看二进制文件所包含的架构:
lipo -info xxx
如得到结果:
$ lipo -info Hyphenate.framework/Hyphenate
Architectures in the fat file: Hyphenate.framework/Hyphenate are: i386 x86_64
说明该二进制中确实不包含arm64,如果引入了这样的二进制文件,在运行到真机时就会报错。
解决办法:
找到包含arm64架构的二进制文件。
二、存在arm64但是找不到
1、第三方库(.a或者.framework)没有添加到Linked Framworks and Libraries
有时候引入第三方库(主要是静态库,如.a文件),是包含arm64架构的,但是导入工程时方式不对,使得.a文件没有添加到Linked Framworks and Libraries列表中,这时候编译器编译时会找不到该.a文件,就会报错。
解决办法:
将相应的.a文件添加到Linked Framworks and Libraries中,就能解决问题。
2、第三方库(.a或者.framework)缺少系统依赖库
有些第三方库,本身是依赖一些系统库的,以Bugly为例,在官网上的集成文档中,就会提醒用户添加依赖,需要添加的依赖有:
- SystemConfiguration.framework
- Security.framework
- libz.dylib 或 libz.tbd
- libc++.dylib 或 libc++.tbd
需要把这些依赖库添加到Linked Framworks and Libraries。如果忘记添加这些,编译器无法编译库文件,因此就会找不到,就会报错。
解决办法:
将第三方库的依赖系统库添加到Linked Framworks and Libraries中
三、因为某种原因编译不成功
1、building settings中architecture不包含arm64
这种情况应该大部分人都知道,你告诉编译器不编译arm64的架构,但是又要运行在arm64架构的手机上,当然会报错啦。
解决办法:
这种情况的解决办法就是,在building settings中,architectures中添加arm64架构。
2、.m文件没有添加到build phase
有时候因为某种原因,使得.m文件没有添加到build phases, Compile Sources中,导致编译失败,也会报这种错误。
解决办法:
在build phases, Compile Sources中重新添加.m文件。
3、.m文件重复
项目中如果存在,两个相同的.m文件,同样会导致编译失败,也会报这种错误。
解决办法:
删除重复的.m文件。
4、-ObjC配置
集成第三方库时,有时候需要做-ObjC配置,-ObjC的作用是将静态库中任何Objective-C代码都链接到APP中,不配置的话,有时会使工程因文件找不到编译失败,会报这种错误。
解决办法:
Build Settings -> Linking -> Other Linker Flags ,添加上 -ObjC
5、集成含C++的库
有些第三方库包含C++代码,用C++编译器编译得到的。如果引入了这种第三方库(最典型的例子是百度地图SDK),工程也需要使用C++编译器编译,否则会因编译失败报错。
解决办法:
最简单的解决办法是将工程中任意一个.m文件改成.mm后缀。
6、bitcode问题
有时候如果引入的第三方库没有使用bitcode,但是主工程中building settings的Enable Bitcode开关打开了,会引起编译失败,也会报"symbols not found for architecture xxx"错误,当然也会有bitcode关键字的错误提示,比较明显,也比较好解决。
解决办法:
将主工程中Enable Bitcode开关关闭。
目前只想到这些,但实际中肯定不止这些,后面遇到了再更新。只要把握造成该问题的本质原因,相信任何这种报错的问题都能够迎刃而解。