PHONY在Makefile中是什么意思?我已经经历过了,但这太复杂了。
有人能简单地向我解释一下吗?
PHONY在Makefile中是什么意思?我已经经历过了,但这太复杂了。
有人能简单地向我解释一下吗?
当前回答
“.PHONY”还有一个重要的棘手之处——当一个物理目标依赖于另一个物理对象的虚假目标时:
目标1->PHONY_FORWARDER1->PHONY-FORWARDER2->TARGET2
您可以简单地预期,如果您更新了TARGET2,那么TARGET1应该被认为是过时的,因此TARGET1应该重新构建。它确实是这样工作的。
棘手的部分是,当TARGET2与TARGET1不过时时——在这种情况下,您应该预计TARGET1不应该重建。
这令人惊讶地不起作用,因为:无论如何都运行了假目标(就像假目标通常所做的那样),这意味着假目标被认为是更新的。正因为如此,TARGET1被认为是过时的,而不是虚假的目标。
考虑:
all: fileall
fileall: file2 filefwd
echo file2 file1 >fileall
file2: file2.src
echo file2.src >file2
file1: file1.src
echo file1.src >file1
echo file1.src >>file1
.PHONY: filefwd
.PHONY: filefwd2
filefwd: filefwd2
filefwd2: file1
@echo "Produced target file1"
prepare:
echo "Some text 1" >> file1.src
echo "Some text 2" >> file2.src
你可以玩这个:
首先做“make prepare”以准备“源文件”通过触摸特定文件来查看它们的更新
您可以看到,fileall通过一个虚假的目标间接依赖于file1,但由于这种依赖性,它总是被重新构建。如果您将fileall中的依赖项从filefwd更改为file,那么现在fileall不会每次都重新生成,而是只有在任何依赖目标作为文件过时时才会重新生成。
其他回答
它是不是文件名的生成目标。
.PHONY: install
表示单词“install”不代表此文件中的文件名生成文件;表示Makefile与名为“install”的文件无关在同一目录中。
“.PHONY”还有一个重要的棘手之处——当一个物理目标依赖于另一个物理对象的虚假目标时:
目标1->PHONY_FORWARDER1->PHONY-FORWARDER2->TARGET2
您可以简单地预期,如果您更新了TARGET2,那么TARGET1应该被认为是过时的,因此TARGET1应该重新构建。它确实是这样工作的。
棘手的部分是,当TARGET2与TARGET1不过时时——在这种情况下,您应该预计TARGET1不应该重建。
这令人惊讶地不起作用,因为:无论如何都运行了假目标(就像假目标通常所做的那样),这意味着假目标被认为是更新的。正因为如此,TARGET1被认为是过时的,而不是虚假的目标。
考虑:
all: fileall
fileall: file2 filefwd
echo file2 file1 >fileall
file2: file2.src
echo file2.src >file2
file1: file1.src
echo file1.src >file1
echo file1.src >>file1
.PHONY: filefwd
.PHONY: filefwd2
filefwd: filefwd2
filefwd2: file1
@echo "Produced target file1"
prepare:
echo "Some text 1" >> file1.src
echo "Some text 2" >> file2.src
你可以玩这个:
首先做“make prepare”以准备“源文件”通过触摸特定文件来查看它们的更新
您可以看到,fileall通过一个虚假的目标间接依赖于file1,但由于这种依赖性,它总是被重新构建。如果您将fileall中的依赖项从filefwd更改为file,那么现在fileall不会每次都重新生成,而是只有在任何依赖目标作为文件过时时才会重新生成。
我经常用它们来告诉默认目标不要开火。
superclean: clean andsomethingelse
blah: superclean
clean:
@echo clean
%:
@echo catcher $@
.PHONY: superclean
如果没有PHONY,使超级清洁将发射干净,以及其他一些东西,并捕捉超级清洁;但是有了PHONY,make superclean就不会解雇捕手superclean了。
我们不必担心会告诉对方,明确的目标是PHONY,因为它并不完全是假的。虽然它从未生成干净的文件,但它有命令可以启动,因此make会认为它是最终目标。
然而,超精简目标确实是假的,因此make将尝试将其与为超精简目标提供dep的任何其他内容叠加起来-这包括其他超精简目标和%目标。
请注意,我们根本没有说任何关于或其他什么的话,所以他们很明显会去找捕手。
输出如下所示:
$ make clean
clean
$ make superclean
clean
catcher andsomethingelse
$ make blah
clean
catcher andsomethingelse
catcher blah
注意:make工具读取makefile并检查规则中“:”符号两侧文件的修改时间戳。
实例
在目录“test”中存在以下文件:
prerit@vvdn105:~/test$ ls
hello hello.c makefile
在makefile中,规则定义如下:
hello:hello.c
cc hello.c -o hello
现在假设文件“hello”是一个包含一些数据的文本文件,它是在“hello.c”文件之后创建的。因此,“hello”的修改(或创建)时间戳将比“hello.c”的更新。因此,当我们从命令行调用“make hello”时,它将打印为:
make: `hello' is up to date.
现在访问“hello.c”文件并在其中添加一些空格,这不会影响代码语法或逻辑,然后保存并退出。现在hello.c的修改时间戳比“hello”的修改时间戳记新。现在,如果您调用“make hello”,它将执行以下命令:
cc hello.c -o hello
文件“hello”(文本文件)将被一个新的二进制文件“hell”(上述编译命令的结果)覆盖。
如果我们在makefile中使用.PHONY,如下所示:
.PHONY:hello
hello:hello.c
cc hello.c -o hello
然后调用“makehello”,它将忽略pwd“test”中存在的任何文件,并每次执行该命令。
现在假设“hello”目标没有声明依赖项:
hello:
cc hello.c -o hello
如果pwd“test”中已经存在“hello”文件,那么“make hello”将始终显示为:
make: `hello' is up to date.