GNU make 学习笔记(三)

  今天又看了一遍“连接库的搜寻目录”,发现有点明白了。就是说库文件的实际名字都是以lib+name的形式出现,在makefile文件中,使用-|name代替lib+name,进行搜索。是这个意思吧?
假想目标
使用假想目标有两个原因:避免和具有相同名称的文件冲突和改善性能。
当要使用假象目标时,最好明确指出,以避免不必要的麻烦。使用.PHONY目标格式将该目标具体的声明为一个假想目标:
.PHONY : clean
一旦这样声明,‘make clean’命令无论目录下是否存在名为‘clean’的文件,该目标的命令都会执行。
假象目标的使用是很灵活的,可以看到下面3个典型示例 :
一、
一个使用假想目标的例子是使用make的递归调用进行连接的情况:此时,makefile文件常常包含列举一系列需要创建的子目录的变量。不用假想目标完成这种任务的方法是使用一条规则,其命令是一个在各个子目录下循环的shell命令,如下面的例子:
subdirs:
        for dir in $(SUBDIRS); do /
          $(MAKE) -C $$dir; /
        done
但使用这个方法存在下述问题:首先,这个规则在创建子目录时产生的任何错误都不及时发现,因此,当一个子目录创建失败时,该规则仍然会继续创建剩余的子目录。虽然该问题可以添加监视错误产生并退出的shell命令来解决,但非常不幸的是如果make使用了‘-k’选项,这个问题仍然会产生。第二,也许更重要的是您使用了该方法就失去使用make并行处理的特点能力。
使用假想目标(如果一些子目录已经存在,您则必须这样做,否则,不存在的子目录将不会创建)则可以避免上述问题:
SUBDIRS = foo bar baz
 
.PHONY: subdirs $(SUBDIRS)
 
subdirs: $(SUBDIRS)
 
$(SUBDIRS):
        $(MAKE) -C $
 
foo: baz
此时,如果子目录‘baz’没有创建完成,子目录’foo’将不会创建;当试图使用并行创建时这种关系的声明尤其重要。
二、
 假想目标也可以有依赖。当一个目录下包含多个程序时,使用假想目标可以方便的在一个makefile文件中描述多个程序的更新。重建的最终目标缺省情况下是makefile文件的第一个规则的目标,但将多个程序作为假想目标的依赖则可以轻松的完成在一个makefile文件中描述多个程序的更新。如下例:
all : prog1 prog2 prog3
.PHONY : all
 
prog1 : prog1.o utils.o
        cc -o prog1 prog1.o utils.o
 
prog2 : prog2.o
        cc -o prog2 prog2.o
 
prog3 : prog3.o sort.o utils.o
        cc -o prog3 prog3.o sort.o utils.o
