伪目标.PHONY

来源:互联网 发布:aws java sdk 编辑:程序博客网 时间:2024/05/05 20:37

这次只有一个main.cpp和一个Makefile文件。

main.cpp

#include <iostream>using namespace std;int main(){cout<<"hello world!"<<endl;return 0;}

Makefile

main:main.og++ -o main main.omain.o:main.cppg++ -c -o main.o main.cpp
执行make之后,目录内多出来了2个文件main.o和main,我们需要的是main,而main.o只是一个中间文件,对于我们来说并不需要,可以删除掉。

我们可以把Makefile这样写:

main:main.og++ -o main main.omain.o:main.cppg++ -c -o main.o main.cppclean:rm *.o
增加了一条规则,目标文件为clean,由于没有依赖的文件,也就是目标文件永远是新的,所以这条规则不会主动执行。

为了执行这条规则,我们可以这样make clean,这样就可以删除所有的.o结尾的文件。

但是当目录内没有.o结尾的文件时,这条命令将会报错,并停止往下执行。

我们把Makefile修改成这样,做个试验:

main:main.og++ -o main main.omain.o:main.cppg++ -c -o main.o main.cppclean:rm *.oecho "clean obj"
删除成功之后,将会输出clean obj。

多次执行make clean,当目录内已经没有.o结尾的文件时,将会出现下面的错误。

rm *.orm: cannot remove `*.o': No such file or directorymake: *** [clean] Error 1
并且也没有往下执行输出clean obj,但是我们关心的不是删除的成功或失败,我们关心的是保证不存在.o结尾的文件。

但是这个Makefile中,如果不存在.o文件,竟然会报错,并且终止执行,shit。

我们可以做如下修改:

main:main.og++ -o main main.omain.o:main.cppg++ -c -o main.o main.cppclean:-rm *.o
也就是在rm的前面加一个减号,这样即使目录内没有.o文件,也会继续往下执行。只不过还是会有出错提示。

rm *.orm: cannot remove `*.o': No such file or directorymake: [clean] Error 1 (ignored)echo "clean obj"clean obj
看到这一坨出错提示,感觉很不爽,我们在修改Makefile,如下:

main:main.og++ -o main main.omain.o:main.cppg++ -c -o main.o main.cppclean:-rm -f *.oecho "clean obj"
即在-rm和*.o之间添加-f,这样无论我们执行多少次make clean,输出结果都是:

rm -f *.oecho "clean obj"clean obj

但是,不要以为这样就万事OK了,我们在目录内添加一个文件,文件名为clean。

我们再执行make clean,结果竟然是:

make: `clean' is up to date.
由于目标clean文件没有依赖文件,并且clean文件已经存在了,所以clean这个目标文件永远是最新的,我们在clean中写的东东也永远不会执行。

怎么办,可以通过Makefile的关键字.PHONY,它显式声明一个目标文件是伪目标,执行该伪目标时,make并不关心该目标文件是否存在,只管执行。

main:main.og++ -o main main.omain.o:main.cppg++ -c -o main.o main.cpp.PHONY:cleanclean:-rm -f *.oecho "clean obj"
这样,不管clean文件是否存在,make clean的时候,clean目标中的命令都会执行。

不管.o文件是否存在,make clean的时候,都不会报错。