我有一个程序依赖于由单独的 makefile 构建的库。 主 makefile 无法正确检测到库已重建,因此不会重新创建我的程序。
主要的
Makefile
可以简化(只用touch
来代表实际的编译)如下。它总是调用子 make 以确保 libA 是最新的,而无需了解其依赖项。
progA: srcA libA
touch $@
libA: make_libA_if_needed
.PHONY: make_libA_if_needed
make_libA_if_needed:
make -f Makefile.libA libA
clean:
rm -f progA libA
第二个makefile
Makefile.libA
可以简化为这样
libA: libsrcA
touch $@
当 libA 不存在或不需要重建时,这会按预期工作
jronnber@jronnber-mobl:~/tmp $ touch srcA libsrcA
jronnber@jronnber-mobl:~/tmp $ make
make -f Makefile.libA libA
make[1]: Entering directory '/home/jronnber/tmp'
touch libA
make[1]: Leaving directory '/home/jronnber/tmp'
touch progA
jronnber@jronnber-mobl:~/tmp $ make
make -f Makefile.libA libA
make[1]: Entering directory '/home/jronnber/tmp'
make[1]: 'libA' is up to date.
make[1]: Leaving directory '/home/jronnber/tmp'
jronnber@jronnber-mobl:~/tmp $
但是,如果我更新 libsrcA,我需要运行 make 两次才能正确重建 progA。
jronnber@jronnber-mobl:~/tmp $ touch libsrcA
jronnber@jronnber-mobl:~/tmp $ make
make -f Makefile.libA libA
make[1]: Entering directory '/home/jronnber/tmp'
touch libA
make[1]: Leaving directory '/home/jronnber/tmp'
jronnber@jronnber-mobl:~/tmp $ make
make -f Makefile.libA libA
make[1]: Entering directory '/home/jronnber/tmp'
make[1]: 'libA' is up to date.
make[1]: Leaving directory '/home/jronnber/tmp'
touch progA
jronnber@jronnber-mobl:~/tmp $
这是 make 中的错误吗?或者我可以以某种方式更改我的
Makefile
来检测 libA 已由 make_libA_if_needed
中的子 make 重建吗?
这条线还不够:
libA: make_libA_if_needed
GNU Make 知道这里没有配方,因此它没有运行命令来更新该目标,因此它“知道”目标尚未被修改。您可以向规则添加一个虚拟配方,以便 make 意识到该目标可能已更新(即使配方为空,make 仍认为它可能已更新)。
因此将上面的行更改为:
libA: make_libA_if_needed ;
(注意添加的分号)。或者,如果您愿意,可以使用这个:
libA: make_libA_if_needed
@: do nothing
或者其他什么。
另一种方法是使用 FORCE 规则而不是 .PHONY。 .PHONY 是一根非常大的棍子,它告诉 make 始终重建目标并假设它已经过时。但 FORCE 技巧可确保目标被重建,而不会假设它已经过时。看起来像这样:
libA: FORCE
$(MAKE) -f Makefile.libA $@
FORCE:
(请注意,您应该始终使用
$(MAKE)
来调用子品牌,而不是make
)。在此模型中,您不需要 make_libA_if_needed
目标。
注意目标的实际名称
FORCE
只是一个约定;你可以随意称呼它。如果您想更加安全,也可以将其声明为.PHONY
。