使用$(ALL_PROG): %: %.c 而不是$(ALL_PROG): $(SRC)。
这是一个我可能在 GNU make 中使用的 Makefile 示例:
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS := -lm
PROGS := $(patsubst %.c, %, $(wildcard *.c))
.PHONY: all clean test $(patsubst %, test@%, $(PROGS))
all: $(PROGS)
clean:
rm -f $(PROGS)
$(PROGS): %: %.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
$(patsubst %, test@%, $(PROGS)): test@%: %
./$^
test: $(patsubst %, test@%, $(PROGS))
像往常一样,注意缩进应该使用 Tab 而不是空格; stackoverflow.com 上使用的编辑器会自动将它们转换为空格。
PROGS 变量将包含目录中所有*.c 文件的名称。
.PHONY: 指令告诉 Make 哪些目标不引用实际文件。 $(patsubst %, test@%, $(PROGS)) 扩展为可执行文件名称列表,每个名称都以test@ 开头:如果目录包含文件foo.c 和bar.c,则扩展为test@foo test@bar。
$(PROGS): %: %.c 配方将每个 .c 文件编译为相应的二进制文件。
$(patsubst %, test@%, $(PROGS)): test@%: % 配方为每个二进制文件创建一个测试目标。如果我们有文件foo.c 和bar.c,则此规则扩展为test@foo test@bar: test@%: %。这意味着对于test@foo 和test@bar 目标,对应的test@% 目标需要% 二进制文件。 ./$^ 又扩展为 ./%,因此是二进制名称。 (如果您不想让 Make 显示正在运行的命令,请使用 @./$^。如果您不在乎测试是否失败,请使用 -./$^。)
test 配方扩展为 test@foo test@bar 如果我们有 foo.c 和 bar.c;即所有可能的测试目标。
可以运行make clean test重新编译目录下所有.c文件,并执行。
如果你只关心一个特定的测试程序,比如foo.c,你可以运行make test@foo,如果foo.c比foo更新,它将重新编译程序。