标签 GNU 下的文章

分布式编译让你的工作更高效

随着工程代码量的增加,往往完整的编译一次Proj消耗的时间可能足够你喝两杯咖啡了,我现在build一次我所在proj的代码需要5分多钟,这是很痛苦的,颇让人懊恼的。为了解决这个工作中的别扭事儿,我在网上搜寻了一番,找到了distcc这个分布式编译工具。

先看看distcc能帮助我节省多少时间吧。我在公司的一台Sun SPARC Solaris9主机下对整个项目源代码按照以前的编译方式进行了一次build,这次build用了5分多钟;同样我使用distcc编译(安装了两个节点,都是Sun SPARC Solaris9主机),居然只用了1分多钟,试想如何有更多的服务器作为distcc的守候进程主机节点的话,势必编译性能还会有提升。

有了"惊人"结果后,我们来看看distcc的原理,distcc本身是gcc的一个wrapper,也可用作本地编译,但是更多的是其分布式编译的强大功能,简单来说:就是将gcc的编译任务分布到各个其他主机上去,然后再传回来整合。它提高的是gcc -c阶段的速度,链接阶段的速度由于肯定要在本地实施,所以distcc无能为力。另外distcc推荐分布的不同主机上安装的编译器版本最好要一致,否则可能会有意想不到的错误。

distcc的安装和使用方法甚是简单,我安装的是distcc-2.13-sol9-sparc-local,直接在root下pkgadd即可。然后在各个distcc节点启动后台守候进程:distccd –daemon –allow x.x.x.x/16,以普通用户启动即可。

客户端使用方法:
1、在自己的用户下,添加环境变量(如果你用的是C shell):setenv DISTCC_HOSTS 'localhost x.x.x.x',代表本机和x.x.x.x上安装并启动了distccd
2、将你的makefile 中的CC=gcc改为CC=distcc gcc
3、make即可 。同样你还可以在make的-j参数选项,如make -j 12,这样在单机上进行多任务并行编译,使速度更快。
4、如果你想观察各节点上distcc的工作状态,可使用distccmon-text 2 命令查看distcc在各台主机上的任务快照。参数2代表:每隔2秒刷新一次。

Distcc理论上是可以部署在不同平台上辅助进行分布式编译的,但是在异构平台上分布需要一段时间设置和调试,我推荐还是尽量部署在同一类型平台上吧。有了distcc,我们的服务器的计算能力得到了充分的发挥,个人工作效率也会有所提高的,不知道长此下去喝咖啡的机会会不会被剥夺了:)

成功Build ACE

近期公司实行新的绩效考核机制,我的考核目标中就有一项叫做:"成功使用新技术、框架、思路等至少3个",呵呵,先不论绩效考核机制是否合理,既然已经这样了那就需要去适应。一直在做Network Application,早就知道ACE在业界中的名气,这回有理由找个时间好好挖掘一下ACE的思路,也为我的绩效目标增色啊^_^。

以上只是开个玩笑罢了。上周末去书店看到电子工业出版社再次出版的'C++网络编程卷一',这套书的卷1以及卷2的英文电子版我早已有了,但是还是喜欢抱着纸板书看书的那种感觉,所以就顺便买了下来。翻看了一下,发现里面的内容恰恰是现在我所需要的,如果是前两年看这本书,理解起来肯定不会很透彻,因为那时的心中缺少的是恰恰是问题和困惑,没有了那些东西看书的效果也就大打折扣;反之如果作者的思路恰恰是把你扶上的正确的思维轨道,以帮助你解决了心中的那个结,你的收获就会是大大的。

记得前年的时候曾经下载过ACE并且尝试从源代码Build,结果是失败了,原因现在已经记不清了;这次重新下载ACE-5.5版本在Solaris 9上用G++ 3.2编译,居然顺利通过,其功劳应该归功于ACE的开发者之一Stephen D. Huston的'The ACE Programmers Guide'一书,而且从ACE自带文档中得知,ACE最先就是在Solaris上开发的。

Build过程:
1. 下载ACE的源码包;解包解压,一般你会在当前目录下获得一个名为'ACE_wrappers'的目录;
2. 设置ACE_ROOT环境变量;如我用的是csh,我就会在用户的HOME路径下的.cshrc中增加一个环境变量ACE_ROOT,比如:setenv ACE_ROOT '/export/home1/baim/ACE_wrappers';
3. 切换路径到$ACE_ROOT/ace/下,创建config.h,在这个头文件中,我们需要做一件事,就是include一个你所在的编译平台的头文件,比如我是在Sun Solaris 9上编译的,我的config.h中的内容就是这样的:
//config.h
#include "config-sunos5.9.h"

不同的平台,包含的头文件不同,这些头文件也都在$ACE_ROOT/ace/下,你可以用'ls -l|grep config'来看看究竟有哪些config头文件,选择你所在平台对应的即可。

