场景·两个静态链接库
接入了腾讯的GVoice来做语音功能,然后针对有些地区不能用GVoice的,提供了个本地录音功能。
本地录音使用的Unity录制原始数据,然后用lame库压缩成mp3。
这样在IOS上就有了两个静态库,libGCloudVoice.a和libmp3lame.a,恩怨纠葛就此展开。
问题1.本地录音崩溃
确定是调用libmp3lame.a的接口崩溃的,用XCode源码调试。
- 崩溃断点在汇编里,不过提示了源码位置。还好。
- 然后就是加入源码调试,结果失败了,断不到崩溃发生的代码文件里。Why。
- 修改源码加日志重新编译。一路把调用路径上的函数挨个打日志,然而找不到原因。What。
- 被折腾的不行时,不知怎么发现是因为和gvoice的lib冲突,链接错乱导致的错误。
网上搜了一圈,发现只要做个简单的预编译设置就好了。
这样就安稳了好一阵子。
问题2.编译链接不过
接入韩国Kakao时,Kakao要求加入-all_load
编译项,然后就编译不过了。
原因是Gvoice和mp3lame都使用了lame,且都把符号导出来了。
网上搜控制静态链接库导出指定的符号,搜到一个文章。文章最后说了个简单的方法:
- 设置
Perform Single-Object Prelink
为Yes
- 在
Single-Object Prelink Flags
里加上-unexported_symbols_list $(PROJECT_DIR)/symbol.txt
一切是那么美好,我还在参考文档的基础上自己有个-exported_symbols_file
选项可以用。
文件的内容是用
nm libmp3lame.a | grep 'Lame_' > xx.txt
导出的。
然后,编译号了,运行nm libmp3lame.a
发现还是一堆符号,What,怎么没!
然后就是一堆的折腾,搜索各种资料,折腾编译参数,还有个文章说静态链接库不可能隐藏的。
也一度怀疑一定要动态链接库-dynamic
才可以使用-exported_symbols_list
这类命令(实际只是不能和-static
一起用)。
我真傻,真的,因为上面的设置已经能工作了。是nm
用的姿势不对。正确姿势说明
查看静态链接库的全局导出符号用nm -Ug xx.a
才行,g
只输出全局符号,U
只输出定义的符号。
nm
输出的列表有个单字母描述,字母是小写的表示是局部符号。
经验汇总
-
nm -Ug xx.a
才是导出静态库全局函数的有效方法,nm -D xx.a
据说可以导出动态链接库的符号表 - 关于链接的知识:
- 静态链接库只是简单把.o合并成一个包。这就意味着可以把所有的静态库简单合并成一个*
- 动态链接库才真正链接成库了。
- prelink是把*.o合并成一个.o,预先链接能链接的函数。
-
控制IOS的静态链接库导出指定符号的最简单方式
参考资料
介绍了lipo,ar,nm的使用
exported_symbols_list用法
静态链接库没有办法隐藏实现了,这个是错误的,XCode可以prelink one object
解决了,是我nm用的姿势不对
nm查看符号表
gcc 控制符号表的导出
gcc编译导出想要的符号