0

我正在用 C 编写一个矩阵库以供练习。为了养成良好的习惯,我正在使用Unity 测试框架进行测试,这意味着我编译了多个测试文件并运行它们。因为我不知道最终会得到多少测试文件,所以我一直在尝试编写我的 Makefile,以便在我的 tests/ 目录中找到任何 .c 文件并将其用于生成相应的可执行文件。

这是我的项目文件结构:

├── bin
├── include
|   ├── fml.h
├── src
|   ├── fml.c
├── test-framework
|   ├── unity.c
|   ├── unity.h
|   ├── unity_internals.h
├── tests
|   ├── check_fml_at.c
|   ├── check_fml_set_at.c
|   ├── check_fml_mem_management.c
├── Makefile
├── Readme

这是我正在努力的Makefile:

BIN_DIR = bin
SRC_DIR = src
TESTS_DIR = tests

FML = $(BIN_DIR)/fml.o
TEST_FRAMEWORK = $(BIN_DIR)/unity.o

CFLAGS = -Wall -Werror -g
CC = gcc

TESTS = $(patsubst %.c, %, $(patsubst $(TESTS_DIR)/%,  \
$(BIN_DIR)/%, $(wildcard $(TESTS_DIR)/*.c)))

$(info $$var is [${TESTS}])

$(TESTS): $(BIN_DIR)/%: $(TESTS_DIR)/%.c $(FML) $(TEST_FRAMEWORK)
    $(CC) $(CFLAGS) $^ -o $@ -Iinclude -Itest-framework
    
$(FML): src/fml.c include/fml.h
    $(CC) $(CFLAGS) -c $< -o $@ -Iinclude

$(TEST_FRAMEWORK): test-framework/unity.c test-framework/unity.h test-framework/unity_internals.h
    $(CC) $(CFLAGS) -c $< -o $@

memcheck:
    valgrind $(TESTS)

check:
    $(TESTS)

clean:
    rm $(TESTS) $(OBJS)

每个测试文件都需要库(fml)和测试框架(unity)。

运行 make 时的预期行为是 check_fml_at、check_fml_set_at 和 check_fml_mem_management 与 fml.o 和 unity.o 库一起显示为 bin/ 文件中的可执行文件。我已经检查过,TESTS 变量正确评估为 check_fml_at、check_fml_set_at 和 check_fml_mem_management。但由于某种原因,只构建了第一个测试,当我运行 make 时,我只在 bin 目录中看到 check_fml_at 以及 fml.o 和 unity.o。

为什么makefile会这样?我可以做些什么来确保 TESTS 中的每个文件都已构建,以便我可以运行每个测试?

感谢您的任何帮助!——托马斯·杜根

4

1 回答 1

0

您的静态模式规则似乎没有任何本质上的错误。make不带参数运行时只构建一个测试的原因是make选择了默认目标,而不是默认规则。如果 makefile 中的第一条规则有多个目标,那么首先出现的就是默认目标。

如果您希望默认构建所有测试,则插入一个新的第一条规则,将所有测试指定为先决条件:

.PHONY: all
all: $(TESTS)

顺便说一句,请注意,当 指定多个测试时,您的memcheckcheck食谱不会像您预期的那样工作$(TESTS)。您将只运行第一个测试,而不是运行每个测试,并将其他测试的名称作为命令行参数传递。也许你想要更像

.PHONY: memcheck check

memcheck:
        for t in $(TESTS); do valgrind $$t; done

check:
        for t in $(TESTS); do $$t; done
于 2022-01-28T20:23:09.783 回答