上面第一个答案中给出的 for 循环解决方案实际上不应该按原样使用。在这种方法中,如果您的子版本之一失败,构建将不会失败(应该如此),而是继续使用其他目录。不仅如此,构建的最终结果将是最后一个子目录 make 的退出代码,因此如果成功,即使其他子目录失败,构建也会成功。不好!!
您可以通过执行以下操作来修复它:
all:
@for dir in $(SUBDIRS); \
do \
$(MAKE) -C $${dir} $@ || exit $$?; \
done
然而现在你遇到了相反的问题:如果你运行“make -k”(即使有错误也继续)那么在这种情况下将不会遵守。失败时它仍然会退出。
上述两种方法的另一个问题是它们会序列化所有子目录的构建,因此如果您启用并行构建(使用 make 的 -j 选项),则只会在单个子目录中发生,而不是在所有子目录中发生。
Eregrith 和 sinsedrix 的解决方案更接近您想要的,但仅供参考,当您调用递归 make 调用时,您永远不应该使用“make”。正如 johfel 的示例所示,您应该始终使用 $(MAKE)。
像这样的东西就是你想要的:
SUBDIRS = subdir1 subdir1 subdir3 ...
all: $(addprefix all.,$(SUBDIRS))
all.%:
@ $(MAKE) -C '$*' '$(basename $@)'
.PHONY: $(addprefix all.,$(SUBDIRS))
当然,您可以为其他目标添加更多这样的节,例如“安装”或其他目标。还有更奇特的方法来处理具有任何通用目标的构建子目录,但这需要更多细节。
如果您想支持并行构建,您可能需要在此级别声明依赖关系,以避免并行构建相互依赖的目录。例如,在上面,如果在 subdir1 和 subdir2 都完成之前无法构建 subdir3 (但 subdir1 和 subdir2 可以并行构建),那么你可以在 makefile 中添加如下内容:
all.subdir3 : all.subdir1 all.subdir2