这样,您可以重建所有程序,也可以参数的形式重建其中的一个或多个(如‘make prog1 prog3')。
三、
 当一个假想目标是另一个假想目标的依赖,则该假想目标将作为一个假想目标的子例程。例如,这里‘make cleanall'用来删除OBJ文件、diff文件和程序文件:
.PHONY: cleanall cleanobj cleandiff
 
cleanall : cleanobj cleandiff
        rm program
 
cleanobj :
        rm *.o
 
cleandiff :
        rm *.diff
本人认为:通过这3个例子,可以归纳为假象目标可以实现make的递归调用,使用假象目标可以对实际目标文件进行批量处理,并且假象目标可以嵌套使用。

没有命令或依赖的规则
例子:
clean: FORCE
        rm $(objects)
FORCE:
在这个例子里,FORCE没有依赖。对于这种规则,只要make执行,就会强制执行clean。关于‘FORCR’的名字没有特别的要求,但‘FORCR’是习惯使用的名字。使用‘FORCR’的方法和使用假想目标(.PHONY: clean)的结果一样,但使用假想目标更具体更灵活有效。

使用空目标文件记录事件
所谓的空目标,实际上就是目标文件没有什么实际内容,只是用来控制一些命令的执行。它之所以能够这样执行是因为规则的命令中有一条用于更新目标文件的‘touch’命令。另外,空目标文件应有一些依赖(否则空目标文件没有存在的意义)。
print: foo.c bar.c
        lpr -p $?
        touch print
按照这个规则,如果任何一个源文件从上次执行‘make print'以来发生变化,键入‘make print'则执行lpr命令。自动变量‘$?’用来打印那些发生变化的文件。

内建的特殊目标名
.PHONY
特殊目标.PHONY的依赖是假想目标。假想目标是这样一些目标,make无条件的执行它命令,和目录下是否存在该文件以及它最后一次更新的时间没有关系。
.SUFFIXES
特殊目标.SUFFIXES的依赖是一列用于后缀规则检查的后缀。
.DEFAULT
.DEFAULT指定一些命令,这些命令用于那些没有找到规则(具体规则或隐含规则)更新的目标。如果.DEFAULT指定了一些命令,则所有提及到的文件只能作为依赖,而不能作为任何规则的目标;这些指定的命令也只按照他们自己的方式执行。
.PRECIOUS
特殊目标.PRECIOUS的依赖将按照下面给定的特殊方式进行处理:如果在执行这些目标的命令的过程中,make被关闭或中断,这些目标不能被删除;如果目标是中间文件,即使它已经没有任何用途也不能被删除,具体情况和该目标正常完成一样;该目标的其它功能和特殊目标.SECONDARY的功能重叠。如果规则的目标格式与依赖的文件名匹配,您可以使用隐含规则的格式(如‘%.O’)列举目标作为特殊目标.PRECIOUS的依赖文件来保存由这些规则创建的中间文件。
.INTERMEDIATE
特殊目标.INTERMEDIATE的依赖被处理为中间文件。.INTERMEDIATE如果没有依赖文件,它将不会发生作用。
.SECONDARY
特殊目标.SECONDARY的依赖被处理为中间文件,但它们永远不能自动删除。.SECONDARY如果没有依赖文件,则所有的makefile文件中的目标都将被处理为中间文件。
.DELETE_ON_ERROR
如果在makefile文件的某处.DELETE_ON_ERROR作为一个目标被提及,则如果该规则发生变化或它的命令没有正确完成而退出,make将会删除该规则的目标,具体行为和它受到了删除信号一样。
.IGNORE
如果您特别为目标.IGNORE指明依赖,则MAKE将会忽略处理这些依赖文件时执行命令产生的错误。如果.IGNORE作为一个没有依赖的目标提出来,MAKE将忽略处理所有文件时产生的错误。.IGNORE命令并没有特别的含义,.IGNORE的用途仅是为了和早期版本的兼容。因为.IGNORE影响所有的命令,所以它的用途不大;我们推荐您使用其它方法来忽略特定命令产生的错误。
.SILENT
如果您特别为.SILENT指明依赖,则在执行之前MAKE将不会回显重新构造文件的命令。如果.SILENT作为一个没有依赖的目标提出来,任何命令在执行之前都不会打印。.SILENT并没有特别的含义,其用途仅是为了和早期版本的兼容。我们推荐您使用其它方法来处理那些不打印的命令。如果您希望所有的命令都不打印,请使用‘-s’或‘-silent’选项。
.EXPORT_ALL_VARIABLES
如该特殊目标简单的作为一个目标被提及,MAKE将缺省地把所有变量都传递到子进程中。
.NOTPARALLEL
如果.NOTPARALLEL作为一个目标提及,即使给出‘-j’选项,make也不使用并行执行。但递归调用的make命令仍可并行执行(在调用的makefile文件
中包含.NOTPARALLEL的目标的例外)。.NOTPARALLEL的任何依赖都将忽略。
任何定义的隐含规则后缀如果作为目标出现都会视为一个特殊规则,即使两个后缀串联起来也是如此,例如‘.c.o’。这些目标称为后缀规则,这种定义方法是过时的定义隐含规则的方法(目前仍然广泛使用的方法)。原则上,如果您要把它分为两个并把它们加到后缀列表中,任何目标名都可采用这种方法指定。实际上,后缀一般以‘.’开始,因此,这些特别的目标同样以‘.’开始。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值