在进入话题之前有几个概念一定要牢牢记在脑子里:
执行规则命令的条件是:
1.依赖比目标新时,这里特别要注意的地方是一般目标总是比依赖新的,为什么呢,因为目标是根据依赖来生成的,所以目标的创建时间总是比依赖的创建时间要新,只有当人工改动依赖文件时,依赖文件的时间属性才会更新。举一个例子有三个工程文件main.c a.c b.c ,main.out依赖于main.o a.o b.o,*.o依赖于*.c,第一次make生成了main.out和所有的.o文件。之后改动一下a.c,再次make执行时是先找到第一个终极目标main.out,这时main.out是比所有的.o文件依赖都新的,所以make在这个时候是不会比较的,要不然就不用执行直接退出了,make执行过程是纵深递归展开的,一直到a.o:a.c等依赖发现不能再展开时再比较,因为a.c比a.o新,所以执行其后面的规则,之后又依次展开其他的*.o:*.c,当然这里的main.o,b.o是不用编译更新的,但还是要展开
最后才返回到main.out目标依赖,发现a.o比main.out新,其后面的规则当然就要执行了。
2.真实的目标文件不存在,注意哦,文件两个字是要特别强调的,伪目标和标签永远也不会是文件,所以它们永远是过期的,依赖
总是比它们新,即使依赖是空的也是如此,通过执行后面的规则命令生成了最新的目标(注意规则命令执行完后,目标总是最新的,不管其是标签还是伪目标)执行完后,make会认为这些伪目标或标签是最新的,当
它们再次作为别的目标依赖时,由于它们是最新的(比它们的依赖新),所以它们后面的规则命令就不会再次执行。不知道讲清楚了没有,下面通过一个例子来演示一下。总的来说伪
目标和标签作为目标时没什么区别。
.PHONY one two three four
total: one two three
@echo "this is the total"
othertotal: one two three four
@echo "this is the othertotal"
three: one two
@echo "this is the three"
one:
@echo "this is the one"
two:
@echo "this is the two"
four:
@echo "this is the four"
执行 make total
结果是:this is the one
this is the two
this is the three
this is the total
简说一下执行过程:
查找看有没有total(这里是标签)这个文件,没有,说明后面的规则命令肯定是要执行的,在执行之前,要先递归
展开one、two和three,先展开one,one是个伪目标,不存在one这样一个目标文件,所以过期,所以它后面的规则命令
要执行来假定生成了一个one这样的最新目标文件。two的过程也是如此。但这里three依赖的one two并没有执行,那是因
为在three之前已经执行了一次one、two,所以在执行three时one和two已经是最新的了。three也是伪目标,没有three这样的目标文件,one和two又是最新的,所以不管从那方面说,three后面的规则命令肯定都要执行了。
执行make othertotal
this is the one
this is the two
this is the three
this is the four
this is the othertotal
这个和上面的差不多
下面在来看一个更有意思的例子make total othertotal,这种情况经常能在大型的工程中见到
执行结果:
this is the one
this is the two
this is the tree
this is the total
this is the four
this is the othertotal
由于它们都是在同一个makefile文件中执行,所以前一个目标的执行结果是会影响到后面的。
大家还可以用#号注释掉.PHONY one two three four这句话,都成了标签,效果会不同吗?试试看吧!