Debug CocoaPods with VSCode
Updtes:
- 2019-09-18 GitHub 中已添加了使用 bundler 辅助 debug 的方式,已不需要下面这些 dirty hack,所以本文已没有存在的意义,具体步骤可以看这个 GitHub 仓库
前一段时间同事介绍了可以用 RubyMine 调试 CocoaPods 源码的方法,看后感觉很神奇。因为之前读 CocoaPods 源码不知道如何调试 Ruby 程序,都是用比较原始的打 log 方式,其实挺低效的,毕竟 log + 断点结合起来才是开发 debug 的最好方式。
但比起 JetBrains 家的 IDE,我更喜欢用 VSCode,所以就研究了一下如何使用它来 debug CocoaPods 源码及 CocoaPods 周边插件。
研究过程中有几个点还是挺有趣的,所以写出来分享一下。
如何加载我们手动指定路径的 pod 插件?
这就要先从 pod 插件的加载过程说起。
CocoaPods 的插件加载是依托于 CLAide 的,具体的查看方法可以看这里。CLAide 中的
PluginManager
会遍历所有的 Ruby Gem,并搜索这些 gem 中是否包含名为 #{plugin_prefix}_plugin
的文件。Pod::Command
继承了 CLAide::Command
,并声明 plugin_prefix
为 %w(claide cocoapods)
。也就是说在 pod 命令执行时,会加载所有包含
claide_plugin.rb
或 cocoapods_plugin.rb
文件的 gem。如果插件是通过这种方式加载的话,那 debug 插件就比较困难了,只能把插件通过
rake install
的方式安装在电脑系统中,才能验证插件功能是否正常,是比较低效的。这也是本文出现的原因。要想实现加载指定路径的 Gem 为 CocoaPods 插件,就需要手动干预这一过程。这一部分的代码在这里可以找到(也是本仓库唯一的一点代码),主要过程是 patch 了
Gem::Specification
的 latest_specs
方法,覆盖或追加一个我们指定路径的 gem 到加载的列表中。如果对 Ruby 是如何查找所有 gems 的过程感到好奇的,可以看这里,本文不作过多介绍。
覆写一个实例的的方法
在短短几十行代码中,还 monkey patch 了一个实例的方法,
def xxxobject.xxx_method
puts "replaced"
end
但如果想要在这个方法使用上下文中的变量是不行的,比如这样,
some_variable = 'a'
def xxxObject.xxx_method
puts some_variable # NameError - undefined local variable or method `some_variable' for #<XX::XXClass:0x00007f99112754c8>
end
道理也很简单,
some_variable
并不在 xxxObject
方法中的作用域内。这里通过把 some_variable
声明成了全局变量缓解了这个问题,但这并不是很好的解决方式,希望有更好解决方式的朋友提出见解。