大家在制作静态库并加入demo中调试的时候,往往会碰到两个疑问:
- 调试的时候可以直接跟到库的源码里
- 断点堆栈信息里可以看到库内部的函数调用
接下来我们就看看这其中发生了什么
问题1 为什么调试的时候可以跟到库的源码里
原因:这个问题直觉上应该是源文件的位置被记录下来了,但是记录在哪里并不太确定。后来使用文本编辑器查看了下二进制文件,发现里面确实记录了源文件的路径,同时相邻处还有XCode的安装目录和部分DEBUG信息。为了具体地确认这些信息所处位置,采用MACHOVIEW继续查看该文件,发现这些信息处于Section(__DWARF,__debug_str)段。
解决:有了上面的结论,很容易想到Build Settings里有个选项Generate Debug Symbols。于是把这个开关关上,重新编译并使用MACHOVIEW查看,发现Section(__DWARF,__debug_str)段已经没有了,拿到demo工程里调试,断点已经无法跟进源文件,问题解决。
另:虽然问题得到解决,但是我们发现在关掉Generate Debug Symbols选项后,编译出来的二进制文件同时丢掉了其他的debug信息。当然,如果仅仅是为了调试无法跟进源文件,只需要改变源码的位置就能解决。
问题2 为什么堆栈信息里可以看到库内部的函数调用
原因:这个问题应该就是二进制文件的符号表里包含了自定义库里写的方法。同样采用MACHOVIEW查看,在Symbol Table段里找到了我们写的方法以及对应的地址。
解决:那么如何去除符号表,很容易想到Build Settings里有个选项Strip Style。我们把Strip Style设为All Symbols,同时开启Deployment Postprocessing(只有在开启Deployment Postprocessing的情况下Strip Style才生效),编译之后再继续查看,惊讶地发现居然没用。在尝试了一些其他方法之后仍然没有找到原因,怎么办?
想到自己测试的静态库是采用Cocoa Touch Framework创建的,那么再试试Cocoa Touch Static Library吧。采用上面同样的配置进行编译,居然又报错了:
symbols referenced by relocation entries that can't be stripped in:`,
应该是部分符号不允许strip(具体没有深究)。那么继续修改Strip Style为Non-Global Symbols,再编译,成功之后查看,发现符号表里已经没有自定义的方法。把最新生成的静态库拿到demo工程中调试,发现堆栈中显示unnamed_symbol。看来这样做是能够去除符号信息的,那么为什么Cocoa Touch Static Library创建的库(后面简称Lib库)可以做到,而Cocoa Touch Framework创建的库(后面简称Framework库)却不行呢?我们继续查找原因。
查看Lib库的最后一次Build日志,我们发现Build的最后一个步骤是Strip libxxx.a
,调用的命令是strip -x libxxx.a
。同时查看Framework库的编译日志,发现并没有Strip这个步骤,也就是说我们的设置并没有生效。那么应该怎么做呢,我尝试了一些其他的方法,但是并没有找到解决方法,看来只能尝试手动Strip了。我们对编译完成之后framework里的二进制文件调用strip -x
在进行测试,发现确实是可行的,问题得到解决。
另:在设置了Strip Style之后,我们发现二进制文件里的Debug信息也会被清除,也就是说解决问题2的同时问题1也解决了。
其他问题
- 为什么framework库设置strip style不生效
- 为什么部分symbole不可以strip,部分可以
参考: