makefile:foreach“make -C”调用

时间:2013-03-27 14:54:42

标签: ubuntu makefile gnu-make

这是我的makefile的一部分:

PATH := $(shell pwd)
EDIR := impl
EFFECTS := $(filter-out $(EDIR), $(shell find $(EDIR) -maxdepth 1 -type d))
ALLMAKES := $(patsubst %, $(PATH)/%, $(EFFECTS))


all:
      $(foreach c,$(ALLMAKES),$(MAKE) -C $(c))

基本上,我想为“impl”目录中的所有目录调用make而不使用“impl”本身。我知道make会记住上次使用-C参数调用时的最后一个目录,这就是我每次都给出绝对路径的原因。是什么让回声看起来像我想要的那样:

make -C <projectdir>/impl/thing1 make -C <projectdir>/impl/thing2 make -C <projectdir>/impl/thing3

问题是make无法完成命令并只是打印:

make: make: Command not found. 

我可以调用“make -C&lt; path&gt;”对于makefile外部的每个目录,但它在foreach调用中不起作用。我试过这个,但它也不起作用:

$(foreach c,$(ALLMAKES),$(shell make -C $(c)))

有什么想法吗?

1 个答案:

答案 0 :(得分:8)

那是因为您正在调用单个make,其中包含许多参数,包括后续的make命令。您需要在make的调用之间添加一个shell命令分隔符。这样的事情会起作用:

all:
        $(foreach c,$(ALLMAKES),$(MAKE) -C $(c) && ) true

第二,你的makefile还有其他问题。您不应该设置名为PATH的make变量,因为这将覆盖子shell的$PATH变量。您可以使用make内置变量$(CURDIR)而不是运行$(shell pwd)。实际上你根本不需要在目录前添加路径,因为运行$(MAKE) -C ...不会改变 shell的工作目录,只需要make,而当make退出时它将被设置回来,所以你可以使用相对路径。

在循环中调用子make也有一些问题。首先,您可以减少可以获得的并行化数量。其次,-k选项无法得到适当的支持(没有很多不愉快的努力)。处理此问题的更好方法是利用make已经知道如何构建大量目标的事实:

all: $(EFFECTS)
$(EFFECTS):
        $(MAKE) -C $@
.PHONY: all $(EFFECTS)

如果不同子目录之间存在特定的排序问题,您也可以定义它们:

impl/thing2: impl/thing1

等。这确保了最大的并行化机会,同时仍然保留了重要的排序。

要为clean添加替代规则,您可以执行以下操作:

CLEAN_EFFECTS := $(addsuffix .clean,$(EFFECTS))
clean: $(CLEAN_EFFECTS)
$(CLEAN_EFFECTS):
        $(MAKE) -C $(basename $@) clean
.PHONY: clean $(CLEAN_EFFECTS)

这很好,因为您还可以通过运行make impl/thing1来构建单个子目录(及其所有先决条件)。或者通过运行make impl/thing1.clean

来清理它们

如果您有更多这些,您也可以使用模式规则等,以避免对每种类型的目标重复此操作。它变得更加麻烦。