我有一个可以创建多个目标的顶级Makefile,我有一个for循环。在这个文件中,我试图读取一个文本文件,其版本号仅在子makefile运行时创建。我有它工作,但它看起来非常难看,所以我认为可能有更好的方法来做到这一点。这是顶级Makefile:
T1=_release
T2=_debug
T3=_test
all: bin/mybin_release.bin
debug: bin/mybin_debug.bin
debug: export DBG:=1
test: bin/mybin_test.bin
test: export TST:=1
define build_foo
bin/mybin$$($(1)).bin: bin/abc$$($(1)).bin bin/xyz$$($(1)).bin
cat $$^ > $$@
VER=$$$$(cat bin/rev.txt) && mv bin/mybin$$($(1)).bin bin/mybin$$($(1))_$$$${VER}.bin
bin/abc$$($(1)).bin:
$(MAKE) -C mod1 # <--- rev.txt is produced here
bin/xyz$$($(1)).bin:
$(MAKE) -C mod2
endef
$(foreach suffix, T1 T2 T3, $(eval $(call build_foo,$(suffix))))
clean:
rm bin/*.bin bin/*.txt
请注意尝试在VER
中抓取文件内容。有没有更好/正确的方法来做到这一点?我不能使用eval
,因为它在开始时运行,rev.txt
只在子make运行时才会创建。
另外,这是构建多个目标(使用foreach)的一种不错的方法吗?我使用导出的变量来修改子makefile构建的目标。
答案 0 :(得分:1)
据我所知,运行bin/rev.txt
时会生成此bin/abcXXX.bin
文件和所有$(MAKE) -C mod1
。所以,对所有人来说都是一样的。怎么样:
include version.mk
version.mk: bin/rev.txt
{ printf 'VER = '; cat $<; } > $@
bin/rev.txt:
$(MAKE) -C mod1
演示:
$ ls
Makefile
$ cat Makefile
include version.mk
all:
touch $(VER).txt
version.mk: rev.txt
{ printf 'VER = '; cat $<; } > $@
rev.txt:
echo "1.2.3" > $@
$ make --quiet
Makefile:1: version.mk: No such file or directory
$ ls
1.2.3.txt Makefile rev.txt version.mk
说明:
version.mk
是make将寻找的第二个makefile。根据{{3}}:
为此,在阅读完所有makefile后,make会考虑每个 作为目标目标并尝试更新它。如果makefile有规则 它说如何更新它(发现在那个非常makefile中或者在 另一个)或者隐含规则适用于它(请参阅使用隐式 规则),必要时会更新。毕竟makefile已经 检查,如果有任何实际更改,请从干净开始 平板并再次读取所有makefile。 (它也会尝试 再次更新它们,但通常这不会改变它们 再次,因为他们已经是最新的。)
注意:在编写makefile时,$(MAKE) -C mod1
将运行多次,这是一种浪费。您可以使用GNU make pattern规则的特异性:当它们有多个目标时,make会认为所有目标都是通过一次调用配方生成的。例如:
$ cat Makefile
all: a.bin b.bin c.bin
a.%in b.%in c.%in:
@echo 'building a.bin b.bin c.bin'
$ make all
building a.bin b.bin c.bin
请参阅?配方仅执行一次以构建3个目标。唯一的问题是%
通配符必须至少匹配一个字符。因此,在您的情况下,您可以执行类似的操作(%
匹配的字符是b
的{{1}}):
bin/
这将告诉make T1 := _release
T2 := _debug
T3 := _test
suffixes := T1 T2 T3
pattern := $(foreach suffix,$(suffixes),%in/abc$($(suffix))) %in/rev.txt
$(pattern):
$(MAKE) -C mod1
一次构建所有$(MAKE) -C mod1
和bin/abcXXX.bin
。与bin/rev.txt
相同。
总而言之,通过将所有这些功能粘合在一起,您可能完全摆脱了$(MAKE) -C mod2
通用规则。类似的东西:
build_foo