XCode编译链接报错-静态库符号冲突问题

场景·两个静态链接库

接入了腾讯的GVoice来做语音功能,然后针对有些地区不能用GVoice的,提供了个本地录音功能。
本地录音使用的Unity录制原始数据,然后用lame库压缩成mp3。
这样在IOS上就有了两个静态库,libGCloudVoice.a和libmp3lame.a,恩怨纠葛就此展开。

问题1.本地录音崩溃

确定是调用libmp3lame.a的接口崩溃的,用XCode源码调试。

  1. 崩溃断点在汇编里,不过提示了源码位置。还好。
  2. 然后就是加入源码调试,结果失败了,断不到崩溃发生的代码文件里。Why。
  3. 修改源码加日志重新编译。一路把调用路径上的函数挨个打日志,然而找不到原因。What。
  4. 被折腾的不行时,不知怎么发现是因为和gvoice的lib冲突,链接错乱导致的错误。

网上搜了一圈,发现只要做个简单的预编译设置就好了。


image.png

这样就安稳了好一阵子。

问题2.编译链接不过

接入韩国Kakao时,Kakao要求加入-all_load编译项,然后就编译不过了。
原因是Gvoice和mp3lame都使用了lame,且都把符号导出来了。
网上搜控制静态链接库导出指定的符号,搜到一个文章。文章最后说了个简单的方法:

  1. 设置Perform Single-Object PrelinkYes
  2. Single-Object Prelink Flags里加上-unexported_symbols_list $(PROJECT_DIR)/symbol.txt

一切是那么美好,我还在参考文档的基础上自己有个-exported_symbols_file选项可以用。

XCode编译链接报错-静态库符号冲突问题_第1张图片
image.png

文件的内容是用 nm libmp3lame.a | grep 'Lame_' > xx.txt导出的。

然后,编译号了,运行nm libmp3lame.a发现还是一堆符号,What,怎么没!
然后就是一堆的折腾,搜索各种资料,折腾编译参数,还有个文章说静态链接库不可能隐藏的。
也一度怀疑一定要动态链接库-dynamic才可以使用-exported_symbols_list这类命令(实际只是不能和-static一起用)。

我真傻,真的,因为上面的设置已经能工作了。是nm用的姿势不对。正确姿势说明
查看静态链接库的全局导出符号用nm -Ug xx.a才行,g只输出全局符号,U只输出定义的符号。
nm输出的列表有个单字母描述,字母是小写的表示是局部符号。

XCode编译链接报错-静态库符号冲突问题_第2张图片
image.png

经验汇总

  1. nm -Ug xx.a才是导出静态库全局函数的有效方法,nm -D xx.a据说可以导出动态链接库的符号表
  2. 关于链接的知识:
    • 静态链接库只是简单把.o合并成一个包。这就意味着可以把所有的静态库简单合并成一个*
    • 动态链接库才真正链接成库了。
    • prelink是把*.o合并成一个.o,预先链接能链接的函数。
  3. 控制IOS的静态链接库导出指定符号的最简单方式


    XCode编译链接报错-静态库符号冲突问题_第3张图片
    image.png

参考资料

介绍了lipo,ar,nm的使用
exported_symbols_list用法
静态链接库没有办法隐藏实现了,这个是错误的,XCode可以prelink one object
解决了,是我nm用的姿势不对
nm查看符号表
gcc 控制符号表的导出
gcc编译导出想要的符号

你可能感兴趣的:(XCode编译链接报错-静态库符号冲突问题)