为什么这个Makefile无法构建成为最终目标,但所有中间目标都能正常工作?

时间:2016-08-19 13:53:31

标签: makefile runtime-error

假设我们有以下Makefile:

.PHONY: build
build:
    cd .. && make

%.hl.a.json: %.c
    touch $@

%.hl.b.json: %.hl.a.json
    touch $@

%.x.p.json: %.hl.b.json
    touch $@

%.x.hl.a.json: %.x.p.json
    touch $@

%.x.hl.b.json: %.x.hl.a.json
    touch $@

.PHONY: clean
clean:
    $(RM) *.json

我们假设我们有一个名为small.c的文件,我想构建small.hl.b.json。但是,运行make small.hl.b.json(使用GNU Make 3.81)会给我:

$ make small.x.hl.b.json
make: *** No rule to make target `small.x.hl.b.json'.  Stop.

但是,Makefile适用于构建生成

small.x.hl.a.json
$ make small.x.hl.a.json
touch small.hl.a.json
touch small.hl.b.json
touch small.x.p.json
touch small.x.hl.a.json
rm small.x.p.json small.hl.a.json small.hl.b.json

因此,如果我首先运行make small.x.hl.a.json,然后然后 make small.x.hl.b.json,那么一切正常。

现在它变得有趣了。如果我执行以下操作:

$ make small.x.hl.a.json
touch small.hl.a.json
touch small.hl.b.json
touch small.x.p.json
touch small.x.hl.a.json
rm small.x.p.json small.hl.a.json small.hl.b.json

$ make clean
rm -f *.json

$ make small.x.hl.b.json
make: *** No rule to make target `small.x.hl.b.json'.  Stop.

它不起作用。但如果我这样做, 就会起作用:

$ make small.x.hl.a.json
touch small.hl.a.json
touch small.hl.b.json
touch small.x.p.json
touch small.x.hl.a.json
rm small.x.p.json small.hl.a.json small.hl.b.json

$ make clean small.x.hl.b.json
rm -f *.json
touch small.hl.a.json
touch small.hl.b.json
touch small.x.p.json
touch small.x.hl.a.json
touch small.x.hl.b.json
rm small.x.p.json small.hl.a.json small.hl.b.json

有人能告诉我发生了什么事吗?为什么我不能直接构建small.x.hl.b.json,而必须首先构建small.x.hl.a.json然后 small.x.hl.b.json

2 个答案:

答案 0 :(得分:0)

我可能错了,如果有人能提供更好的答案,我会删除这个答案,但这对我来说就像GNUMake 3.81中的错误一样

首先考虑目标small.x.hl.b.json,找到两个与之匹配的模式规则:

%.hl.b.json: %.hl.a.json # call this rule 2
    ...

%.x.hl.b.json: %.x.hl.a.json # call this rule 5
    ...

请注意,这两个规则都具有相同的先决条件,small.x.hl.a.json

看起来Make然后犯了一个错误。 (这是我出去的地方。)它正在寻找一种构建small.x.hl.a.json的方法,记住它已经使用了规则2和5,但是没有记住它们是并行替代品,而不是顺序步骤。稍后,当Make需要small.hl.b.json时,唯一要服务的规则是规则2,其中拒绝理由是它不能在链中使用相同的模式规则两次。不要紧,这个调用会使用一个较短的词干,更不用说有问题的链实际上是两个链,其中一个尚未使用规则2,Make认为这是一个死胡同。

这也符合其他实验的结果。 Make可以在没有这种自我碰撞的情况下构建small.x.hl.b.json,一旦构建了该目标,Make就可以在一个步骤中构建small.x.hl.b.json,而不会产生麻烦的链。

答案 1 :(得分:0)

我找到了一个教程说:

  

首先尝试使用短杆的规则,如果存在平局,则会选择首先出现的规则。

所以我尝试交换规则的顺序以便.x。目标首先出现,然后一切正常!