如何在Makefile中避免手动枚举.o目标文件?
Makefile自动生成目标文件列表解决方案
问题根因
你使用OBJECT_FILES = $(wildcard $(BUILD_DIR)/*.o)的写法会报错,核心原因是wildcard函数在Makefile解析阶段就会执行,首次构建时build目录为空,没有任何.o文件,所以OBJECT_FILES最终会被赋值为空,链接阶段自然找不到各个模块的符号,触发「undefined reference」错误。
正确实现方法
不需要从build目录匹配已有的.o,而是直接从src目录的源文件列表推导目标文件列表即可,使用Make内置的字符串替换函数就能实现:
- 先从所有源文件中过滤掉单独编译的
main.c - 把剩余模块源文件的路径、后缀批量替换为build目录下的.o后缀
修改后的Makefile核心代码
BUILD_DIR = $(CURDIR)/build INCLUDE_DIR = $(CURDIR)/include SRC_DIR = $(CURDIR)/src CC = gcc # 更规范的CFLAGS写法,把-I参数和路径分开 CFLAGS = -Wall -g # 模式规则,先自动创建build目录再编译 $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(INCLUDE_DIR)/%.h @mkdir -p $(@D) @$(CC) $(CFLAGS) -I$(INCLUDE_DIR) -c $< -o $@ SRC_FILES = $(wildcard $(SRC_DIR)/*.c) HEADER_FILES= $(wildcard $(INCLUDE_DIR)/*.h) # 过滤main.c,生成模块源文件列表 MODULE_SRC_FILES = $(filter-out $(SRC_DIR)/main.c, $(SRC_FILES)) # 批量替换得到目标文件列表,无需手动枚举 OBJECT_FILES = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(MODULE_SRC_FILES)) prog: $(SRC_DIR)/main.c $(OBJECT_FILES) @$(CC) $(CFLAGS) -I$(INCLUDE_DIR) $^ -o $(BUILD_DIR)/$@
注意事项
- 原有模式规则要求每个模块.c必须对应同名的.h文件,如果存在无对应头文件的模块,需要调整模式规则的依赖项,否则会匹配失败
- 代码中用
CURDIR替换了你原来的CURRENT_DIR,CURDIR是Make内置的当前工作目录变量,无需额外定义
内容的提问来源于stack exchange,提问作者uch
相关产品推荐
相关产品推荐

