为业务团队发搭建效率平台,提高研发效率,高效支撑日常业务迭代一直是我们的目标。得物作为业界体量巨大的纯 swift 开发的 App,由于其庞大的组件数量, 编译速度一直是我们开发效率的拦路虎。
虽然我们做了很多的努力,让编译速度有了显著的提升,但是如果日常每一个测试包出现问题都要重新编译运行,那么这对于任何一个开发团队来说都是比较难受的。因此,我们根据Xcode的Attach to Process研发一整套的实时调试方案。
该方案使得工程师在排查问题时,可以不必进行编译,直接拿到运行App的测试机,将之连上电脑,就能够正常进行调试。能够正常下断点、输出变量名等。 2. 内容介绍
本文主要介绍得物实时调试的全套解决方案,实现对测试包还原出包环境和无需编译就可以进行断点调试的功能。整体按实时调试方案的可行性分析,方向调研,优化方案设计,推进优化落地,最后在团队推广的流程。本文主要讲4个主要内容,包括:Attach to Process介绍,环境还原,实时调试探索,组件化工程的实时调试。下面就来详细介绍下得物的实时调试方案设计。 3.Attach to Process 3.1 什么是Attach to Process ?
其实苹果对于Attach to Process的介绍很少,简而言之,就是Xcode在名为Attach to Process的Debug菜单中包含了这个功能。这会显示一个对话框,让你可以告诉Xcode等待你的应用程序的进程开始运行。
点击Attach之后Xcode 将自动附加所选择的程序到其进程并启用调试器,接着,你就可以使用 Xcode 的调试工具设置断点、调试视图层次结构等等,这意味着你无需重新编译运行就可以让Xcode来附加你的程序,并且去调试它。 3.2 Attach to Process的意义?
当你从测试手中拿到一个测试包,测试反馈说这个包有一个严重的问题,那么你想要调试这个棘手的问题的时候,尽管它会发生多少次,但是当它发生时,你会发现这个测试包没有在 Xcode 上运行。更糟糕的是,你的App代码库可能非常庞大,需要很久的编译时长才可再次运行。这时候,我们想到可以通过埋点、用户行为路径等方式来猜测这问题发生的可能性,但是这可能并不能最好的解决方式。
对于绝大多数的iOS开发来说,在XCode上使用Debug模式来调试程序才是我们最得心应手的方式,我们严重依赖断点来调试一段代码。因此Xcode提供了一个Attach to process的功能,其实这也依赖LLDB的强大功能,可以让LLDB附加到正在运行的程序中去。根据这一特性,我们就可以不必重新编译运行我们的程序来完成对测试包的断点调试。
●运行我们安装的DuAttachProcess程序,然后通过Xcode的工具栏的Debug->Attach to Process将我们的程序进行Attach,此时会有一个等待的标志,等待其完成就好。
为了更好的模拟我们的出包环境,我们需要在一个新的路径打开DuAttachProcess源码工程并且进行Attach。
结论:通过以上验证,Xocde给出的The library for the breakpoint is loaded这个条件是满足的,所以我们要看其他两个条件是否满足 。 5.3 代码的路径映射
现在我们来看第一个条件,该断点所在行的代码必须被编译。可是我们文章开头说过,实时调试是不需要编译的,但是Xcode又必须要求我们被编译,这不是自相矛盾了吗?其实是有办法可以解决的。
首先我们是不是会有疑问,Xcode是如何知道这一行有没有被编译?我们一般都会有一个简单粗暴的想法:
Xcode 在编译生生成二进制的过程中,在二进制中某个地方存储了该二进制所对应的源码的文件路径。Xcode就是通过该文件路径来判断某块代码是否被编译。
要验证这个猜想,我们必须要读取我们的可执行文件中的路径信息,我们可以通xxd这个命令来验证:
post_install do |installer|
installer.pods_project.build_configurations.each do |podConfig|
if podConfig.name == '出包时的config(debug、release、internal等)'
podConfig.build_settings["SWIFT_OPTIMIZATION_LEVEL"] = "-Onone"
end
end
end