调试Podfile

Cocoapods 是如何解析 Podfile 的

简单来说,Podfile 文件里所写的就是一段 ruby 代码, 这段代码是通过大多脚本语言都有的 eval 方法来执行的。

1
2
3
# ruby
x = eval '1 + 2 + 3'
puts x # 6
1
2
3
# python
x = eval('2 + 2 + 3')
print x # 7
1
2
3
// JavaScript
let x = eval('1 * 2 * 3')
console.log(x) // 6

具体可以看这篇文章手动解析 Podfile部分

调试 Podfile

既然 Podfile 中的代码在 pod install 过程中被调用,那么肯定可以进行调试。

  1. 安装用于调试的 debugger : gem install pry

    如果你是通过 bundle 来管理工程用到的 gems 的,那么你需要将 gem 'pry' 添加到你的 Gemfile 文件中,并执行 bundle install --verbose

  2. Podfile 的开头引入 debugger : require 'pry'
  3. 在想要插入断点的地方添加调试:binding.pry

Podfile 文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
require 'pry'

platform :ios, '11.0'

target 'poddebug' do
use_frameworks!
pod 'Moya'

end

post_install do |installer|
binding.pry
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf'
config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES'
end
end
end

执行 pod install后,就断点在 binding.pry 所在的那一行

binding_pry.png

实战操作

如上面 Podfile 中所写的那样, 要对 pod proejct 中的每个 target 的每个 configurationsbuild settings 进行修改。

那这段代码是怎么来的呢,当然你可以通过查看 xcodeproj 的文档写出这段代码,但有些情况下文档中缺少了一些东西,并没有对一些东西进行说明。那么此时就可以通过调试 Podfile 写出写段代码。

我是谁,我在哪

首先断点在了 binding.pry,所以这意味着什么,此时此刻我是谁我在哪,我该做什么。为了解决这个问题,我需要看一下我周围都有什么东西,也就是当前调用栈中都有哪些东西。

使用 ls 命令可以得到当前上下文可用的 方法实例变量常量本地变量实例方法类变量 等等。

ls.png

要进行上述修改,我需要在 pod install 完成后再进行修改,以免我的修改被意外地覆盖。所以上面的 Pod::Podfile::DSL#methods:post_install 方法应该是符合我们需求的。所以在 Podfile 中调用试试看

你是谁

installer.png
图中的 installerpost_install 的回调闭包的参数,同样的使用 ls 命令来看一下这个 installer 具体是个什么东西

ls_installer

  1. 使用 ls 查看当前上下文, 得到 installer 变量
  2. 使用 ls 查看这个 installer,得到 installer 变量可用的方法和实例变量
  3. 通过 2 知道 installer 有名为 pods_projectpod_targets的方法和实例变量,那么两个实例变量里存放的是什么呢?

pods_project

pod_targets

install_pod_targets.png

从上面两个图可以猜测 installer.pods_project.targetsinstaller.pod_targets 应该是同一个东西.

分别进行打印
compare.png

额,结果跟猜测的不一样。那应该用哪个呢?接着往下看,现在拿到了 targets, 下一步要拿到 targetconfiguration, 既然拿到了 targets 数组,我们只取其第一个元素来进行探测

pod_targets_build_config.png
pods_project_build_config.png

从上面两张图可以看出 pod_targets 数组中元素没有符合 build configuration 相关的实例变量或方法,而 pods_project.targets数组的元素则可以找到与build configuration高度符合的方法。

下面就只关注 pods_project 这条线了。调用改方法看其返回值是否符合预期

build_config.png

完美!拿到了工程的两个 configuration: ReleaseDebug
如果再能拿到下面的 build settings就大功告成了,还是使用 ls 来进行探测一番

build_settings.png

大功告成!成功拿到了 build settings。下面就可以根据 ruby 的语法写出上面 Podfile 中的那段代码了。

1
2
3
4
5
6
7
8
9
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf'
config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES'
end
end
end

嵌套了两个 each, 改写一下:

1
2
3
4
5
6
7
8
post_install do |installer|
installer.pods_project.targets
.flat_map { |t| t.build_configurations }.each do |config|
config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf'
config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES'
end
end