在所有子目录中递归构建相同目标的最简单方法是什么?

问题描述

我有一个包含多个组件和子组件的项目。我想要顶部目录中的make命令转到子目录并为给定目标运行子项make。我知道我可以写很多单独的sh命令,每个命令由cd和随后的make调用组成,但是我感觉必须有一种更简单甚至更自动的方式。

我该怎么做?

解决方法

一个更好的解决方案是使用make的自然功能来运行许多命令,而根本不使用shell循环。

如果您不想直接在您的makefile中列出子目录(我个人总是手动列出它们:比较安全,也没什么大不了的,因为新目录不会一直出现),然后找到您可以使用带有makefile的所有直接子目录:

SUBDIRS := $(patsubst %/Makefile,%,$(wildcard */Makefile))

现在找出用户要求的目标。如果他们不要求提供,我们将使用all作为默认目标(当然,您可以更改此目标):

GOALS := $(or $(MAKECMDGOALS),all)

然后创建依赖于所有子目录的目标,并为每个子目录运行与在命令行中指定的目标相同的目标:

.PHONY: $(GOALS) $(SUBDIRS)
$(GOALS): $(SUBDIRS)
$(SUBDIRS):
        $(MAKE) -C $@ $(MAKECMDGOALS)

注意,这显然仅适用于GNU make。

,

以下代码将查找包含名为Makefile的文件的所有子目录,并在其中运行具有相同目标的make

SubMakefiles只是一个文件查找,将返回类似./Makefile foo/Makefile bar/Makefile的内容。由此,dir命令留下了./ foo/ bar/,而filter-out则删除了./。这给了我们一个列表,我们可以使用解释sh命令的make处理器轻松地进行迭代。最后,如果返回错误错误,我们自己将使用|| exit $$?返回相同的错误。

请注意,这将无法与-k-j的make选项一起正常使用,因为所有子make都是从单个配方调用的。

# Make the same target in all subdirectories with a Makefile.
SubMakefiles    = $(shell find -L . -maxdepth 2 -type f -name Makefile)
SubMakeDirs     = $(filter-out ./,$(dir $(SubMakefiles)))

clean depend all::
        @for dir in $(SubMakeDirs); do \
            $(MAKE) -C $$dir $@ || exit $$?; \
        done