You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Criterion框架编译C单元测试失败,请求修正Makefile

问题:使用Criterion框架编译C单元测试时Makefile报错

我尝试用Criterion为C项目编写单元测试,但运行tests_run规则时编译失败,报错提示找不到目标文件的生成规则。

项目结构

.
├── include
│   └── mysh.h
├── Makefile
├── obj
├── src
│   ├── arrays_handler.c
│   ├── builtin_env.c
│   ├── delete_from_env.c
│   ├── display_env.c
│   ├── display_prompt.c
│   ├── doubly_linked_list.c
│   ├── env_handler.c
│   ├── execute_command.c
│   ├── mysh.c
│   ├── my_strcmp.c
│   ├── my_strcpy.c
│   ├── my_strdup.c
│   ├── my_strlen.c
│   ├── my_strncmp.c
│   ├── my_strndup.c
│   ├── my_strrchr.c
│   ├── my_str_to_word_array.c
│   ├── name_slice.c
│   ├── parse_command.c
│   ├── sanitize.c
│   ├── shell_handler.c
│   └── strbind.c
└── tests
    ├── Makefile
    └── sanitize_test.c

根目录Makefile(可正常编译)

INCLUDE_DIR :=  include
OBJ_DIR     :=  obj
SRC_DIR     :=  src
NAME        :=  mysh
CC          :=  gcc
CFLAGS      :=  -Wall -Wextra -Werror -ggdb3
CPPFLAGS    :=  -I$(INCLUDE_DIR)

SRC_FILES := $(wildcard $(SRC_DIR)/*.c)
OBJ_FILES := $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC_FILES))

all: $(NAME)

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
    @$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

$(NAME): $(OBJ_FILES)
    @$(CC) $(CFLAGS) -o $@ $^ $(LDLIBS)

clean:
    @$(MAKE) -C ./tests tests_clean
    @rm -rf $(OBJ_DIR)/*.o

fclean: clean
    @$(MAKE) -C ./tests tests_fclean
    @rm -rf $(NAME)

tests_run: fclean
    @$(MAKE) -C ./tests tests_run

re: fclean all

.PHONY: all clean fclean tests_run re

测试目录原Makefile(报错版本)

CC          :=  gcc
CFLAGS      :=  -Wall -Wextra -Werror -ggdb3
CPPFLAGS    :=  -I../include
LDFLAGS     :=  -Lcriterion/lib
LDLIBS      :=  -lcriterion
NAME        = ../unit-tests
OBJ_DIR     = ../obj
SRC         = $(shell find ../src -name '*.c' ! -name 'mysh.c')
TEST_SRC    = $(shell find . -name '*.c')
OBJ         = $(patsubst ../src/%.c,$(OBJ_DIR)/%.o,$(SRC))
TEST_OBJ    = $(patsubst ./%.c,$(OBJ_DIR)/%.o,$(TEST_SRC))

$(OBJ_DIR)/%.o: %.c
    @mkdir -p $(OBJ_DIR)
    @$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

tests_run: $(OBJ) $(TEST_OBJ)
    @$(CC) $(CFLAGS) $(LDFLAGS) $(filter-out ../obj/mysh.o,$(TEST_SRC) $(SRC)) $(LDLIBS) -o $(NAME)
    @./$(NAME)

tests_clean:
    @rm -rf $(OBJ)
    @rm -f ../*.gcda
    @rm -f ../*.gcno

tests_fclean: tests_clean
    @rm -f $(NAME)

.PHONY: tests_run tests_clean tests_fclean

报错信息

make[1]: enter the "[...]/tests" directory
make[1]: exit the "[...]/tests" directory
make[1]: enter the "[...]/tests" directory
make[1]: exit the "[...]/tests" directory
make[1]: enter the "[...]/tests" directory
make[1]: *** No rule to make target "../obj/display_prompt.o", required for "tests_run". Stop.
make[1]: exit directory "[...]/tests".
make: *** [Makefile:29: tests_run] Error 2

修正后的测试目录Makefile

CC          :=  gcc
CFLAGS      :=  -Wall -Wextra -Werror -ggdb3
CPPFLAGS    :=  -I../include
LDFLAGS     :=  -Lcriterion/lib
LDLIBS      :=  -lcriterion
NAME        = ../unit-tests
OBJ_DIR     = ../obj
# 排除mysh.c,只取src下的其他源文件
SRC         = $(filter-out ../src/mysh.c, $(wildcard ../src/*.c))
TEST_SRC    = $(wildcard ./*.c)
# 生成src对应目标文件路径
OBJ         = $(patsubst ../src/%.c, $(OBJ_DIR)/%.o, $(SRC))
# 生成测试源文件对应目标文件路径,添加test_前缀避免重名
TEST_OBJ    = $(patsubst ./%.c, $(OBJ_DIR)/test_%.o, $(TEST_SRC))

# 规则1:编译src目录下的.c文件到obj目录
$(OBJ_DIR)/%.o: ../src/%.c
    @mkdir -p $(OBJ_DIR)
    @$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

# 规则2:编译当前目录(tests)下的.c文件到obj目录
$(OBJ_DIR)/test_%.o: ./%.c
    @mkdir -p $(OBJ_DIR)
    @$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

tests_run: $(OBJ) $(TEST_OBJ)
    # 链接所有目标文件生成测试可执行文件
    @$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $(NAME)
    @./$(NAME)

tests_clean:
    @rm -rf $(OBJ) $(TEST_OBJ)
    @rm -f ../*.gcda ../*.gcno

tests_fclean: tests_clean
    @rm -f $(NAME)

.PHONY: tests_run tests_clean tests_fclean

关键修改点说明

  1. 源文件匹配优化:用wildcard替代find,符合Makefile常规写法,避免不必要的子shell调用。
  2. 目标文件规则修复:
    • 新增专门处理../src/%.c到$(OBJ_DIR)/%.o的规则,解决原规则无法匹配上层目录源文件的问题。
    • 测试文件目标文件添加test_前缀,避免和src目录的目标文件重名冲突。
  3. 链接命令修正:原命令错误使用源文件而非目标文件,改为用$^引用所有依赖目标文件,逻辑清晰且正确。
  4. 清理规则完善:确保测试生成的目标文件也被清理。

内容的提问来源于stack exchange,提问作者Nayrosk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:55:15