如何使用目标相关的编译器通过相同的规则制作多个目标?

How to make multiple targets by the same rule using target-dependent compilers?

假设我想验证 hello.c 与多个编译器的兼容性。如何使用 Makefile 来实现?

这是我为此编写的 Makefile。

# Makefile, version 1. 
# It tests hello.c using multiple compilers. 

TEST = test_gcc test_clang
.PHONY: $(TEST) all

all: $(TEST)

test_gcc: CC = gcc
test_clang: CC = clang

$(TEST): hello 
    ./hello
    rm -f hello

hello: hello.c
    $(CC) hello.c -o hello

如果我运行make test_gcctest_clang,一切正常。但是,make all 导致以下结果。

./hello
Hello, world!
rm -f hello
touch hello.c
./hello
make : ./hello : command not found
make: *** [Makefile:10 : test_clang] Error 127

所以 hello 没有为 test_clang 重新制作。这对像我这样的 Makfile 初学者来说似乎是这样。

问题:在我的Makefile中,test_clang依赖于hello,当test_gcc完成时,它已被删除。那么为什么 make 不在 运行 宁 ./hello 之前再次生成它?

我的尝试:

为了解决这个问题,我尝试了以下修改,在test_gcctest_clang之后触及hello.c。还是不行,还是一样的问题

# Makefile, version 2. 
# It tests hello.c using multiple compilers. 

TEST = test_gcc test_clang
.PHONY: $(TEST) all

all: $(TEST)

test_gcc: CC = gcc
test_clang: CC = clang

$(TEST): hello hello.c
    ./hello
    rm -f hello
    touch hello.c

hello: hello.c
    $(CC) hello.c -o hello

按照@HolyBlackCat 的建议,我也尝试了以下方法。

# Makefile, version 3.
# It tests hello.c using multiple compilers.

TEST = test_gcc test_clang
.PHONY: $(TEST) all

all: $(TEST)

test_gcc: CC = gcc
test_clang: CC = clang

$(TEST): hello_$(CC)
    ./hello_$(CC)
    rm -f hello_$(CC)

hello_$(CC): hello.c
    $(CC) hello.c -o hello_$(CC)

make all的输出是

gcc hello.c -o hello_gcc
./hello_gcc
Hello, world!
rm -f hello_gcc
./hello_clang
make : ./hello_clang : commande not found
make: *** [Makefile:13 : test_clang] Error 127

这更奇怪 --- hello_clang 从未被制作过,即使它是(仅)被 test_clang 要求的。

为方便起见,这里是我用于测试的标准hello.c

/* hello.c */

#include <stdio.h>

int main()
{
    printf("Hello, world!\n");
    return 0;
}

非常感谢您提出任何建议。如果您对我的 Makefile 进行一般性评论,而不一定是针对我提出的问题,我们也将不胜感激。我真的是初学者

查看特定于目标的变量的文档:很明显,特定于目标的变量在配方中生效。您不能在先决条件中使用它们,当然也不能在定义目标时使用它们。

在没有目标特定变量的情况下执行此操作可能更简单,只需使用模式规则即可:

TEST = test_gcc test_clang
.PHONY: all

all: $(TEST)

test_%: hello_%
        ./$<

hello_%: hello.c
        $* $< -o $@

(我不知道你为什么在测试后立即删除二进制文件,在这个版本中,所以我删除了它)。