我对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
的规则,但为什么呢?有什么东西显而易见吗?
答案 0 :(得分:1)
要构建与模式%.html
匹配的目标(即以.html
结尾的任何目标名称),如果规则可以构建依赖关系(使用{来自原始目标构建的目标),则应用规则{1}}前置)。
../a/
。这与模式x.html
匹配,因此规则适用:make查看是否可以构建%.html
。../a/x.html
与模式../a/x.html
匹配,因此规则适用:make查看是否可以构建%.html
。../a/../a/x.html
与模式../../a/x.html
匹配,因此规则适用,等等。词干字符可以匹配路径的任何部分,包括目录分隔符。
您可以通过运行%.html
(make -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