这几天研究了下在 Xcode 上使用 distcc 进行分布式编译,无疾而终,在此记录下过程中遇到的一些主要问题,以备后续研究。
distcc
distcc 是一个开源的分布式编译工具,它可以将 C 语言的编译任务分发到多台机器上进行编译,最终再发回主机进行链接,以此加快编译速度。
使用 PSPDF 的方案,本地编译成功,远程编译失败
最初 distcc 的分布式编译方案就是在 PSPDF 的 Blog 上看到的,之前配置 CCache 的时候也参考过他们的 Blog。原文地址在此:Crazy Fast Builds Using Distcc
文中提到,目前 distcc 原生不支持 Xcode + clang,因为 Xcode 调用 clang 编译时,使用了许多特殊的选项,distcc 缺少了对这些选项的支持。因此,PSPDF 团队提供了一份打了补丁的 distcc。下面我快速总结下他们的方案,详细的讲解请看原文。
配置步骤
- 在配置好 CCache 的情况下(不是必要条件,只是为了方便配置)
- 先使用 brew 安装原生 distcc:命令行中
brew install distcc
- 拉下 PSPDF 打补丁后的源代码:PSPDF distcc
- 编译源码:
1 | ./autogen.sh |
- 在
/usr/local/Cellar/distcc/
目录下,找到刚刚用 brew 安装的 distcc 的所有二进制文件,用刚刚编译出来的几个二进制文件替换; - 在
~/.distcc/
目录下创建hosts
文件,写入远程的编译机器的地址,如172.16.0.1
; - 让 Xcode 调用 distcc:在配置了 CCache 的工程目录下,把
ccache-clang
脚本中原有的命令都注释掉,换成exec distcc clang "$@"
;(这是一个偷懒办法,使用包含 CCache 的工程就是为了利用ccache-clang
脚本拦截clang
的调用。此外,还可以在这行命令前,加上export DISTCC_VERBOSE=0
来输出distcc
的日志) - 本地配置好后,给远端的编译服务器也按上述步骤
启动
- 在编译的机器上跑起 distcc 的后台编译线程:
1 | distccd --no-detach --daemon --allow 172.16.0.0/16 --allow 127.0.0.1 --log-stderr --verbose |
- 在本机
brew install watch
,然后新开一个终端窗口执行watch distccmon-text
,用来监控本机任务分发的情况; - Xcode 开始编译;
遇到的问题
- 如果只把
localhost
作为编译服务器,则编译没问题,输出 COMPILE_OK; - 如果不在本地编译,把任务分发到远端的编译服务器,则远端全部编译失败
COMPILE_ERROR exit code 1
,然后 distcc 回滚到本地编译;
使用 distcc with pump mode
看到网上有一个类似的错误,声称开启 pump mode
后可以解决上述问题,于是尝试 distcc with pump mode
。
pump mode
是指不仅将编译任务分发到远端,而且还将预处理的任务分发到远端,这使得传输的数据量变得非常大,但是当远端服务器数量够多,且带宽超过100M 的情况下,它可能会极大提升编译速度。
开启方法
- 在之前提到的
hosts
文件中的所有 IP 后面都加上,lzo,cpp
,如172.16.0.1,lzo,cpp
; - 在
ccache-clang
的那句脚本上,加上pump
,变成exec pump distcc clang "$@"
;
遇到的问题
- 直接编译,发现报错,缺少某些
.so .sh .py
文件,尝试将本地编译生成的一些对应的文件拷贝到/usr/local/Cellar/distcc/
目录下,最终不再报类似错误; - 解决上述编译错误的问题后,Xcode 显示编译成功,但远端的控制台发现编译失败。检查后发现,似乎是本地分析代码依赖的时候,发生了错误,导致无法分发预处理的任务,在本地完成了预处理,而本地预处理后,分发编译任务给远端时,就又出现了最初的本地编译成功,远端而编译失败的情况。错误信息如下:
1 | __________Using distcc-pump from /usr/local/Cellar/distcc/3.2rc1/bin |
总结
分布式编译十分美好,在 Xcode 上理论上是可行的,Xcode 4 之前甚至内嵌了 distcc。但是目前 distcc 目前原生不支持 Xcode,且其社区不是很活跃,特别是 Xcode 上的应用成功的案例更是少之又少,几乎为零,提及它的内容大多是几年前发布的。以此初步判断,目前除非投入较多精力寻找变通手段,进行适配,否则较难实现分布式编译。欢迎成功实践了 distcc 或其他分布式编译方式的朋友和我