深入学习Make命令和Makefile(上)(3)



五、makefile中的规则

除了指明目标和模块之间的依赖关系之外,makefile还要规定相应的规则来描述如何生成目标,或者说使用哪些命令来根据依赖模块产生目标。就上例而言,当make程序发现需要重新构建f1.o的时候,该使用哪些命令来完成呢?很遗憾,到目前为止,虽然make知道哪些文件需要更新,但是却不知道如何进行更新,因为我们还没有告诉它相应的命令。

当然,我们可以使用命令gcc -c f1.c来完成,不过如果我们需要规定一个include目录,或者为将来的调试准备符号信息的话,该怎么办呢?所有这些,都需要在makefile中用相应规则显式地指出。

实际上,makefile是以相关行为基本单位的,相关行用来描述目标、模块及规则(即命令行)三者之间的关系。一个相关行格式通常为:冒号左边是目标(模块)名;冒号右边是目标所依赖的模块名;紧跟着的规则(即命令行)是由依赖模块产生目标所使用的命令。相关行的格式为:

目标:[依赖模块][;命令]

习惯上写成多行形式,如下所示:

目标:[依赖模块]

命令

命令

需要注意的是,如果相关行写成一行,“命令”之前用分号“;”隔开,如果分成多行书写的话,后续的行务必以tab字符为先导。对于makefile而言,空格字符和tab字符是不同的。所有规则所在的行必须以tab键开头,而不是空格键。初学者一定对此保持警惕,因为这是新手最容易疏忽的地方,因为几个空格键跟一个tab键在肉眼是看不出区别的,但make命令却能明察秋毫。

此外,如果在makefile文件中的行尾加上空格键的话,也会导致make命令运行失败。所以,大家一定要小心了,免得耽误许多时间。

六、Makefile文件举例

根据图1的依赖关系,这里给出了一个完整的makefile文件,这个例子很简单,由四个相关行组成,我们将其命名为mymakefile1。文件内容如下所示:

main: main.o f1.o f2.o
gcc -o main main.o f1.o f2.o
main.o: main.c def1.h
gcc -c main.c
f1.o: f1.c def1.h def2.h
gcc -c f1.c
f2.o: f2.c def2.h def3.h
gcc -c f2.c

注意,由于我们这里没有使用缺省名makefile 或者Makefile ,所以一定要在make命令行中加上-f选项。如果在没有任何源码的目录下执行命令“make -f Mymakefile1”的话,将收到下面的消息:

make: *** No rule to make target ‘main.c’, needed by ‘main.o’. Stop.

Make命令将makefile中的第一个目标即main作为要构建的文件,所以它会寻找构建该文件所需要的其他模块,并判断出必须使用一个称为main.c的文件。因为迄今尚未建立该文件,而makefile又不知道如何建立它,所以只好报告错误。好了,现在建立这个源文件,为简单起见,我们让头文件为空,创建头文件的具体命令如下:

$ touch def1.h
$ touch def2.h
$ touch def3.h

我们将main函数放在main.c文件中,让它调用function2和function3,但将这两个函数的定义放在另外两个源文件中。由于这些源文件含有#include命令,所以它们肯定依赖于所包含的头文件。如下所示:

/* main.c */
#include
#include “def1.h”
extern void function2();
extern void function3();
int main()
{
function2();
function3();
exit (EXIT_SUCCESS);
}
/* f1.c */
#include “def1.h”
#include “def2.h”
void function2() {
}
/* f2.c */
#include “def2.h”
#include “def3.h”
void function3()

建好源代码后,再次运行make程序,看看情况如何:

$ make -f Mymakefile1
gcc -c main.c
gcc -c f1.c
gcc -c f2.c
gcc -o main main.o f1.o f2.o
$

好了,这次顺利通过了。这说明Make命令已经正确处理了makefile描述的依赖关系,并确定出了需要建立哪些文件,以及它们的建立顺序。虽然我们在makefile 中首先列出的是如何建立main,但是make还是能够正确的判断出这些文件的处理顺序,并按相应的顺序调用规则部分规定的相应命令来创建这些文件。当这些命令执行时,make程序会按照执行情况来显示这些命令。

如今,我们对def2.h加以变动,来看看makefile能否对此作出相应的回应:

$ touch def2.h

$ make -f Mymakefile1
gcc -c f1.c
gcc -c f2.c
gcc -o main main.o f1.o f2.o
$

这说明,当Make命令读取makefile 后,只对受def2.h的变化的影响的模块进行了必要的更新,注意它的更新顺序,它先编译了C程序,最后连接生产了可执行文件。现在,让我们来看看删除目标文件后会发生什么情况,先执行删除,命令如下:

$ rm f1.o

然后运行make命令,如下所示:

$ make -f Mymakefile1
gcc -c f1.c
gcc -o main main.o f1.o f2.o
$

很好,make的行为让我们非常满意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值