Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Makefile模式规则要么忽略虚假规则,要么自动删除输出文件_Makefile_Wildcard_Gnu Make - Fatal编程技术网

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

Makefile模式规则要么忽略虚假规则,要么自动删除输出文件,makefile,wildcard,gnu-make,Makefile,Wildcard,Gnu Make,我正在尝试编写一个makefile,使用模式规则为多个源中的每个源生成多个输出文件 我有以下Makefile(GNU Make 3.8.1): 由于*.all不代表实际的输出文件,我尝试将它们标记为。但是,运行make则不起作用: $ ls Makefile $ make make: Nothing to be done for `all'. 根据make-d: No implicit rule found for `all'. Considering target file `foo.

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

我有以下
Makefile
(GNU Make 3.8.1):

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

$ ls
Makefile
$ make
make: Nothing to be done for `all'.
根据
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'.
它似乎在假装运行
%.所有的
规则,但跳过主体

但是在注释掉
.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
根据
make-d
,它说:

Removing intermediate files...
最小示例 给出异常行为的最小示例:

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

%.out:
    touch $@
我希望运行
makesomefile.all
使其创建文件
somefile.out
,但它会被删除:

$ make somefile.all
touch somefile.out
Made somefile
rm somefile.out

GNU make会考虑您的
somefile.out
文件,这就是在您的示例中自动删除这些文件的原因。您可以指示GNU make使用
.PRECIOUS
特殊目标保存这些文件,如下所示:

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

%.out:
    touch $@

.PRECIOUS: %.out
阻止make删除中间文件 我建议不要使用
.PRECIOUS
(原因见下文)。使用
.SECONDARY
将保留
.out
文件:

TARGETS=foo bar
all: $(TARGETS:=.all)

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

%.out:
    touch $@

.SECONDARY: $(TARGETS:=.out)
$(TARGETS:=.all)
只需将
.all
附加到
目标中的所有名称<代码>$(目标:=.out)
附加
.out
。显然,我们不能将
%.out
用作
.SECONDARY
的目标。这样就不用单独重新列出所有目标

我不想用
.PRECIOUS
来做这个,因为

如果make在其配方执行过程中被终止或中断,则不会删除目标

这会在文件系统中留下损坏的文件。这里有一个例子

all: foo.all bar.all

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

%.out:
    sh -e -c 'echo "{1, 2, 3" > $@; FAIL!; echo "}" >> $@'

.PRECIOUS: %.out
失败!命令模拟在其工作中间崩溃的工具。下面是一个shell会话,使用上面的Makefile:

$ ls
Makefile
$ make
sh -e -c 'echo "{1, 2, 3" > foo.out; FAIL!; echo "}" >> foo.out'
sh: 1: FAIL!: not found
make: *** [foo.out] Error 127
$ cat foo.out
{1, 2, 3
哎呀。。。我的
foo.out
文件不完整。让我们再试一次:

$ make
Made foo
sh -e -c 'echo "{1, 2, 3" > bar.out; FAIL!; echo "}" >> bar.out'
sh: 1: FAIL!: not found
make: *** [bar.out] Error 127
$ cat *.out
{1, 2, 3
{1, 2, 3
Make对于以前运行时留下的文件一点也不明智,因此当您再次运行Make时,它将按面值接收损坏的文件<代码>foo.out
没有重新生成(尽管有“makefoo”消息),因为它已经存在,并且生成文件直接尝试生成bar

.SECONDARY
使其能够:

.SECONDARY所依赖的目标被视为中间文件,只是它们不会自动删除

这意味着它们永远不会因为是中间文件而被自动删除。如果重建目标的工具崩溃,则删除正在重建的目标的默认生成行为不受影响

使用带有模式规则的
.PHONY
似乎
.PHONY
只适用于明确的目标,而不是推断的目标。我还没有找到证实这一点的文件。然而,这是可行的:

TARGETS:=foo bar
TARGETS_all:=$(TARGETS:=.all)

.PHONY: all
all: $(TARGETS_all)

.PHONY: $(TARGETS_all)
$(TARGETS_all): %.all: %.out
    @echo Made $*

%.out:
    touch $@

.SECONDARY: $(TARGETS:=.out)
在此规则中,
$(TARGETS\u all):%.all:%.out
$(TARGETS\u all):
给出了可应用模式的目标列表。它使
foo.all
bar.all
成为明确的目标。如果没有这一点,它们将被推断为目标


您可以通过在目录中创建名为
foo.all
的文件并反复运行make来测试它是否工作。
foo.all
文件对make没有影响。

我只能猜测
.PHONY
需要明确的目标。我已经用我的发现更新了我的答案。@Louis我们显然不能使用%.out作为.SECONDARY的目标。似乎是对我的答案的另一个确认,这是双冒号target/dep行的文档:这个问题是的重复,尽管不明显。阅读关于使用
.PHONY
匹配模式规则的回答。
TARGETS:=foo bar
TARGETS_all:=$(TARGETS:=.all)

.PHONY: all
all: $(TARGETS_all)

.PHONY: $(TARGETS_all)
$(TARGETS_all): %.all: %.out
    @echo Made $*

%.out:
    touch $@

.SECONDARY: $(TARGETS:=.out)