在Makefile中删除具有配方的目标失败

在Makefile中删除具有配方的目标失败,makefile,Makefile,我试图在makefile中使用.DELETE\ON\u ERROR目标来删除这两个$(OBJ) 和可执行文件如果配方失败,但不起作用。如果我在编译模式规则时将错误放在任何对象文件中,则会发生错误并停止。旧的对象文件仍然在它的位置上,但我希望。DELETE\u on\u ERROR将其删除 有人能测试代码吗?-是否可以包含$(DEP)或标记-DDBG影响?目标是删除失败的.o文件和可执行文件 OUTPUT = executable CPP := $(shell find $(SRC) -type

我试图在makefile中使用
.DELETE\ON\u ERROR
目标来删除这两个
$(OBJ)
可执行文件
如果配方失败,但不起作用。如果我在编译模式规则时将错误放在任何对象文件中,则会发生错误并停止。旧的对象文件仍然在它的位置上,但我希望
。DELETE\u on\u ERROR
将其删除

有人能测试代码吗?
-是否可以包含$(DEP)
或标记
-DDBG
影响?目标是删除失败的
.o
文件和
可执行文件

OUTPUT = executable
CPP := $(shell find $(SRC) -type f -name "*.cpp")
OBJ := $(CPP:.cpp=.o)
DEP := $(OBJ:.o=.d)

CXX := g++
CXXFLAGS =-MMD -MP -DDBG
INCLUDES = -I.

.DELETE_ON_ERROR :

$(OUTPUT): $(OBJ)
    $(CXX) $^ -o $@

%.o: %.cpp
    $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@

-include $(DEP)

.PHONY : clean
clean:
    rm -rf $(OBJ) $(DEP) 

我不确定你看到了什么样的失败,但我担心你真的没有一个好的方法来做到这一点
.o
文件和可执行文件(
$(输出)
)是独立的规则。如果后者失败,则前者已被排除在考虑之外。见:

。删除错误:
如果
.DELETE\u ON\u ERROR
在makefile中的任何位置被称为目标,则
make
将删除规则的目标,前提是该规则已更改且其配方以非零退出状态退出,就像它接收到信号时一样。看

换句话说,如果您的目标在
.o
目标本身更新后生成二进制对象失败,make将删除更改的文件。但如果您的可执行文件没有链接,它将不会返回并删除对象文件

不确定这是否好,但如果您真的需要,您可能可以通过重构您的makefile来实现这一点,使其基本上具有来自源代码先决条件规则的direct exec+objs,只需一个配方。明显的缺点是,这样的规则意味着单个
.c
文件更改会导致所有文件被重新编译(基本上否定了使用
make
的实质好处)


编辑:我将对评论进行进一步的阐述以澄清。您似乎想要的是:如果有一个损坏的
.c
文件并且编译失败,请删除旧的
.o
文件。这显然不是
.DELETE\u ON\u ERROR
的工作原理。如果
.o
文件已经更新,然后规则失败,它将删除它(“如果规则的目标已更改,则删除该目标”),但如果出现上述语法问题,编译器将在生成
.o
文件之前失败


因此,例如,如果您更新了编译的(模式)规则,使其首先
触摸
.o
文件上的es(有效更新时间戳),然后尝试编译。编译器调用和规则失败后,会考虑更新失败根的目标并将其删除。或者,您也可以更改为规则,首先尝试
rm
预期的.o'文件,在这种情况下,您实际上不需要使用
.DELETE\u ON\u ERROR
(如果相关源中没有更改,则不会使用该规则,因此它实际上没有听起来那么糟糕)。这两种方法都不是很干净,但会导致您描述的行为。

编写输出文件时,编译器可能会崩溃。在这种情况下,存在比其源更新的损坏输出文件。Make将由于错误而停止,但在下一次运行时,它不会重新编译输出文件,因为它比ist源文件更新,并且Make将在构建步骤中一次又一次失败。
使用.DELETE_ON_错误规则,如果编译器(或任何构建步骤失败)在接触(并损坏)输出文件后出现错误而退出,make将删除输出文件,因此它将在下次运行时重新编译。(如果编译器在未接触旧输出文件的情况下失败,那么它将始终在下次运行时重新编译)

失败的原因是我破坏了任何对象文件,而不是在模式规则中编译期间发生语法错误,因此,如果我使用
.DELETE\u ON\u ERROR
我希望删除旧的.o文件,在编译
可执行文件
后,它会发现缺少一个
.o
文件,make也会删除
可执行文件
。现在,在出错后停止,
.o
文件仍然在oits位置。实际上,这根本不会发生。因为您的规则是简单的编译步骤,并且更新目标时出现语法错误,所以它不满足“如果规则的目标已更改,则删除规则的目标”。编译器在创建新的.o文件之前会失败,而旧的文件保持不变。好的,那么如果我们忘记了
可执行文件
,它应该与
%一起工作吗。o:%.cpp
?根据您的回答,我在编译器之前将
@touch@
添加到模式规则中,现在它可以正常工作了。谢谢)。我已经了解了您所谈论的内容,现在这一部分很清楚“如果规则的目标发生了变化,请删除它”。但你能解释一下为什么会这样吗。为什么目标必须更新?为什么它不能仅仅与退出代码相关?谢谢。可以说我不在房间里。:)因此,除了能够观察并将行为与文档联系起来,我只能猜测动机是什么。我认为这可能与假设有关(特别是在计算成本更高的那一天),如果失败没有产生任何变化,失败没有损坏您的目标/结果,您可能希望保留它(供进一步使用)?但是,如果把它与一个巨大的盐粒,我其实并不真的知道,正如所说的,我只是猜测。
%.o: %.cpp
    @touch $@
    $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@