依赖于目录下(包括子目录)所有文件的Makefile规则

问题描述 投票:0回答:2

我的 Makefile 中的一条规则将整个目录 (

res/
) 压缩为 ZIP 文件。显然,当res/目录下的
any
文件发生变化时,需要执行这条规则。因此,我希望该规则将该目录下的所有文件作为先决条件。我该如何实施这个规则?

在 Bash 中启用

globstar
选项,您可以使用通配符模式
res/**/*
获取该目录中所有文件的列表。然而,如果你在 Makefile 中指定它作为先决条件,它似乎不起作用:

filename.jar: res/**/*

即使在

touch
中创建文件后
res/
,仍然可以生成报告

make: `filename.jar' is up to date.

很明显它没有识别出该模式。

如果我将目录本身声明为先决条件:

filename.jar: res

那么当文件被修改时,Make将不会重新执行(我认为

make
只查看目录本身的修改日期,只有在添加、删除或重命名直接子级时才会更改)。

makefile wildcard gnu-make glob
2个回答
89
投票

这个:

filename.jar: $(wildcard res/**/*)

似乎有效,至少在某些平台上。

编辑:

或者更好,直接解开这个结:

filename.jar: $(shell find res -type f)

0
投票

之前的答案不正确。您不能使用双 glob

**
并期望它递归。遵循这个规则:

filename.jar: $(wildcard res/**/*.java) # does not work as expected

该行实际上与此行的行为相同:

filename.jar: $(wildcard res/*/*.java)

它将匹配

res/foo/bar.java
,但不会匹配
res/foo/bar/example.java

感谢名为 “2023 年 6 月辞职”的用户指点

**
实际上并不能递归地工作。
wildcard
的手册页清楚地表明,唯一支持的魔术字符是
*
(不是
**
)、
?
[
]

相反,您可以结合使用

shell
函数
find
命令
。这样做的困难在于它不能很好地处理带有空格或换行符的文件名。这是一个根据需要转义空格的解决方案,但不处理文件名中的换行符:

filename.jar: $(shell find res -name '*.java' | sed 's@ @\\ @g')
© www.soinside.com 2019 - 2024. All rights reserved.