如果文件存在,如何编写Makefile规则来删除文件(干净)?

Ale*_*xey 6 makefile

在我看来,像Makefile规则可以大致分为"正面"和"负面"规则:"正面"规则创建缺失或更新过时文件,而"负面"规则删除文件.

编写"肯定"规则的先决条件非常简单:如果目标和先决条件是文件名,make默认情况下,如果目标丢失或过时,则运行配方(此上下文中的丢失文件可能被视为无限旧文件).

但是,请考虑"负面"规则,例如针对目标clean.写它的通常方法似乎是这样的:

clean:
    rm -f *.log *.synctex.gz *.aux *.out *.toc
Run Code Online (Sandbox Code Playgroud)

这显然不是最好的方法:

  1. rm 即使没有任何事情可以执行,

  2. 需要使用-f标志来抑制其错误消息和退出状态,标志具有其他(可能不合需要的)效果,并且

  3. clean与"正面"目标的正常情况不同,不会向用户报告无关目标的事实.

我的问题是:如何编写一个Makefile规则,make只有在某些文件存在的情况下才能处理它?(就像那些有用的东西make clean.)

Mik*_*han 6

如何编写仅在某些文件存在时才应由 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.


l0b*_*0b0 3

这可以很容易地解决:

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在打印奇怪的文件名时避免终端可能的损坏。