Makefile即使不应该递归地应用规则

时间:2016-09-29 19:23:22

标签: makefile gnu-make

我对GNU make有一个非常古怪的问题。我有以下文件:

a/x.html
b/Makefile
b/c/Makefile

a/x.html的内容无关紧要。 b/Makefile的内容如下:

SRC=../a
all: x.html

%.html: ${SRC}/%.html
        rsync $< $@

b/c/Makefile的内容相同,但SRC的定义除外:

SRC=../../a

如果我在make中运行b/c/,则结果符合预期:

rsync ../../a/x.html x.html

x.html已从a/复制到b/c/

但是,如果我在make中运行b/,我得到的输出就是几行:

make: stat: ../a/../a/.. (repeated many times) ../a/x.html: File name too long

似乎make递归地应用了%.html的规则,但为什么呢?有什么东西显而易见吗?

1 个答案:

答案 0 :(得分:1)

要构建与模式%.html匹配的目标(即以.html结尾的任何目标名称),如果规则可以构建依赖关系(使用{来自原始目标构建的目标),则应用规则{1}}前置)。

  1. 你要求建立../a/。这与模式x.html匹配,因此规则适用:make查看是否可以构建%.html
  2. ../a/x.html与模式../a/x.html匹配,因此规则适用:make查看是否可以构建%.html
  3. ../a/../a/x.html与模式../../a/x.html匹配,因此规则适用,等等。
  4. 词干字符可以匹配路径的任何部分,包括目录分隔符。

    您可以通过运行%.htmlmake -r -d来显示调试输出,-d来关闭会导致大量噪音的内置规则来查看正在尝试的内容。

    当您在-r时,这会在第2步停止,因为b/c存在但../../a/x.html没有。

    解决此问题的一种方法是列出您要操作的文件。您可以从../../../../a/x.html中已存在的文件列表中构建该列表:

    ../a

    这有一个缺点,如果$(notdir $(wildcard ${SRC}/*.html)): %.html: ${SRC}/%.html rsync $< $@ 中的HTML文件本身是由../a中的规则构建的,那么在b/Makefile中运行make将不会构建它们一个原始的源目录。这不应该是一个问题:在b b之外构建一个makefile是不常见的。

    另一种没有这种缺陷的方法是使用绝对路径。

    b