Makefile模式规则要么忽略虚假规则,要么自发删除输出文件

Mec*_*ail 5 makefile wildcard gnu-make

我正在尝试编写一个makefile以使用模式规则为多个源中的每个源生成多个输出文件。

我有以下Makefile(GNU Make 3.8.1):

all : foo.all bar.all

%.all : %.pdf %.svg
    @echo Made $*

%.pdf :
    touch $@

%.svg :
    touch $@

.PHONY: foo.all bar.all
Run Code Online (Sandbox Code Playgroud)

由于*.all不代表实际的输出文件,因此我尝试将其标记为.PHONY。但是,运行make则不起作用:

$ ls
Makefile
$ make
make: Nothing to be done for `all'.
Run Code Online (Sandbox Code Playgroud)

根据make -d

 No implicit rule found for `all'.
  Considering target file `foo.all'.
   File `foo.all' does not exist.
   Finished prerequisites of target file `foo.all'.
  Must remake target `foo.all'.
  Successfully remade target file `foo.all'.
  Considering target file `bar.all'.
   File `bar.all' does not exist.
   Finished prerequisites of target file `bar.all'.
  Must remake target `bar.all'.
  Successfully remade target file `bar.all'.
 Finished prerequisites of target file `all'.
Must remake target `all'.
Successfully remade target file `all'.
make: Nothing to be done for `all'.
Run Code Online (Sandbox Code Playgroud)

这似乎是假装执行%.all规则,但跳过了正文。

但是在.PHONY注释掉该行的情况下,Make运行目标,但随后自发决定删除输出文件:

$ make
touch foo.pdf
touch foo.svg
Made foo
touch bar.pdf
touch bar.svg
Made bar
rm foo.pdf foo.svg bar.pdf bar.svg
Run Code Online (Sandbox Code Playgroud)

根据make -d,它说:

Removing intermediate files...
Run Code Online (Sandbox Code Playgroud)

最小的例子

给出异常行为的最小示例:

%.all: %.out
    @echo Made $*

%.out:
    touch $@
Run Code Online (Sandbox Code Playgroud)

我希望运行make somefile.all以使其创建文件somefile.out,但它会被删除:

$ make somefile.all
touch somefile.out
Made somefile
rm somefile.out
Run Code Online (Sandbox Code Playgroud)

Eri*_*ski 2

您的somefile.out文件被 GNU make 视为中间文件,这就是它们在您的示例中被自动删除的原因。您可以指示 GNU make 通过使用.PRECIOUS特殊目标来保留这些文件,如下所示:

%.all: %.out
    @echo Made $*

%.out:
    touch $@

.PRECIOUS: %.out
Run Code Online (Sandbox Code Playgroud)