枫林在线论坛精华区>>程序设计
[255621] 主题: 跟我一起写 Makefile(十四)
作者: redhat (RedHat)
标题: 跟我一起写 Makefile(十四)[转载]
来自: 192.168.*.*
发贴时间: 2004年07月24日 12:44:15
长度: 6614字

使用make更新函数库文件
———————————

函数库文件也就是对Object文件(程序编译的中间文件)的打包文件。在
Unix下,一般是由命令"ar"来完成打包工作。

一、函数库文件的成员

一个函数库文件由多个文件组成。你可以以如下格式指定函数库文件及其
组成:

    archive(member)

这个不是一个命令,而一个目标和依赖的定义。一般来说,这种用法基本
上就是为了"ar"命令来服务的。如:

    foolib(hack.o) : hack.o
            ar cr foolib hack.o

如果要指定多个member,那就以空格分开,如:

    foolib(hack.o kludge.o)

其等价于:

    foolib(hack.o) foolib(kludge.o)

你还可以使用Shell的文件通配符来定义,如:

    foolib(*.o)


二、函数库成员的隐含规则

当make搜索一个目标的隐含规则时,一个特殊的特性是,如果这个目标是
"a(m)"形式的,其会把目标变成"(m)"。于是,如果
我们的成员是"%.o"的模式定义,并且如果我们使用"mak
e foo.a(bar.o)"的形式调用Makefile时,隐含规则会去找"ba
r.o"的规则,如果没有定义bar.o的规则,那么内建隐含规则生效,
make会去找bar.c文件来生成bar.o,如果找得到的话,make执行的命令大
致如下:

    cc -c bar.c -o bar.o
    ar r foo.a bar.o
    rm -f bar.o

还有一个变量要注意的是"$%",这是专属函数库文件的自动化
变量,有关其说明请参见"自动化变量"一节。


三、函数库文件的后缀规则

你可以使用"后缀规则"和"隐含规则"来生成函数库
打包文件,如:

    .c.a:
            $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
            $(AR) r $@ $*.o
            $(RM) $*.o

其等效于:

    (%.o) : %.c
            $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
            $(AR) r $@ $*.o
            $(RM) $*.o


四、注意事项

在进行函数库打包文件生成时,请小心使用make的并行机制("-j&q
uot;参数)。如果多个ar命令在同一时间运行在同一个函数库打包文件上
,就很有可以损坏这个函数库文件。所以,在make未来的版本中,应该提
供一种机制来避免并行操作发生在函数打包文件上。

但就目前而言,你还是应该不要尽量不要使用"-j"参数。

 

后序
——

终于到写结束语的时候了,以上基本上就是GNU make的Makefile的所有细
节了。其它的产商的make基本上也就是这样的,无论什么样的make,都是
以文件的依赖性为基础的,其基本是都是遵循一个标准的。这篇文档中80
%的技术细节都适用于任何的make,我猜测"函数"那一章的内容
可能不是其它make所支持的,而隐含规则方面,我想不同的make会有不同
的实现,我没有精力来查看GNU的make和VC的nmake、BCB的make,或是别的
UNIX下的make有些什么样的差别,一是时间精力不够,二是因为我基本上
都是在Unix下使用make,以前在SCO Unix和IBM的AIX,现在在Linux、Sol
aris、HP-UX、AIX和Alpha下使用,Linux和Solaris下更多一点。不过,我
可以肯定的是,在Unix下的make,无论是哪种平台,几乎都使用了Richar
d Stallman开发的make和cc/gcc的编译器,而且,基本上都是GNU的make(
公司里所有的UNIX机器上都被装上了GNU的东西,所以,使用GNU的程序也
就多了一些)。GNU的东西还是很不错的,特别是使用得深了以后,越来越
觉得GNU的软件的强大,也越来越觉得GNU的在操作系统中(主要是Unix,
甚至Windows)"杀伤力"。

对于上述所有的make的细节,我们不但可以利用make这个工具来编译我们
的程序,还可以利用make来完成其它的工作,因为规则中的命令可以是任
何Shell之下的命令,所以,在Unix下,你不一定只是使用程序语言的编译
器,你还可以在Makefile中书写其它的命令,如:tar、awk、mail、sed、
cvs、compress、ls、rm、yacc、rpm、ftp……等等,等等,来完成诸如&
quot;程序打包"、"程序备份"、"制作程序安装包&
quot;、"提交代码"、"使用程序模板"、"合并
文件"等等五花八门的功能,文件操作,文件管理,编程开发设计,
或是其它一些异想天开的东西。比如,以前在书写银行交易程序时,由于
银行的交易程序基本一样,就见到有人书写了一些交易的通用程序模板,
在该模板中把一些网络通讯、数据库操作的、业务操作共性的东西写在一
个文件中,在这些文件中用些诸如"@@@N、###N"奇怪字串标注
一些位置,然后书写交易时,只需按照一种特定的规则书写特定的处理,
最后在make时,使用awk和sed,把模板中的"@@@N、###N"等字
串替代成特定的程序,形成C文件,然后再编译。这个动作很像数据库的&
quot;扩展C"语言(即在C语言中用"EXEC SQL"的样子执
行SQL语句,在用cc/gcc编译之前,需要使用"扩展C"的翻译程
序,如cpre,把其翻译成标准C)。如果你在使用make时有一些更为绝妙的
方法,请记得告诉我啊。

回头看看整篇文档,不觉记起几年前刚刚开始在Unix下做开发的时候,有
人问我会不会写Makefile时,我两眼发直,根本不知道在说什么。一开始
看到别人在vi中写完程序后输入"!make"时,还以为是vi的功能
,后来才知道有一个Makefile在作怪,于是上网查啊查,那时又不愿意看
英文,发现就根本没有中文的文档介绍Makefile,只得看别人写的Makefi
le,自己瞎碰瞎搞才积累了一点知识,但在很多地方完全是知其然不知所
以然。后来开始从事UNIX下产品软件的开发,看到一个400人年,近200万
行代码的大工程,发现要编译这样一个庞然大物,如果没有Makefile,那
会是多么恐怖的一样事啊。于是横下心来,狠命地读了一堆英文文档,才
觉得对其掌握了。但发现目前网上对Makefile介绍的文章还是少得那么的
可怜,所以想写这样一篇文章,共享给大家,希望能对各位有所帮助。

现在我终于写完了,看了看文件的创建时间,这篇技术文档也写了两个多
月了。发现,自己知道是一回事,要写下来,跟别人讲述又是另外一回事
,而且,现在越来越没有时间专研技术细节,所以在写作时,发现在阐述
一些细节问题时很难做到严谨和精练,而且对先讲什么后讲什么不是很清
楚,所以,还是参考了一些国外站点上的资料和题纲,以及一些技术书籍
的语言风格,才得以完成。整篇文档的提纲是基于GNU的Makefile技术手册
的提纲来书写的,并结合了自己的工作经验,以及自己的学习历程。因为
从来没有写过这么长,这么细的文档,所以一定会有很多地方存在表达问
题,语言歧义或是错误。因些,我迫切地得等待各位给我指证和建议,以
及任何的反馈。

最后,还是利用这个后序,介绍一下自己。我目前从事于所有Unix平台下
的软件研发,主要是做分布式计算/网格计算方面的系统产品软件,并且我
对于下一代的计算机革命——网格计算非常地感兴趣,对于分布式计算、
P2P、Web Service、J2EE技术方向也很感兴趣,同时,对于项目实施、团
队管理、项目管理也小有心得,希望同样和我战斗在“技术和管理并重”
的阵线上的年轻一代,能够和我多多地交流。我的MSN是:haoel@hotmail
.com(常用),QQ是:753640(不常用)。(注:请勿给我MSN的邮箱发信
,由于hotmail的垃圾邮件导致我拒收这个邮箱的所有来信)

我欢迎任何形式的交流,无论是讨论技术还是管理,或是其它海阔天空的
东西。除了政治和娱乐新闻我不关心,其它只要积极向上的东西我都欢迎


最最后,我还想介绍一下make程序的设计开发者。



首当其冲的是: Richard Stallman  

开源软件的领袖和先驱,从来没有领过一天工资,从来没有使用过Window
s操作系统。对于他的事迹和他的软件以及他的思想,我无需说过多的话,
相信大家对这个人并不比我陌生,这是他的主页:http://www.stallman.
org/ 。这里只贴上一张他的近照:


 计算机、音乐、蝴蝶就是他的最爱



第二位是:Roland McGrath  

个人主页是:http://www.frob.com/~roland/ ,下面是他的一些事迹:


1)  合作编写了并维护GNU make。

2)  和Thomas Bushnell一同编写了GNU Hurd。

3)  编写并维护着GNU C library。 

4)  合作编写并维护着部分的GNU Emacs。 

 

在此,向这两位开源项目的斗士致以最真切的敬意。


(全文完)


========== * * * * * ==========
返回