本文所述环境的搭建是基于Ubuntu 12.04 64bit,android版本是4.1(其他版本估计也一样)。android编译环境的搭建就不再赘述了,请参考尽量参考官方文档https://source.android.com/source/initializing.html
Distcc 是一个将 C、C++等程序的编译任务分发到网络中多个主机的程序。 Distcc的工作原理为: GCC 编译C/C++构建一个execualble分为四个阶段: 预处理:.c 到.i,由cc完成 汇编:.i到.s ,由cc完成 编译:.s到.o,由as完成 链接:.o 到可执行文件,由collect2完成 其中第三阶段是效率瓶颈。distcc是一个编译器驱动器。它在”gcc -c”阶段把预处理输出分发到指定的服务器阵列并收集结果。GNU Make的”-j”并行编译可以利用distcc来加速编译。distcc本身事实上并不参与任何编译过程,而只是一个编译器的前端。为编译器加入分布式特性,并参与部分管理和简单的负载均衡的功能。distcc在本地完成预处理(使用gcc -E,完成头文件、宏的展开),把结果发给集群中的工作主机,由工作主机完成编译(使用gcc -c)并发回编译结果,最后在本地做链接。 distcc分布式编译程序可以将包含两个部分: distcc:在客户端分发编译任务到编译主机 distccd:编译主机启动distccd守护进程接收编译任务,并返回编译结果。
如果不想走弯路,请不要
sudo apt-get install distcc
也不要在https://code.google.com/p/distcc/downloads/list这里下载安装包。
我通过这两种方式安装后都会在编译主机上产生编译错误,结果几乎所有任务都在本地编译了。这样就没意义了。
我推荐的方法是:
svn checkout http://distcc.googlecode.com/svn/trunk/ distcc-read-only
代码checkout下来自己编译。拿到代码后,要仔细阅读INSTALL文件,里面很详细,胜过任何网上的其他介绍distcc环境搭建的文章,当然android涉及交叉编译,会有所不同。
为了顺利编译处安装包,按照INSTALL文档所述,安装以下依赖:
sudo apt-get install gcc make python python-dev binutils-dev alien libavahi-client-dev
为了编译出deb安装包,要安装alien。
Ubuntu 12.04是支持zeroconf的,可以ps查看下,是有avahi-daemon在运行的,但是为了编译出支持zeroconf的安装包,需要安装libavahi-client-dev依赖。zeroconf是什么东西我就不赘述了。万事具备只差make了,执行以下:
./autogen.sh ./configure --with-avahi sudo make deb
with-avahi参数表明build出的包支持zeroconf。如果一切顺利,你将在源码的packaging目录下得到build出来的安装包
distcc_3.2rc1-1_amd64 distcc-server_3.2rc1-1_amd64
安装他们:
dpkg -i distcc_3.2rc1-1_amd64 distcc-server_3.2rc1-1_amd64
注意:
为了实现zeroconf,我最初在虚拟机和本机上做实验,按照下文继续配置好后,可以找到主机。相同的环境在另一台电脑上搭建,zeroconf却找不到那台电脑。我使用avahi-discover查看Distributed Compiler下的所有主机,确实是可以看到的。这就说明zeroconf的实现程序avahi是可以找到这个主机的,distcc利用avahi寻找主机,理论上也应该可以找到的。继续追踪/var/log/syslog
文件,看到类似下面这一行
(daemon_proc) Browsing for 'x86_64-unknown-linux-gnu_4.4.3_distcc._tcp'.
也就是说,distcc通过avahi寻找主机的时候,要求主机和gcc的版本都要一致,但是实际上gcc小版本不一致并不会影响编译结果。果断改代码,zeroconf.c文件中:
...... # if (dcc_get_gcc_version(version, sizeof(version)) && # dcc_get_gcc_machine(machine, sizeof(machine))) { # # dcc_make_dnssd_subtype(stype, sizeof(stype), version, machine); # } else { rs_log_warning("Warning, failed to get CC version and machine type.\n"); strncpy(stype, DCC_DNS_SERVICE_TYPE, sizeof(stype)); stype[sizeof(stype)-1] = 0; # } ......
这样distcc找主机时,参数就是"_distcc._tcp"了。这样修改至少在我这边是OK的
涉及到的配置文件主要在"/etc/distcc/"文件夹下
client.allow中内容为
#表明192.168.*的IP都能发给自己编译任务 192.168.0.0/16
拷贝android源码包prebuilts下的编译工具到指定目录:/usr/local/distcc/prebuilts/
修改commands.allow.sh的内容为:
numwords=1 allowed_compilers=" /usr/bin/cc /usr/bin/c++ /usr/bin/c89 /usr/bin/c99 /usr/bin/gcc /usr/bin/g++ /usr/bin/*gcc-* /usr/bin/*g++-* /usr/local/distcc/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin/arm-linux-androideabi* /usr/local/distcc/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6/bin/i686-linux* " ......
注意保证新添加的那两行的内容真是存在,否则服务端会发生编译错误。
在"/etc/distcc/"文件夹下
hosts文件的内容为:
localhost +zeroconf
貌似zeroconf能找到的IP只能匹配一个网段,所以可以自己在文件中继续添加其他IP地址。
在"/etc/init.d/"文件夹下
distcc文件的内容为:
...... OPTIONS="--zeroconf --log-file=/var/log/distccd.log --daemon --stats --job-lifetime=1200" USER=distcc PROG="distccd" PIDFILE=/var/run/$PROG.pid EXEC="/usr/bin/distccd" ......
"--zeroconf --log-file=/var/log/distccd.log"参数是为了支持zeroconf和log。
最后重新重启distccd
sudo /etc/init.d/distcc reload
以上步骤完成后就基本完成了服务端的配置(客户端也要进行那些配置),客户端要想启动distcc编译,还需要继续以下步骤:
以下只是叙述了android要成功启动distcc编译任务所以要的必备条件,很多改动并不优雅。
首先确保编译前
export PATH=/usr/bin/distcc:$PATH
不建议写到环境变量中
在"build/core/combo"文件夹下
TARGET_linux-arm.mk文件:
...... ifeq ($(strip $(TARGET_TOOLS_PREFIX)),) TARGET_TOOLCHAIN_ROOT := /usr/local/distcc/prebuilts/gcc/$(HOST_PREBUILT_TAG)/arm/arm-linux-androideabi-4.6 TARGET_TOOLS_PREFIX := $(TARGET_TOOLCHAIN_ROOT)/bin/arm-linux-androideabi- endif ......
select.mk文件:
...... include $(BUILD_COMBOS)/$(combo_target)$(combo_os_arch).mk $(combo_target)CC := distcc $($(combo_target)CC) $(combo_target)CXX := distcc $($(combo_target)CXX) ......
最后启动编译
. ./build/envsetup.sh lunch make -jN
即可
5.监视distcc编译任务
distcc自带distccmon-text,可以启动文本化监视
#3秒刷新一次 distccmon-text 3
也可以使用distccmon-gnome启动图形化监视程序
sudo apt-get install distccmon-gnome distccmon-gnome &
即可