我有以下Makefile
:
ifneq ($(MAKECMDGOALS),clean)
-include generated.mk
endif
FOO ?= foo
all: a.txt
a.txt:
echo $(GEN_FOO) > $@
generated.mk: Makefile
echo GEN_FOO = $(FOO) > $@
.PHONY: clean
clean:
$(RM) a.txt
$(RM) generated.mk
建立单个目标时可以正常工作:
$ make clean
rm -f a.txt
rm -f generated.mk
$ make all
echo GEN_FOO = foo > generated.mk
echo foo > a.txt
但是,当我尝试一次建立多个目标时,事情进展并不顺利:
$ make clean all
rm -f a.txt
rm -f generated.mk
echo foo > a.txt
$ make all
echo GEN_FOO = foo > generated.mk
make: Nothing to be done for 'all'.
如果提供了变量,情况会变得更糟:
$ make clean
rm -f a.txt
rm -f generated.mk
$ make FOO=bar clean all
echo GEN_FOO = bar > generated.mk
rm -f a.txt
rm -f generated.mk
echo bar > a.txt
$ make all
echo GEN_FOO = foo > generated.mk
make: Nothing to be done for 'all'.
$ make FOO=bar clean all
rm -f a.txt
rm -f generated.mk
echo foo > a.txt
有什么办法可以纠正这种不正确的行为?
答案 0 :(得分:4)
Make确实在按照您的指示进行操作,而您没有告诉我们您想要做的事情与您告诉它做的事情不同(说 fix这样错误的行为在您没有定义行为的错误之处时并不能真正帮助我们,所以我们不能为您提供很多帮助。
您可能对包含的Makefile和比较$(MAKECMDGOALS)
之间的交互感到困惑。请注意:
ifneq ($(MAKECMDGOALS),clean)
除非您确切指定一个目标:clean
,否则这将不匹配。在您指定多个目标(其中一个是干净的)的情况下,由于clean all
不等于clean
,因此可以匹配。因此,当您运行make clean all
时,使将包含生成的生成文件,如果不存在,将生成该生成文件。
因为生成的包含文件仅被重建一次,所以当第一次解析makefile时,不可能这样说:“先运行规则X(例如clean
),然后重建包含的makefile,然后重新调用make “。
但是,用clean all
调用make总是一个坏主意。这是因为如果您要尝试添加-j
以实现并行性,则清理和构建将并行运行并破坏所有内容。
一个半常见的选择是提供一条可以同时执行这两种操作的不同规则,如下所示:
rebuild:
$(MAKE) clean
$(MAKE) all
然后运行make rebuild
。
答案 1 :(得分:0)
您当然可以在Shell的帮助下强制执行该行为。例如,在bash
中,您可以使用
for target in "clean" "all";
do
make $target;
done
如果要重做很多步骤,可以将其设为可执行脚本,也可以将其包装在shell函数中。