将目标并行委托给其他 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 foo
用a b c
调用,如果我make bar
用d e f
调用,用a b c d e f
如果我 make foo bar
?
我不能使用 include
,因为 Makefile.other
是由我使用的工具自动生成的,它本身包含生成的文件,并使 clean
目标太慢。我试过 T +=
而不是 T =
,并使 foo
和 bar
依赖于具有规则的单独目标,但是 T
是规则本地的,因此另一个目标只能看到其中一个目标的信息。
不,你不能只用目标 foo
和 bar
做你想做的事。
你要求 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 foo
make bar
和make 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 时,总是 运行 目标 foo
和 bar
,所以它总是 运行 $(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,但所有后续时间该变量都是空的,所以它什么都不做。
它不是很漂亮,我不太确定它会做你真正想要的,但它会做你要求的。
假设我有一个 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 foo
用a b c
调用,如果我make bar
用d e f
调用,用a b c d e f
如果我 make foo bar
?
我不能使用 include
,因为 Makefile.other
是由我使用的工具自动生成的,它本身包含生成的文件,并使 clean
目标太慢。我试过 T +=
而不是 T =
,并使 foo
和 bar
依赖于具有规则的单独目标,但是 T
是规则本地的,因此另一个目标只能看到其中一个目标的信息。
不,你不能只用目标 foo
和 bar
做你想做的事。
你要求 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 foo
make bar
和make 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 时,总是 运行 目标 foo
和 bar
,所以它总是 运行 $(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,但所有后续时间该变量都是空的,所以它什么都不做。
它不是很漂亮,我不太确定它会做你真正想要的,但它会做你要求的。