GNU强制删除中间文件

时间:2016-12-08 13:41:23

标签: makefile

我有一个编译器,它从.ec文件生成.c文件作为中间步骤。编译器不会删除.c文件。不能要求编译器跳过调用$ CC来生成.o文件。我试图让GNU make(3.81)将生成的.c文件视为中间文件并清理它们。以下是一个独立的示例,它使用没有隐含规则的文件扩展名重现错误行为。

.INTERMEDIATE: %.delme

%.o: %.ec
        cp $< $(<:.ec=.delme)
        cp $(<:.ec=.delme) $@

all: test.o

执行测试用例:

rm -f test.*
touch test.ec
make
if [[ -e test.delme ]]; then echo "Failure"; else echo "Success"; fi

2 个答案:

答案 0 :(得分:1)

Make只能考虑使目标成为中间人。您不能仅仅将文件系统上的随机文件声明为中间文件,并为您删除它。

此处.delme文件创建为构建.o文件的配方的副作用; make并不知道任何事情,所以make不会删除它,因为makefile中没有中间的目标。

在您的示例中,您可以将两个cp命令拆分为单独的规则,这样可以使中间设置起作用:

%.delme : %.ec
        cp $< $@
%.o : %.delme
        cp $< $@

我假设在您的真实环境中您无法做到这一点,因为它是生成中间文件和真实文件的所有命令。在这种情况下,您必须自己处理配方中的删除:

%.o : %.ec
        cp $< $(<:.ec=.delme)
        cp $(<:.ec=.delme) $@ && rm -f $(<:.ec=.delme)

注意,如果.delme命令失败,则会保留cp文件;如果你想删除它,无论你能做什么。

修改

要删除中间文件,即使命令失败,您也必须保留退出代码,以便告诉make它是什么。类似的东西:

%.o : %.ec
        cp $< $(<:.ec=.delme)
        cp $(<:.ec=.delme) $@; e=$$?; rm -f $(<:.ec=.delme); exit $$e

答案 1 :(得分:1)

尝试使用模式规则告诉make你的编译器从.ec源生成.o和.c文件。然后将所有c文件声明为INTERMEDIATE。具有多个输出的模式规则与非模式规则的工作方式不同。 Make将仅运行模式规则一次以从规则生成所有输出文件,而静态规则将针对每个输出文件运行。另请注意,模式规则将生成所有输出文件,即使它只需要其中一个作为目标。

结果是这样的:

SRC := foo.ec bar.ec
OBJS := $(SRC:.ec=.o)

all: program

program: $(OBJS)
        cat $^ > $@

%.o %.c: %.ec
        cp $< $(<:.ec=.c) ; cp $< $(<:.ec=.o)

.INTERMEDIATE: $(SRC:.ec=.c)

从.ec生成.c和.o的命令将运行一次以生成这两个文件。因为make知道它创建了.c(即使它只需要.o),它就足以知道删除它了。 .INTERMEDIATE目标仅在明确列出文件而不使用模式时才有效,因此我们没有使用%.c。无论如何,这似乎是一个坏主意,如果你有一个.ec文件产生的C源并为你删除它会怎么样?示例输出:

$ make
cp foo.ec foo.c ; cp foo.ec foo.o
cp bar.ec bar.c ; cp bar.ec bar.o
cat foo.o bar.o > program
rm bar.c foo.c

$ touch foo.ec ; make
cp foo.ec foo.c ; cp foo.ec foo.o
cat foo.o bar.o > program
rm foo.c

请注意,在第二次调用时,它只删除了foo.c,因为bar.o / c没有重建。