这是一篇通过 CocoaPods 插件整合开发工具的记录文章,主要涉及到以下几部分内容:
1、Podfile 内声明公有源和私有源 source
2、Podfile 内提供 dev_pods
自定义方法用于提测过程中实时拉取组件分支最新 commit
3、解决 libwebp
科学上网问题:修改公有源里 podspec git 地址为 github 地址
4、解决 CocoaPods bug:一旦有任一组件在 podspec 里使用 resources
命令管理资源文件,CocoaPods 会把所有组件内的资源文件拷贝到 main bundle 里
只需在 Podfile 里添加这样一行,即可解决以上问题:
1 | plugin 'cocoapods-lebbay' |
而且整合了其他插件命令到 cocoapods-lebbay
工程内,方便用户安装和命令维护。接下来就来详细介绍下各部分的实现细节。
Podfile 内声明公有源和私有源 source
我们的组件化目前是采用了公有源和私有源双源的方案。为了 pod install 命令能够找到公有组件和私有组件,需要在 Podfile 里指定双源地址,如:
1 | # 私有源地址 |
但这样存在以下问题:
1、公司项目存在多个 APP,每个工程都要配置这样两行,各组件 Example 工程也存在这样的问题
2、公司 git 曾经换过几次地址,每次都要更换各个工程里的地址,且导致历史 tag 工程 pod install 失败
3、新电脑需要手动添加私有源才能工作
这次新建 cocoapods-lebby
插件工程,就通过 CocoaPods 提供的 source_provider
hook 时机添加 source 来统一管理源地址,源不存在时可自动添加。如下注册插件:
1 | Pod::HooksManager.register('cocoapods-lebbay', :source_provider) do |context| |
闭包参数 context
对象提供了 add_source
方法用于添加 source 对象,这里借鉴 CocoaPods 源码做法,给 Pod::Source::Manager
扩展了两个方法分别提供私有源和公有源:
1 | module Pod |
插曲:修复 CocoaPods bug #10764
通过 source_provider
hook 时机添加源地址后引发了 CocoaPods 的一个小 bug。目前 CocoaPods 已将默认的公有源从 master(git)换成了 trunk(CDN),并在 #9871 这个 PR 里加了个功能,即在 Podfile 里没有明确使用 master 源并且你的 repo list 里还有 master 的话,在执行 pod install 之后 CocoaPods 会打印一段警告文案提醒用户删除 master 源:
[!] Your project does not explicitly specify the CocoaPods master specs repo. Since CDN is now used as the default, you may safely remove it from your repos directory via pod repo remove master. To suppress this warning please add warn_for_unused_master_specs_repo => false to your Podfile.
当然 CocoaPods 也提供了方法来关掉这个警告:
1 | install! 'cocoapods', :warn_for_unused_master_specs_repo => false |
因为现在在国内 CDN 的地址几乎都被封了,pod install
经常失败,尤其是组件发版时的 lint 过程。所以我们还在用 master 源。如果使用 source_provider
hook 来添加源的话也应该是明确了在使用 master 源,并且不需要这段警告文案。查看 CocoaPods 源码(**installer.rb**)发现,只检查了 Podfile 里的 source 写法,漏掉了插件提供 source 的场景。加上对 plugin sources 的检查的逻辑如下:
1 | def warn_for_removing_git_master_specs_repo |
提交了 PR:**Check the podfile sources and plugin sources when printing warnings without explicitly using the master source. #10764** 应该会在 1.11.0 版本上线。
Podfile 内提供 dev_pods 自定义方法用于提测过程中实时拉取组件分支最新 commit
在组件开发过程中经常会修改几个 pod 的代码,需要一个个的将 pod 指向本地开发目录。在项目测试过程中又要将 pod 一个个指向提测分支,比如:
1 | # 开发阶段 |
为了简化写法,我们提供了 dev_pods
方法,简化逻辑后思路大致如下
1 | def dev_pods(pods, branch = '') |
在 ./bin/.development_path
文件里配置本地开发目录。dev_pods
方法的用法如下:
1 | # 开发阶段 |
在测试阶段还有一个问题是,我们希望在组件的提测分支上修改了 bug、提交 commit 之后主工程 pod install 即可拉取最新代码。但因为 Podfile.lock
文件的存在,pod install 之后会把 commit 节点记下来,除非我们在提交 pod 改动后,再去更新主工程的 Podfile.lock
文件,否则是不会拉取最新代码的。
为了实现这一需求,我们在 dev_pods
方法里修改了 Podfile.lock
文件,删掉 commit 节点信息,这样在拉取对应 pod 组件的时候就会拉取最新代码了。
在应用过程中发现的另一问题是:tag 冲突。当组件 PodA 指向的 release/1.0.0
分支里 podspec
里的版本号是 0.0.9
,那么主工程的 Podfile.lock
文件里记录的就是 0.0.9
。当测试完成,组件 podA 发版修改版本号为 1.0.0
并提交到了 release/1.0.0
分支里,这时主工程再执行 pod install 就会报 tag 冲突。
为解决这一问题,避免提测组件版本号变更影响主工程提测打包,我们的做法是如果 PodA 通过 dev_pods
方法指向了分支,那么在 dev_pods
里删掉 PodA 在 Podfile.lock
里的记录(只删除 version、branch、commit 信息即可),这样在 pod install 的时候就会像下载一个新的 pod 一样。
问题、需求及解决思路大致如上。以前的方案是写了个 ruby 文件(lebbay.rb
) 放在主工程目录,在 Podfile 里 require './bin/lebbay.rb'
。修改 Podfile.lock
文件也是脚本遍历文件内容操作字符串。现在统一整合到了 cocoapods-lebbay
插件里,为 Podfile 扩充了 DSL 方法,修改 Podfile.lock
文件可以直接使用 cocoapods-core
提供的 Lockfile 类及其方法:
1 | module Pod |
我们同时修改了 Pods/
文件夹下的 Manifest.lock
文件,是因为 CooaPods 在 pod install 过程中会对比 lock 文件里记录的 version 版本号。若 Manifest.lock
文件里记录的版本没变的话,在执行 pod install 时 Pods/
文件夹里对应 Pod 的代码很可能是不会更新的。
其中关于开发目录(development_path = Config.instance.dev_pods_path
),给 Pod::Config
扩展了两个方法:设置开发目录 & 读取开发目录:
1 | module Pod |
给 pod 扩展了两个方法入口分别执行这俩方法,读取开发目录(pod dev-pods-path cat
),设置开发目录(pod dev-pods-path set
):
1 | require 'cocoapods-lebbay/cache_config' |
解决 libwebp 科学上网问题:修改公有源里 podspec git 地址为 github 地址
这个问题是因为 libwebp 的 podspec 里 git 地址是:https://chromium.googlesource.com/webm/libwebp
,在 pod install 的时候大概率会因为网络原因而下载失败。将其改为:https://github.com/webmproject/libwebp.git
即可。
之前的做法是在 lebbay.rb
脚本里提供了 libwep_spec_fix
方法批量修改公有源里 libwebp.podspec
的 git 地址,然后在 Podfile 文件里调用下这个方法。
现在也整合到了 cocoapods-lebbay
插件里,在 pre_install
的 hook 时机里执行:
1 | Pod::HooksManager.register('cocoapods-lebbay', :pre_install) do |context| |
解决 CocoaPods bug:一旦有任一组件在 podspec 里使用 resources 命令管理资源文件,CocoaPods 会把所有组件内的资源文件拷贝到 main bundle 里
虽然我们目前没有 pod 在使用 resources
命令,但为了避免三方库会引入这个问题,我们还是做了规避,在 post_install
的 hook 时机里修复 CocoaPods 的脚本。之前是将 post_install
的 hook 写在了 Podfile 里,现在放在了插件里来做:
1 | Pod::HooksManager.register('cocoapods-lebbay', :post_install) do |context| |
后记
做完这些,各个工程里的 Podfile 文件就清爽了很多,之后再有需求的话也可以在 cocoapods-lebbay
插件里统一管理。
除了以上问题的整合,还把之前写的两个插件(组件自动化发版 pod deliver
命令和本地化文案词条管理 pod localize
命令)统一整合在了一起方便用户安装和命令维护。