2

这是我的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. 

我可以在makefile之外为每个目录单独调用“make -C <path>”,但它在foreach调用中不起作用。我已经尝试过了,但它也不起作用:

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

有任何想法吗?

4

1 回答 1

10

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

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

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

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

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

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

impl/thing2: impl/thing1

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

要添加替代规则,例如 for 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

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

于 2013-03-27T16:32:40.280 回答