在 Makefile 中构建非默认目标 'all' 的二进制文件

Building binary with not default target 'all' in Makefile

下面我有简单的Makefile。使用默认目标 all.

时运行清晰
objects = foo.o bar.o all.o
all: $(objects)

all2: $(objects)

# These files compile via implicit rules
foo.o: foo.c
bar.o: bar.c
all.o: all.c

all.c:
    echo "int main() { return 0; }" > all.c
    
    
%.c:
    touch $@

clean:
    rm -f *.c *.o all2

但是当我执行 make all2 我得到:

touch foo.c
cc    -c -o foo.o foo.c
touch bar.c
cc    -c -o bar.o bar.c
echo "int main() { return 0; }" > all.c
cc    -c -o all.o all.c
touch all2.c
cc    -c -o all2.o all2.c
cc   all2.o foo.o bar.o all.o   -o all2
rm all2.o all2.c

all2 目标取决于 foo.o bar.o all.o,但为什么它试图获得 all2.c

为什么在最后执行clean目标?第 rm all2.o all2.c

原因是 make 有一个 built-in 规则,它知道如何从具有相同前缀的目标文件构建二进制文件;也就是说,给定一个二进制文件 foo make 有一个 built-in 规则知道如何从 foo.o.

构建它

您有一个目标 all2,通常这并不重要,因为您没有 all2.c,因此 make 无法找到构建 all2.o 的方法,并且所以它决定没有构建 all2.

的规则

但是在您的 makefile 中,您已经创建了构建任何 .c 文件的规则,因此当 make 尝试寻找构建 all2.o 的方法时,它发现它可以从 all2.c 并且有一个构建规则 all2.c,所以规则匹配。

当然,您的 non-test 生成文件中不会有像 %.c : ; touch $@ 这样的规则,因此您不会在任何真正的生成文件中看到此问题。

如果你想让它在你的测试环境中工作,你可以像@Cheatah 说的那样,声明 all2 规则是假的,这将阻止 make 试图查找任何规则来构建它。