在我看来,像Makefile规则可以大致分为"正面"和"负面"规则:"正面"规则创建缺失或更新过时文件,而"负面"规则删除文件.
编写"肯定"规则的先决条件非常简单:如果目标和先决条件是文件名,make默认情况下,如果目标丢失或过时,则运行配方(此上下文中的丢失文件可能被视为无限旧文件).
但是,请考虑"负面"规则,例如针对目标clean.写它的通常方法似乎是这样的:
clean:
rm -f *.log *.synctex.gz *.aux *.out *.toc
Run Code Online (Sandbox Code Playgroud)
这显然不是最好的方法:
rm 即使没有任何事情可以执行,
需要使用-f标志来抑制其错误消息和退出状态,标志具有其他(可能不合需要的)效果,并且
clean与"正面"目标的正常情况不同,不会向用户报告无关目标的事实.
我的问题是:如何编写一个Makefile规则,make只有在某些文件存在的情况下才能处理它?(就像那些有用的东西make clean.)
如何编写仅在某些文件存在时才应由 make 处理的 Makefile 规则?(比如什么对 make clean 有用。)
你可以这样做:
filenames := a b c
files := $(strip $(foreach f,$(filenames),$(wildcard $(f))))
all: $(filenames)
$(filenames):
touch $@
clean:
ifneq ($(files),)
rm -f $(files)
endif
Run Code Online (Sandbox Code Playgroud)
示例会话:
$ make
touch a
touch b
touch c
$ make clean
rm -f a b c
$ make clean
make: Nothing to be done for 'clean'.
Run Code Online (Sandbox Code Playgroud)
也许对某些目的有用,但我觉得它是对make clean.
这可以很容易地解决:
clean:
for file in *.log *.synctex.gz *.aux *.out *.toc; do \
if [ -e "$file" ]; then \
rm "$$file" || exit 1; \
else \
printf 'No such file: %s\n' "$file" \
fi \
done
Run Code Online (Sandbox Code Playgroud)
该if声明是必要的,除非您的 shell 支持并已启用nullglob或类似的东西。
如果您printf支持,%q您应该使用它,而不是%s在打印奇怪的文件名时避免终端可能的损坏。