杂症一、 -all_load跳坑
在项目集成qiyu(七鱼客服)后,发现编译报错:
duplicate symbol _gost_do_sign in: /Users/renzhenfei/Desktop/Sharing-iOS/ShareBag/Pods/QIYU_iOS_SDK/SDK/libcrypto.a(gost_sign.o) /Users/renzhenfei/Desktop/Sharing-iOS/ShareBag/ShareBag/General/thirdPartFrameWork/Meitu/
很明显,上面报错信息就是项目中存在了重复的symbol,也就是qiyu客服SDK中和项目中原来的产生了冲突。通过 查看七鱼客服的集成文档发现,如果项目中其他的SDK中已经集成了OpenSSL,机会产生冲突,解决方法就是:不要导入七鱼的libcrypto.a文件。
image.png
按照提示删除了libcrypto.a文件后,结果又报错了:
ld: library not found for -lcrypto clang: error: linker command failed with exit code 1 (use -v to see invocation)
library找不着了,就这样被困在了这里。删除和保留都不行。最后没办法将冲突的两个SDK集成到一个新项目中,看看是否报错。结果竟然是好的。那就是我的项目配置问题了。然后突然想起来Other Linker Flags这个链接配置,里面不知道啥时候加了-all_load这个祸害🙃。删除这个祸害后再次编译就好了。
反思
究其原因怪自己对Other Linker Flags中的配置不够熟悉,不能第一时间定位到问题。下面总结一下:
-ObjC:
加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中。
如果集成一个三方库的时候发现"selector not recognized"错误,三方库中的category方法找不到,很有可能就是没有添加-Objc参数导致的。
-all_load:
会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很 有可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force_load参数。
-force_load:
所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载。
杂症二、旧项目迁移部分功能,报错:ld: symbol(s) not found for architecture arm64
因为旧项目比较大,想要将部分的功能迁移过来,然后就一个个frame拷贝了过来,最后拷贝的差不多的时候,编译通过,链接报错,报错部分信息如下:
"mtnn::MTVector<mtnn::MTBlob>::~MTVector()", referenced from:
l1166 in libMTSkin.a
l1171 in libMTSkin.a
l1174 in libMTSkin.a
l1179 in libMTSkin.a
l1183 in libMTSkin.a
l1253 in libMTSkin.a
l1448 in libMTSkin.a
...
"mtnn::MTBlob::~MTBlob()", referenced from:
l857 in libMTSkin.a
l858 in libMTSkin.a
l878 in libMTSkin.a
l879 in libMTSkin.a
l890 in libMTSkin.a
l891 in libMTSkin.a
l1032 in libMTSkin.a
...
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
因为设计引用到的是C++的库,所以语法可能有些看不懂。例如 "mtnn::MTVector<mtnn::MTBlob>::~MTVector()",虽然看不懂C++语法,但是发现里面的MTVector这个关键字,应该是一个对象。然后就到新项目中去搜索这个类,看看是否存在。最后发现这个对象存在的framework已经被导入进来了。然后再搜索其他的关键字:MTBlob、mtnn。没有搜索到,那么问题应该就是缺少包含这两个对象的静态库导致的。然后去原来的旧项目中搜索这个库就行了。
小技巧:在项目中直接全局搜索的话,是搜索不到库文件的.h文件内容的。如果手动查找就比较费劲了。我们可以借助命令行的查找命令:
grep -R targetName searchPath
这条命令就是在指定的目录下面(searchPath),搜索包含targetName的内容。搜索的是路径下全部文件的内容。
如果要搜索目录下的文件名:
find tagetPath -name targetName
其中的targePath 和 targetName 替换成搜索的路径和名称。
知识扩展
类似 "ld: framework not found"的错误的原因:
1、路径不对,配置的路径下framework search path或者library search path找不到类库。
2、other linker flags里面没有加入三方库:
-framework “targetFramework”表示加入的是framework,如果要加入的是.a,则需要用-l"xxxx"。如果集成了C++库的话还要加入-l"c++"。
杂症三、 将framework设置为optional导致的运行时的崩溃:Thread 1: signal SIGABRT
在代码调试的过程中为了保证编译通过,将新加入的framework设置成了optional,这样编译链接阶段是没有问题了。导致了后来的运行阶段的报错,而且没有明确的错误信息。运行阶段直接抛出了错误“Thread 1: signal SIGABRT”。然后崩溃定位到了调用framework某个C++方法的地方。可以定位到与该framework有关,但是查了下在项目的链接库中已经引入了该framework,并且搜索的framework路径也添加好了。这下就不太好定位问题了。后来仔细检查了一遍发现在链接库中将framework设置成了optional,然后改为required后再次运行发现已经有了错误提示信息了:“reason image not found”。就是镜像文件没有找到,这下总算是定位到问题了,接下来就是解决了。google一搜索,解决方法就出来了:
image.png
杂症四、 Universal Link采坑
Universal Link相关的配置都做好后(相关配置请百度),在备忘录输入配置的Associated Domains地址后,点击可以直接跳转app。但是在safari以及微信中点击该地址无法直接跳转。这就是Universal的一个坑,要想通过微信或者safari跳转到我们的app,必须有一个承载页面,然后在承载界面上增加一个点击事件,点击后调用Universal Link对应的链接。这样就可以跳转了。
例如我们配置的Universal Link 地址为https://abc.trytry.com。如果在safari中直接点击该地址,是不能跳转的。然后我们做一个承载页(该承载页的域名必须和Universal Link的域名不一样),比如https://def.trytry.com,然后在该承载页点击按钮调用https://abc.trytry.com/main (/main为universal配置文件中的路径)。就可以跳转了。
网友评论