Makefile: 避免无限模式递归

6

我认为这很简单

%.png: ../figs/%.png
        convert $? -resize '40%' $@

我的意思是,我想从"../figs/"中的相应图像在此目录中生成一张图片。

但是,上述方法会导致无限的依赖关系链,因为../figs/foo.png匹配%.png,因此make尝试检查../figs/../figs/foo.png,这又匹配了%.png,因此make继续尝试...最终,make停止并显示"文件名太长"。

我必须遗漏了什么。有没有一个简单的解决方案?

3个回答

7

使用空规则来中止链路

%.png: ../figs/%.png
    convert $? -resize '40%' $@

../figs/%.png: ;

谢谢!太完美了。有趣的是,与 Mac OS X 一起提供的 GNU Make 3.81 仍然会使用您的代码生成无限循环,而我单独安装的 GNU Make 4.2.1 则不会。这是否意味着这个问题只是最近才被解决? - Ryo
1
3.82中,模式规则似乎已经被切换到了最短干扰词顺序,你可以通过将空规则放在其他规则之前来解决这个问题。在3.81中可以采取这种方法。 - user657267

4

以上所有答案都非常有趣。然而,我想提到终端规则解决方案:

%.png:: ../figs/%.png
    convert $? -resize '40%' $@

通过更改为双冒号::,我们就能标记先决条件终止

一种选择是通过使用双冒号定义匹配任何规则来将其标记为终止。 当规则为终止时,它仅在其先决条件实际存在时生效。使用其他隐式规则生成的预备条件不够好。换句话说,在终止规则之外不允许进一步链接。

注意:仅适用于匹配任何规则。


1

user657267的解决方案非常完美。另一个选择是使用静态模式规则:

PNGS    := $(patsubst ../figs/%.png,%.png,$(wildcard ../figs/*.png))

all: $(PNGS)

$(PNGS): %.png: ../figs/%.png
    convert $< -resize '40%' $@

clean:
    rm -f $(PNGS)

从所有先决条件的列表计算出所有目标的列表具有几个不错的副作用,例如可以添加allclean目标。

1
谢谢!我已经使用了类似于你的PNGS的目标列表,但我不知道你可以使用该列表来限制模式的应用(即你的第3个非空行,带有两个冒号)。顺便说一句,我使用$(notdir ...)函数而不是patsubst - Ryo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接