我有一个编译器,它从.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
答案 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没有重建。