合并 "terminal pattern rule" 与 "static pattern rule"

Combine "terminal pattern rule" with "static pattern rule"

我想要一个可以一个一个安装文件,也可以一个一个卸载的Makefile。

仅当源文件比目标文件更新时,文件的安装规则才应该运行。

只有当文件存在于系统中时,文件的卸载规则才应该运行。

现在我有:

SRC_FILES = ...
sys_files = ...

$(sys_files): $(DESTDIR)$(systemdir)/%: $(SRCDIR)/%
    @echo ' INSTALL $@';
    $(INSTALL_DATA) -T '$(SRCDIR)/$*' '$@';

uninstall_sys_files = $(addprefix uninstall-,$(sys_files))

$(unsinstall_sys_files): uninstall-%:
    @echo ' RM  $*';
    $(RM) '$*';

上面代码的问题是它 运行 是卸载 (RM) 目标,即使文件不存在,(我可以接受,但我宁愿不打印 RM未删除文件的消息。是的,我可以有条件地做到这一点,但只有当 make 不能用“静态终端模式规则”处理这个问题时我才会这样做?)。

所以,有没有类似的东西?:

$(unsinstall_sys_files):: uninstall-%: %
    @echo ' RM  $*';
    $(RM) '$*';

这将使该规则终止并取决于 %.

的存在

根据我的测试,这就像双冒号是一个冒号一样。


编辑:

虽然这看起来不错,但事实并非如此,因为如果规则失败(因为文件不存在),那么整个 make 都会失败,或者您需要忽略卸载部分中的错误,这我不是很满意。

我不太确定您希望通过标记规则终端获得的优势...除非我遗漏了一些与您想要做的事情似乎没有太大关系的东西。

你的最后一个问题(“规则失败,因为文件不存在”),我理解你的意思是卸载配方失败,很容易解决:只需设置 RM = rm -f 以便rm 如果文件不存在也不会失败。

如果你能举例说明你真正想做的事情就太好了;您希望如何调用 make 以及您希望它如何运行(结果操作)。

Make 旨在更新 文件,而不是删除文件。也就是说,它的整个目标是找到不存在或过时的文件,并使它们存在/更新它们。

但是,您可以这样做:

RM := rm -f

sys_exists := $(wildcard $(addprefix $(DESTDIR)$(systemdir)/,$(sys_files)))

uninstall: $(patsubst $(DESTDIR)$(systemdir)/%,uninstall-%,$(sys_exists)))

uninstall-%:
        @echo ' RM  $*'
        $(RM) '$(DESTDIR)$(systemdir)/$*'

这样uninstall只会删除实际存在的文件。