4. 切换到$ACE_ROOT/include/makeinclude下,创建一个叫'platform_macros.GNU'的文件,同样这里也有平台相关的一堆.GNU文件,我们只需在我们新建的platform_macros.GNU文件中包含对应文件即可。
如我用g++在Solaris 9上编译,我就该选择:platform_sunos5_g++.GNU
//platform_macros.GNU
include $(ACE_ROOT)/include/makeinclude/platform_sunos5_g++.GNU

这个文件里还可以放置make的编译选项,比如我要生成.a文件,我可以这么做:
//platform_macros.GNU
static_libs=1
include $(ACE_ROOT)/include/makeinclude/platform_sunos5_g++.GNU

5. 切换到$ACE_ROOT/ace/下,输入make命令执行即可。编译的过程是漫长的,大约1个小时,之后你就会发现在$ACE_ROOT/ace/下有libACE.so -> libACE.so.5.5.0*、libACE.so.5.5.0*和libACE.a出现了。

构建过程到此结束。

ACE的makefile没有.phony install,所以在你的ACE应用程序里可直接引用$(ACE_ROOT)/ace下面的头文件,直接链接$(ACE_ROOT)/ace下面的libACE.a库即可。

//HelloACE.cpp
#include "ace/Log_Msg.h"

void foo (void);

int ACE_TMAIN (int, ACE_TCHAR *[])
{
  ACE_TRACE(ACE_TEXT ("main"));

  ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHi Mom\n")));
  foo();
  ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n")));

  return 0;
}

void foo (void)
{
  ACE_TRACE (ACE_TEXT ("foo"));

  ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHowdy Pardner\n")));
}

//编译
g++ -o HelloACE HelloACE.cpp -I$ACE_ROOT -I./ -L$ACE_ROOT/ace -lACE  -lsocket -ldl -lgen -lnsl -lposix4 -lthread

这里有几点注意事项:
1、如果libACE.so.5.5.0*和libACE.a都同时在$ACE_ROOT/ace下的话,上面的编译命令默认优先进行动态链接。也就是说编译出来的可执行程序HelloACE在运行的时候如果找不到libACE.so.5.5.0就会报错。
2、如果想进行静态链接的话,可以将$ACE_ROOT/ace下的libACE.so.5.5.0删除或者改名,这样在执行上面的编译命令后即是静态链接。
3、注意g++链接.a和.o时是有顺序的,g++从左到右读入目标文件或.a文件中的符号,如果靠右边的目标文件或者.a文件中没有靠左面的目标文件或者.a文件中的未定义的符号定义的话(或者白话一点说:右边没有左边想要的),程序就会报错。比如我们把上述的编译命令改一下,改为:
g++ -o HelloACE -I$ACE_ROOT -I./ -L$ACE_ROOT/ace -lACE  -lsocket -ldl -lgen -lnsl -lposix4 -lthread HelloACE.cpp
执行命令后,会出现下面错误提示:

未定义                  文件中的
 符号                       在文件中
ACE_Log_Msg::log(ACE_Log_Priority, char const*, …)/var/tmp//ccBl9Q0L.o
ACE_Log_Msg::last_error_adapter()      /var/tmp//ccBl9Q0L.o
ACE_Log_Msg::conditional_set(char const*, int, int, int)/var/tmp//ccBl9Q0L.o
ACE_Log_Msg::instance()             /var/tmp//ccBl9Q0L.o
ld: 致命的: 符号参照错误. 没有输出被写入HelloACE
collect2: ld returned 1 exit status

实际上上面的命令g++ -o HelloACE -I$ACE_ROOT -I./ -L$ACE_ROOT/ace -lACE  -lsocket -ldl -lgen -lnsl -lposix4 -lthread HelloACE.cpp等价于下面两个命令:

g++ -c -I$ACE_ROOT -I./ HelloACE.cpp
g++ -o HelloACE -L$ACE_ROOT/ace -lACE  -lsocket -ldl -lgen -lnsl -lposix4 -lthread HelloACE.o

其实上面错误提示中的"/var/tmp//ccBl9Q0L.o",其实就是一个匿名的HelloACE.o

另外在'The ACE Programmers Guide'一书中,作者给了个Makefile,如下:
BIN   = HelloACE
BUILD = $(VBIN)
SRC = $(addsuffix .cpp,$(BIN))
LIBS =
LDFLAGS = -L$(PROJ_ROOT)/lib
#—————————————————
#Include macros and targets
#—————————————————
include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU
include $(ACE_ROOT)/include/makeinclude/macros.GNU
include $(ACE_ROOT)/include/makeinclude/rules.common.GNU
include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU
include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU
include $(ACE_ROOT)/include/makeinclude/rules.local.GNU

直接用该Makefile会让你的build更简洁,另外还有支持多个.cpp文件的Makefile在那本书里,大家可以参考。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats