Make:动态文件递归?

Make: dynamic file recursion?

假设我有以下目录结构,其中有一个根节点:


/root/
  Makefile
  branch1/
  branch2/
  .../

然后我编写了以下最小的 makefile:

branches=$(shell find * -maxdepth 1 -type d -printf "%f "}

%:
    -${MAKE} ${MAKECMDGOALS} -C branch1
    -${MAKE} ${MAKECMDGOALS} -C branch2
    ...

准备使用 branches 变量动态执行此中继并尝试了几种通配符和后代规则变体但没有成功,我的问题是:我如何捕获 any 来自外部范围的命令目标(就像我现在正在做的那样),并为我的 find 表达式检测到的每个文件执行生成中继?

在伪代码中(不适用于我的 make 版本,它是 Cygwin 上最新可用的最佳版本):

branches=$(shell find * -maxdepth 1 -type d -printf "%f "}

branch-%:
    -${MAKE} ${MAKECMDGOALS} -C $*

%: ${foreach branch,${branches}, branch-${branch}}

与原始 makefile 不同,这不起作用。但是,似乎应该如此。有办法吗?

还有第二个问题

Make 的并行性将被我使用 -j 选项的指数扇出的伪代码方法(如果有效)破坏,而我使用的第一种方法不会破坏并行性。

然而,理想情况下,此生成文件应该能够为分支列表中的每个文件动态执行一个生成中继。但是,我目前看不到动态实现它的方法。

首先,我不确定您为什么要使用复杂的 shell 函数;为什么不只是:

branches := $(wildcard */.)

或者,如果您不想要结尾的 /.

branches := $(patsubst %/.,%,$(wildcard */.))

其次,您第二次尝试失败的原因是创建没有配方的模式规则无效。参见 Canceling Pattern Rules

相反,您可以使用 .DEFAULT 特殊目标。它看起来像这样:

branch-%:
        -${MAKE} -C $* $(CMD)

.DEFAULT:
        @$(MAKE) CMD=$@ ${addprefix branch-,${branches}}

这确实使用了递归 make,它的行为与原来的略有不同。

我不确定我是否理解你关于 -j 的第二点。 GNU make(除非您使用的是真正的旧版本)可以在所有 submake 之间进行通信,以确保它们启动的作业数量与您请求的数量一样多,但不会更多。

哦,我忘了,如果你不想使用 .DEFAULT 和递归,还有另一种显而易见的方法:

$(MAKECMDGOALS): $(addprefix branch-,$branches))