问题描述
我有一个包含多个组件和子组件的项目。我想要顶部目录中的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