Makefile依赖生成、目标文件存储等技术问题咨询
Makefile 问题解答
1. 依赖生成命令能否放在%.o: %.c规则下?用法是否正确?
可以放在该规则下,这种写法是允许的,但原用法存在细节问题:
- 每次编译
.o文件时重新生成.d依赖文件,逻辑上是合理的——源文件变化时依赖关系可能同步变更。 - 但
$(CC) $(CFLAGS) -MM $*.c生成的依赖内容中,目标是当前目录下的.o文件(比如test.o),如果后续把.o移到$(OBJ)目录,这个依赖路径会失效,导致Make无法找到目标。 - 更推荐用编译器内置参数简化流程:
$(CC) -c $(CFLAGS) $< -o $@ -MMD -MP -MF $(OBJ)/$*.d,编译和生成依赖一步完成,还能自动处理路径问题。
2. 如何将.o和.d文件都存储到$(OBJ)目录?
需要调整模式规则、目标路径和依赖生成逻辑,具体修改如下:
# 确保输出目录存在,避免编译时因目录缺失报错 $(shell mkdir -p $(OBJ) $(EXEC)) # 修改模式规则,指定.o文件输出到$(OBJ)目录 $(OBJ)/%.o: %.c $(CC) -c $(CFLAGS) $< -o $@ -MMD -MP -MF $(OBJ)/$*.d # 调整目标文件路径,给所有.o文件加上$(OBJ)前缀 A1_OBJ = $(addprefix $(OBJ)/, $(A1_SRC:.c=.o)) A2_OBJ = $(addprefix $(OBJ)/, $(A2_SRC:.c=.o))
解释:
$(OBJ)/%.o: %.c表示从当前目录的.c文件,生成$(OBJ)目录下的对应.o文件。-MMD让编译器自动生成依赖文件,-MP避免头文件被删除时Make报错,-MF指定依赖文件输出到$(OBJ)目录。$(addprefix)工具函数给所有.o路径添加$(OBJ)/前缀,确保目标路径正确。
3. 为什么A1目标加了const.h var.h,而A2没加?
A1目标后添加const.h var.h属于冗余依赖,完全没必要:
- 每个
.o文件的头文件依赖已经通过.d文件处理——如果.c文件包含const.h或var.h,.d文件会记录该.o与对应头文件的依赖关系,当头文件修改时,对应的.o会自动重新编译,进而触发A1目标的重新链接。 - A2目标的写法是正确的:链接目标(A1、A2)只需要依赖
.o文件即可,头文件的依赖已经在编译.o的阶段处理完毕。
4. 能否将两行-include合并为一行?
可以,有两种简洁实现方式:
- 方式一:先合并目标变量再引用
ALL_OBJ = $(A1_OBJ) $(A2_OBJ) -include $(ALL_OBJ:.o=.d)
- 方式二:直接在一行中引用两个变量的转换结果
-include $(A1_OBJ:.o=.d) $(A2_OBJ:.o=.d)
两种写法效果完全一致,都能正确包含所有.d依赖文件。
内容的提问来源于stack exchange,提问作者Thomas D.
相关产品推荐
相关产品推荐

