Laz*_*zer 1535 makefile phony-target
.PHONYMakefile 中的含义是什么?我已经完成了这个,但它太复杂了.
有人可以用简单的语言向我解释一下吗?
Eli*_*sky 1749
默认情况下,Makefile目标是"文件目标" - 它们用于从其他文件构建文件.假设它的目标是一个文件,这使得编写Makefile相对容易:
foo: bar
create_one_from_the_other foo bar
Run Code Online (Sandbox Code Playgroud)
但是,有时您希望Makefile运行不代表文件系统中的物理文件的命令.这方面的好例子是"清洁"和"全部"的共同目标.可能情况并非如此,但您可能clean在主目录中有一个名为的文件.在这种情况下,Make会被混淆,因为默认情况下,clean目标将与此文件关联,而Make只会在文件看起来与其依赖关系不相关时运行它.
这些特殊目标称为假冒,您可以明确告诉他们与文件无关,例如:
.PHONY: clean
clean:
rm -rf *.o
Run Code Online (Sandbox Code Playgroud)
make clean即使您有一个名为的文件,现在也会按预期运行clean.
就Make而言,虚假目标只是一个总是过时的目标,所以无论何时你问make <phony_target>,它都会运行,独立于文件系统的状态.一些常见的make是经常假目标是:all,install,clean,distclean,TAGS,info,check.
Geo*_* Y. 703
让我们假设您有install目标,这在makefile中非常常见.如果您不使用.PHONY,并且名为的文件install与Makefile位于同一目录中,则不make install执行任何操作.这是因为Make将规则解释为"执行这样的配方以创建名为install" 的文件.由于文件已经存在,并且其依赖关系没有改变,因此不会做任何事情.
但是,如果您创建install目标PHONY,它将告诉make工具目标是虚构的,并且make不应该指望它创建实际文件.因此,它不会检查install文件是否存在,这意味着:a)如果文件存在则不会改变其行为,b)stat()不会调用extra .
通常,Makefile中不生成与目标名称同名的输出文件的所有目标都应该是PHONY.这通常包括all,install,clean,distclean,等.
小智 102
注意:make工具读取makefile并检查规则中":"符号两侧的文件的修改时间戳.
在目录'test'中存在以下文件:
prerit@vvdn105:~/test$ ls
hello hello.c makefile
Run Code Online (Sandbox Code Playgroud)
在makefile中,规则定义如下:
hello:hello.c
cc hello.c -o hello
Run Code Online (Sandbox Code Playgroud)
现在假设文件'hello'是包含一些数据的文本文件,该文件是在'hello.c'文件之后创建的.因此'hello'的修改(或创建)时间戳将比'hello.c'更新.因此,当我们从命令行调用'make hello'时,它将打印为:
make: `hello' is up to date.
Run Code Online (Sandbox Code Playgroud)
现在访问'hello.c'文件并在其中放入一些空格,这不会影响代码语法或逻辑,然后保存并退出.现在hello.c的修改时间戳比'hello'的修改时间戳更新.现在,如果你调用'make hello',它将执行以下命令:
cc hello.c -o hello
Run Code Online (Sandbox Code Playgroud)
文件'hello'(文本文件)将被一个新的二进制文件'hello'覆盖(上面的编译命令的结果).
如果我们在makefile中使用.PHONY如下:
.PHONY:hello
hello:hello.c
cc hello.c -o hello
Run Code Online (Sandbox Code Playgroud)
然后调用'make hello',如果pwd中存在任何名为'hello'的文件,它将忽略每次执行命令.
现在假设如果makefile中没有target的依赖项:
hello:
cc hello.c -o hello
Run Code Online (Sandbox Code Playgroud)
'hello'文件已存在于pwd'test'中,然后'make hello'将始终显示为:
make: `hello' is up to date.
Run Code Online (Sandbox Code Playgroud)
You*_*Bet 73
.PHONY: install
Run Code Online (Sandbox Code Playgroud)
Jam*_*ald 29
最好的解释是GNU make手册本身:4.6 Phony Targets部分.
.PHONY是make的特殊内置目标名称之一.您可能感兴趣的还有其他目标,因此值得浏览这些参考资料.
当需要考虑.PHONY目标时,make将无条件地运行其配方,无论具有该名称的文件是否存在或其最后修改时间是什么.
您可能还对make的标准目标感兴趣,例如all和clean.
Edo*_*iel 20
特殊目标.PHONY:允许声明虚假目标,因此不会make将它们检查为实际文件名:即使此类文件仍然存在,它也会一直工作。
你可以把几个.PHONY:放在你的Makefile:
.PHONY: all
all : prog1 prog2
...
.PHONY: clean distclean
clean :
...
distclean :
...
Run Code Online (Sandbox Code Playgroud)
还有另一种声明虚假目标的方法:简单地::不带先决条件:
all :: prog1 prog2
...
clean ::
...
distclean ::
...
Run Code Online (Sandbox Code Playgroud)
该::有其他的含义,看到这里,但没有先决条件总是执行的食谱,即使目标已经存在,从而充当假目标。
Eth*_*ris 11
还有一个重要的棘手问题".PHONY" - 当物理目标依赖于依赖于另一个物理目标的虚假目标时:
TARGET1 - > PHONY_FORWARDER1 - > PHONY_FORWARDER2 - > TARGET2
您只是希望如果您更新了TARGET2,那么应该将TARGET1视为对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
Run Code Online (Sandbox Code Playgroud)
你可以玩这个:
你可以看到fileall通过假目标间接依赖于file1 - 但由于这种依赖性,它总是被重建.如果您更改依赖fileall从filefwd到file现在fileall没有得到重建,每一次,但只有当依赖目标的任何反对它陈旧的文件.
小智 10
因此,假设运行 make 的目录中有一个名为“clean”的文件。现在让我们以下面的 Makefile 为例:
clean:
rm lol
Run Code Online (Sandbox Code Playgroud)
现在,当您运行“make clean”时,您将得到以下输出:

但如果将“.PHONY: clean”添加到 Makefile 并运行“make clean”,您将看到以下输出:

发生了什么?由于目录中存在文件,所以第一次将 clean 视为目标。但添加 .PHONY 后,make 会忽略该文件(以及时间戳跟踪)并将其解释为正常干净。
现在,这可以应用于许多情况,您希望 make 忽略作为目标给出的参数(当您在该目录中具有相同名称的文件时)。
我经常用它们来告诉默认目标不要开火。
\n\nsuperclean: clean andsomethingelse\n\nblah: superclean\n\nclean:\n @echo clean\n\n%:\n @echo catcher $@\n\n.PHONY: superclean\nRun Code Online (Sandbox Code Playgroud)\n\n如果没有 PHONY,make superclean则会触发clean、andsomethingelse、 和catcher superclean;但对于 PHONY,make superclean不会触发catcher superclean.
我们不必担心告诉 makeclean target is PHONY, because it isn't completely phony. Though it never produces the clean file, it has commands to fire so make will think it's a final target.
然而,superclean目标确实是假的,所以 make 会尝试将它与任何其他为目标 \xe2\x80\x94 提供依赖的东西堆叠起来,superclean这包括其他superclean目标和% target.
请注意,我们根本没有提及andsomethingelse或blah, so they clearly go to the catcher.
输出看起来像这样:
\n\n$ make clean\nclean\n\n$ make superclean\nclean\ncatcher andsomethingelse\n\n$ make blah \nclean\ncatcher andsomethingelse\ncatcher blah\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
362667 次 |
| 最近记录: |