即使没有更改,Makefile 也始终会构建
我有以下 Makefile 用于在 tex 源文件上运行 pdflatex:
MAKEFLAGS += --warn-undefined-variables
deps := mydoc.tex mydoc.cls
mydoc.pdf: $(deps)
.PHONY: build
build: $(deps)
pdflatex mydoc.tex mydoc.pdf
.PHONY: build
clean: ## Delete misc
rm -f mydoc.out mydoc.pdf mydoc.aux mydoc.log
当我运行 make build
时,它总是运行 pdflatex,即使 mydoc.tex
没有更改。
我的理解是 make build
应该说如果 mydoc.tex
没有改变就没有什么可做的。我做错了什么?
I have the following Makefile for running pdflatex on tex source files:
MAKEFLAGS += --warn-undefined-variables
deps := mydoc.tex mydoc.cls
mydoc.pdf: $(deps)
.PHONY: build
build: $(deps)
pdflatex mydoc.tex mydoc.pdf
.PHONY: build
clean: ## Delete misc
rm -f mydoc.out mydoc.pdf mydoc.aux mydoc.log
When I run make build
it always runs pdflatex even though mydoc.tex
has not changed.
My understanding is make build
should say there is nothing to do if mydoc.tex
has not changed. What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,您已将目标
build
声明为.PHONY
。虚假目标的全部意义在于,它总是被认为是过时的,并且它的配方将被调用。所以,当然,配方总是运行的。即使您删除了
.PHONY
,该配方仍将始终运行。你说 make 应该什么都不做,因为mydoc.tex
没有改变……那么,make 如何知道mydoc.tex
没有改变呢?与什么相比没有改变? Make 没有自己的数据库来告诉它上次运行的时间,以及文件上的所有时间戳在过去的某个时间是什么。它只是依赖于比较文件系统上现在存在的文件的时间戳。当您编写规则时,它会告诉 make,如果任何先决条件的修改时间比目标更新,则目标已过时,应运行配方以使其保持最新。
因此,如果您编写规则
build: mydoc.tex
,make 将查看先决条件mydoc.tex
是否比目标build
新。由于没有文件build
并且从未创建过文件,因此mydoc.tex
将始终被视为比不存在的文件更新,并且配方将始终运行。您需要确保规则的目标是配方更新的文件。最佳实践是确保您编写的每个配方(更新文件)都会更新
$@
自动变量中包含的文件:First, you've declared the target
build
to be.PHONY
. The entire point of a phony target is that it will always be considered out of date and its recipe will be invoked. So, of course the recipe is always run.Even if you remove the
.PHONY
though, the recipe will always be run. You say make should do nothing ismydoc.tex
has not changed... well, how can make know thatmydoc.tex
has not changed? Not changed compared to what? Make doesn't have its own database that tells it the last time it ran, and what all the timestamps on the files were at some time in the past. It simply relies on comparing timestamps of files on the filesystem as they exist now.When you write a rule it tells make, if any of the prerequisites have a newer modification time than the target, then the target is out of date and the recipe should be run to bring it up to date.
So if you write a rule
build: mydoc.tex
make will look to see if the prerequisitemydoc.tex
is newer than the targetbuild
. Since there is no filebuild
and one is never created,mydoc.tex
will always be considered newer than a non-existent file, and the recipe will always be run.You need to be sure that the target of the rule is the file that is updated by the recipe. Best practice is to ensure that every recipe you write (that updates a file) updates the file contained in the
$@
automatic variable: