请问大家makefile 中的这样的标记起什么作用

xiehui888 2009-03-03 09:42:43
我在资料上看到 :

.PHONY : clean
clean :
rm edit $(objects)
这种方法,也就是make的“隐晦规则”。上面文件内容中,“.PHONY”表示,clean是个伪目标文件



我想问大家的是伪目标文件起的是什么作用


make .PHONY 与make clean 命令是一样的结果吗?

...全文
875 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
josephSC 2011-01-25
  • 打赏
  • 举报
回复
下面是英文版的phony手册,比较详尽:


4.6 Phony Targets

A phony target is one that is not really the name of a file; rather it is just a name for a recipe to be executed when you make an explicit request. There are two reasons to use a phony target: to avoid a conflict with a file of the same name, and to improve performance.

If you write a rule whose recipe will not create the target file, the recipe will be executed every time the target comes up for remaking. Here is an example:

clean:
rm *.o temp

Because the rm command does not create a file named clean, probably no such file will ever exist. Therefore, the rm command will be executed every time you say ‘make clean’. The phony target will cease to work if anything ever does create a file named clean in this directory. Since it has no prerequisites, the file clean would inevitably be considered up to date, and its recipe would not be executed. To avoid this problem, you can explicitly declare the target to be phony, using the special target .PHONY (see Special Built-in Target Names) as follows:

.PHONY : clean

Once this is done, ‘make clean’ will run the recipe regardless of whether there is a file named clean.

Since it knows that phony targets do not name actual files that could be remade from other files, make skips the implicit rule search for phony targets (see Implicit Rules). This is why declaring a target phony is good for performance, even if you are not worried about the actual file existing.

Thus, you first write the line that states that clean is a phony target, then you write the rule, like this:

.PHONY: clean
clean:
rm *.o temp

Another example of the usefulness of phony targets is in conjunction with recursive invocations of make (for more information, see Recursive Use of make). In this case the makefile will often contain a variable which lists a number of subdirectories to be built. One way to handle this is with one rule whose recipe is a shell loop over the subdirectories, like this:

SUBDIRS = foo bar baz

subdirs:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir; \
done

There are problems with this method, however. First, any error detected in a submake is ignored by this rule, so it will continue to build the rest of the directories even when one fails. This can be overcome by adding shell commands to note the error and exit, but then it will do so even if make is invoked with the -k option, which is unfortunate. Second, and perhaps more importantly, you cannot take advantage of make's ability to build targets in parallel (see Parallel Execution), since there is only one rule.

By declaring the subdirectories as phony targets (you must do this as the subdirectory obviously always exists; otherwise it won't be built) you can remove these problems:

SUBDIRS = foo bar baz

.PHONY: subdirs $(SUBDIRS)

subdirs: $(SUBDIRS)

$(SUBDIRS):
$(MAKE) -C $@

foo: baz

Here we've also declared that the foo subdirectory cannot be built until after the baz subdirectory is complete; this kind of relationship declaration is particularly important when attempting parallel builds.

A phony target should not be a prerequisite of a real target file; if it is, its recipe will be run every time make goes to update that file. As long as a phony target is never a prerequisite of a real target, the phony target recipe will be executed only when the phony target is a specified goal (see Arguments to Specify the Goals).

Phony targets can have prerequisites. When one directory contains multiple programs, it is most convenient to describe all of the programs in one makefile ./Makefile. Since the target remade by default will be the first one in the makefile, it is common to make this a phony target named ‘all’ and give it, as prerequisites, all the individual programs. For example:

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

Now you can say just ‘make’ to remake all three programs, or specify as arguments the ones to remake (as in ‘make prog1 prog3’). Phoniness is not inherited: the prerequisites of a phony target are not themselves phony, unless explicitly declared to be so.

When one phony target is a prerequisite of another, it serves as a subroutine of the other. For example, here ‘make cleanall’ will delete the object files, the difference files, and the file program:

.PHONY: cleanall cleanobj cleandiff

cleanall : cleanobj cleandiff
rm program

cleanobj :
rm *.o

cleandiff :
rm *.diff
gdh7201 2010-08-07
  • 打赏
  • 举报
回复
thanks!
zjs_worm 2009-04-02
  • 打赏
  • 举报
回复
“.PHONY 来显示地指明一个目标是“伪目标”,向make说明,不管是否有这个文件,这个目标就是“伪目标”。
伪目标的特性是:总是被执行的.
.PHONY : clean
只要有这个声明,不管是否有“clean”文件,要运行“clean”这个目标,只有“make clean””


这两句让我很困惑啊!!既然“总是被执行的”,那干嘛还要显性得“make clean”才能让clean执行呢??

PS:哪位兄弟有make 的 manual (英文版)分享一下啊??不胜感激!!!
xiehui888 2009-03-04
  • 打赏
  • 举报
回复
2楼正解
fox000002 2009-03-03
  • 打赏
  • 举报
回复
可以多查查 make 的 manual

A phony target is one that is not really the name of a file. 
It is just a name for some commands to be executed when you
make an explicit request. There are two reasons to use a phony
target: to avoid a conflict with a file of the same name,
and to improve performance.
  • 打赏
  • 举报
回复
..我也是看的陈皓-<跟我一起写 Makefile>,很详尽.
ckc 2009-03-03
  • 打赏
  • 举报
回复
.PHONY 不是什么“伪目标”
它和all的目的是不一样的
.phony是一个特殊工作目标(special target)
它用来指定一个假想的工作目标,也就是说它后面的并不是一个实际文件,而且肯定要视为未更新(也就是说条件总是满足,需要处理)

上面的兄弟,不要被坏书误导啊
平平 2009-03-03
  • 打赏
  • 举报
回复
.PHONY 来显示地指明一个目标是“伪目标”,向make说明,不管是否有这个文件,这个目标就是“伪目标”。
伪目标的特性是:总是被执行的.
.PHONY : clean
只要有这个声明,不管是否有“clean”文件,要运行“clean”这个目标,只有“make clean”这样。于是整个过程可以这样写:
.PHONY: clean
clean:
rm *.o temp
伪目标一般没有依赖的文件。但是,我们也可以为伪目标指定所依赖的文件。伪目标同样可以作为“默认目标”,只要将其放在第一个。一个示例就是,如果你的Makefile需要一口气生成若干个可执行文件,但你只想简单地敲一个make完事,并且,所有的目标文件都写在一个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
我们知道,Makefile中的第一个目标会被作为其默认目标。我们声明了一个“all”的伪目标,其依赖于其它三个目标。由于伪目标的特性是,总是被执行的,所以其依赖的那三个目标就总是不如“all”这个目标新。所以,其它三个目标的规则总是会被决议。也就达到了我们一口气生成多个目标的目的。“.PHONY : all”声明了“all”这个目标为“伪目标”。
随便提一句,从上面的例子我们可以看出,目标也可以成为依赖。所以,伪目标同样也可成为依赖。看下面的例子:
.PHONY: cleanall cleanobj cleandiff
cleanall : cleanobj cleandiff
rm program
cleanobj :
rm *.o
cleandiff :
rm *.diff
“make clean”将清除所有要被清除的文件。“cleanobj”和“cleandiff”这两个伪目标有点像“子程序”的意思。我们可以输入“make cleanall”和“make cleanobj”和“make cleandiff”命令来达到清除不同种类文件的目的。

推荐你看 陈皓-《跟我一起写 Makefile》

3,287

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 实用资料发布区
社区管理员
  • 实用资料发布区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