将目标并行委托给其他 make 文件,不包含

Delegating targets to other make files, in parallel, without include

假设我有一个 Makefile:

foo: T = a b c
bar: T = d e f

foo bar:
        $(MAKE) -f Makefile.other $(T)

如果 Makefile.other 对 a b c 和 d e f 之间的依赖信息进行编码,这在 make -j foo bar 上是错误的。有没有办法让它做 "right" 的事情?也就是说,在所有情况下,只执行一次$(MAKE) -f ...,如果我make fooa b c调用,如果我make bard e f调用,用a b c d e f 如果我 make foo bar?

我不能使用 include,因为 Makefile.other 是由我使用的工具自动生成的,它本身包含生成的文件,并使 clean 目标太慢。我试过 T += 而不是 T =,并使 foobar 依赖于具有规则的单独目标,但是 T 是规则本地的,因此另一个目标只能看到其中一个目标的信息。

不,你不能只用目标 foobar 做你想做的事。

你要求 make foo bar 做一些不同于 make foo 和 make bar.

规则:

foo bar:
        $(MAKE) -f Makefile.other $(T)

只是 shorthand 用于:

foo :
    $(MAKE) -f Makefile.other $(T)

bar:
    $(MAKE) -f Makefile.other $(T)

所以,为了说明,如果 Makefile.other 是:

.phony: a b c d e f

a b c d e f:
    @echo $@

那么make foo bar不会有任何结果但是:

$ make foo bar
make -f Makefile.other a b c
make[1]: Entering directory `/home/imk/develop/SO/scrap'
a
b
c
make[1]: Leaving directory `/home/imk/develop/SO/scrap'
make -f Makefile.other d e f
make[1]: Entering directory `/home/imk/develop/SO/scrap'
d
e
f
make[1]: Leaving directory `/home/imk/develop/SO/scrap'

make 根据订单制作 foo,然后制作 bar。这个"the right thing".

如果你想制作a b c d e f,那么你必须定义一个 第三个 make 需要全部完成的目标。例如:

foo_todo = a b c
bar_todo = d e f
foobar_todo = $(foo_todo) $(bar_todo)

foo bar foobar:
    $(MAKE) -f Makefile.other $($@_todo)

然后make foomake barmake foo bar都和以前一样, make foobar 输出:

make -f Makefile.other a b c d e f
make[1]: Entering directory `/home/imk/develop/SO/scrap'
a
b
c
d
e
f

当你 运行 make foo bar make 时,总是 运行 目标 foobar,所以它总是 运行 $(MAKE) ... 食谱两次:一次用于 foo,一次用于 bar。当你 运行 make foo bar.

时,你不能 运行 只有一个食谱

因此,我可以告诉您如何根据正在构建的目标将 T 设置为正确的值,但这无济于事,因为子 make 总是 运行 两次而不管。 那是棘手的部分。

如果你真的非常想这样做,你可以这样做:

SUBMAKE = $(MAKE) -f Makefile.other $(T)

T :=
ifeq ($(filter foo,$(MAKECMDGOALS)),foo)
    T += a b c
endif
ifeq ($(filter bar,$(MAKECMDGOALS)),bar)
    T += d e f
endif

foo bar:
        +$(SUBMAKE)$(eval SUBMAKE :=)

这是做什么的?首先,它根据命令行上的值(存储在 MAKECMDGOALS.

中计算 T

其次,在配方中它首先扩展到SUBMAKE的值,然后使用eval函数将SUBMAKE设置为空。这意味着这个配方第一次 运行 它将调用 submake,但所有后续时间该变量都是空的,所以它什么都不做。

它不是很漂亮,我不太确定它会做你真正想要的,但它会做你要求的。