让make停止多目录构建中的第一个错误

时间:2017-11-01 02:39:35

标签: makefile compilation

我们的项目为每个多目录子制作使用具有以下类型规则的Makefile:

DIRS = lib audio conf parser control
all: $(DIRS)
        @for DIR in $(DIRS); \
        do \
          ( cd $$DIR; $(MAKE) $(MFLAGS) all; ) \
        done

如果任何文件无法在其中一个leaf make中编译,则构建将停止在该目录中 - 但其余的make仍在继续。如何设置这些Makefile,以便任何级别的第一个错误都会停止整个make?

由于

2 个答案:

答案 0 :(得分:1)

来自bash手册的for循环部分:

  

返回状态是最后一个命令的退出状态   执行。

因此,您无需捕获返回状态。如果任何子品牌失败,您需要配方失败:

DIRS = lib audio conf parser control
all: $(DIRS)
    @for DIR in $(DIRS); do \
        $(MAKE) -C $$DIR $(MFLAGS) all || exit 1; \
    done

但是,为每个目录设置单独的配方会更好,而不是单个for循环:

DIRS = lib audio conf parser control

all: $(DIRS)

.PHONY: all $(DIRS)

$(DIRS):
    $(MAKE) -C $@ $(MFLAGS) all

这样,如果子制作失败,则完整规则的配方会失败并停止。请注意.PHONY特殊目标,在这种情况下需要它,因为您希望运行配方,即使该目录已存在。

此结构还有另一个优点:如果以并行模式运行make(make -j N),它将同时启动多个子制作,而不是仅使用for循环制作一个子制作。反过来,每个子品牌将并行启动多个配方,最多可达N个工作。在多处理器或多核架构上,加速因子可能非常重要。

但是,如果您的项目不是并行安全的,也就是说,如果您的目录处理顺序很重要并且未在makefile中正确定义,则此优势可能会成为一个缺点。如果您遇到这种情况,可以添加:

.NOTPARALLEL:

主makefile开头的特殊目标告诉make。但是明确定义目录间依赖关系会更好。如果你不知道怎么做,请问另一个问题。

答案 1 :(得分:0)

我在this question's answer中找到答案:我必须重写以捕获每个子制作的返回状态。