Makefile GNU强制删除中间文件

Makefile GNU强制删除中间文件,makefile,Makefile,我有一个编译器,它从.ec文件生成.c文件作为中间步骤。编译器不会删除.c文件。不能要求编译器跳过调用$CC以生成.o文件。我试图让GNUMake(3.81)将生成的.c文件作为中间文件处理并清理它们。下面是一个单独的示例,它使用没有隐含规则的文件扩展名再现了错误行为 .INTERMEDIATE: %.delme %.o: %.ec cp $< $(<:.ec=.delme) cp $(<:.ec=.delme) $@ all: test.o

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

.INTERMEDIATE: %.delme

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

all: test.o

<>制作只能考虑使目标居中。您不能只是将文件系统上的随机文件声明为中间文件,然后让您删除它

这里创建的
.delme
文件是构建
.o
文件的配方的副作用;make对此一无所知,因此make不会删除它,因为makefile中没有中间目标

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

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

<>制作只能考虑使目标居中。您不能只是将文件系统上的随机文件声明为中间文件,然后让您删除它

这里创建的
.delme
文件是构建
.o
文件的配方的副作用;make对此一无所知,因此make不会删除它,因为makefile中没有中间目标

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

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

尝试使用模式规则告诉您的编译器从.ec源代码生成.o和.c文件。然后将所有c文件声明为中间文件。具有多个输出的模式规则与非模式规则的工作方式不同。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)

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

尝试使用模式规则告诉它们,让编译器从.ec源生成.o和.c文件。然后将所有c文件声明为中间文件。具有多个输出的模式规则与非模式规则的工作方式不同。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)

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

感谢您的精彩解释!我的新方法是对副作用文件执行rm-f。您是否可以更新该示例以显示即使命令失败如何删除它?我想不出来了。更新了答案。非常感谢!我仍在掌握make如何调用shell命令,所以这并不明显。我真的很感谢你花时间来阐述这个问题的答案。谢谢你的精彩解释!我的新方法是对副作用文件执行rm-f。您是否可以更新该示例以显示即使命令失败如何删除它?我想不出来了。更新了答案。非常感谢!我仍在掌握make如何调用shell命令,所以这并不明显。我真的很感谢你花时间来扩展我的答案。这对我的简单cp示例有效,但对我必须使用的交叉编译器无效。我不太清楚为什么。针对我的特殊情况,我选择了rm解决方案,但我认为这是一种更为惯用的解决方案。这就是为什么我把它作为公认的答案。这适用于我的简单cp示例,但不适用于我必须使用的交叉编译器。我不太清楚为什么。针对我的特殊情况,我选择了rm解决方案,但我认为这是一种更为惯用的解决方案。这就是为什么我把这个作为公认的答案。
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)
$ 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