如何处理GNU make中的子make错误?

3

我在我的Makefile(GNU)中使用了子make。但每当子make失败时,主make都会继续运行并成功完成。我希望只要子make失败,主Makefile就失败。我该怎么做?

all:   
    pushd ${STA_DIR};make clean;make ARGS=${A1},${A2};popd

每当在STA_DIR中进行编译失败时,主要的编译过程并不会停止。我希望能够使主要的编译过程停止。
1个回答

10
由于您没有提供有关规则的任何详细信息,我们无法回答这个问题。当make执行程序时,无论是编译器、链接器、文档格式化器还是其他make实例,它都以相同的方式工作: 如果退出代码为0,这在UNIX中表示“成功”,那么make将继续下一个规则。如果退出代码是非0,这在UNIX中表示“失败”,那么make将停止(除非您使用了-k选项)。
只有当make尝试构建的所有目标都成功时,make程序本身才会退出0
因此,如果正确编写,你的make将会在子make失败时停止。如果没有停止,则调用子make的规则正在丢失退出代码,这就是父make没有失败的原因。如果您提供了您的规则,我们可以告诉您如何修复它。
基于我的经验,我建议您可能有一个类似这样运行子make的规则:
SUBDIRS = foo bar biz

all:
        for d in $(SUBDIRS); do $(MAKE) -C $$d; done

.PHONY: all

这里你没有检查每个子make的退出代码,所以它不会停止。 从shell发送回make的只有最后一个命令的最终退出代码。 如果是这样的话,你应该像这样重新编写你的 makefile:

SUBDIRS = foo bar biz

all: $(SUBDIRS)

$(SUBDIRS):
        $(MAKE) -C $@

.PHONY: all $(SUBDIRS)

编辑

根据您的makefile和上述内容,您可以看到问题所在:脚本中的最后一个命令是popd,它不会失败,因此命令的退出代码是成功的。请注意,在这里您不需要使用pushdpopd(至少在UNIX系统上不需要),因为每个命令都在单独的shell中运行,当shell退出时,工作目录会被重置。

您需要像这样:

all:
        cd "${STA_DIR}" && ${MAKE} clean && ${MAKE} ARGS="${A1},${A2}"
&& 运算符是一个短路测试成功的操作符;如果其中任何一个命令失败,则整个命令将立即失败。
此外,请记住在调用递归 make 时始终使用 $(MAKE)${MAKE}(它们是相同的),不要使用静态的 make

明白了,谢谢。我刚刚在我的原始帖子中添加了实际的Makefile以供参考。 - user1293997
太好了。我会对我的制作进行必要的更改。非常感谢!! - user1293997
在递归调用中,使用${MAKE}make有什么区别呢? - sta
3
请参见 https://www.gnu.org/software/make/manual/html_node/MAKE-Variable.html 。实际上还有其他更好的理由。如果您想了解,请提出一个新问题:在与主题无关的答案评论中不合适。 - MadScientist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接