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

嵌入式三层架构项目Makefile跨目录依赖文件生成问题

解决嵌入式C项目跨目录依赖文件(.d)生成问题

先明确你的项目典型目录结构(方便后续对应配置):

project-root/
├── application/
│   ├── inc/
│   │   └── app_main.h
│   └── src/
│       └── app_main.c
├── middle/
│   ├── inc/
│   │   └── hal_uart.h
│   └── src/
│       └── hal_uart.c
├── bottom/
│   ├── inc/
│   │   └── driver_uart.h
│   └── src/
│       └── driver_uart.c
└── _build/
    └── Makefile

下面给出不用-I指定头路径的解决方案:

1. 统一源文件的头文件包含方式

放弃使用短路径包含头文件,改用相对项目根目录的完整相对路径包含,比如:

  • 在app_main.c中包含HAL层头文件:#include "../middle/inc/hal_uart.h"
  • 在hal_uart.c中包含Driver层头文件:#include "../../bottom/inc/driver_uart.h"

这种方式让编译器无需-I就能直接定位到头文件,同时生成依赖时会记录完整路径,避免依赖跟踪失效。

2. 编写Makefile的依赖生成逻辑

在_build/Makefile中按以下逻辑配置,确保.d文件正确生成并被Make识别:

完整Makefile示例

# 定义项目根目录(Makefile在_build下,所以根目录是上级目录)
PROJECT_ROOT := ../

# 编译器及编译选项(根据你的嵌入式平台调整)
CC := arm-none-eabi-gcc
CFLAGS := -std=c99 -Wall -O2 -mcpu=cortex-m4 -mthumb

# 收集所有源文件目录
SRC_DIRS := $(PROJECT_ROOT)application/src \
            $(PROJECT_ROOT)middle/src \
            $(PROJECT_ROOT)bottom/src

# 递归获取所有.c源文件
SRCS := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c))

# 目标文件和依赖文件的存放目录(统一放在_build下,避免污染源码目录)
OBJ_DIR := obj
DEP_DIR := dep

# 转换源文件路径为目标文件、依赖文件路径
OBJS := $(patsubst $(PROJECT_ROOT)%.c,$(OBJ_DIR)/%.o,$(SRCS))
DEPS := $(patsubst $(PROJECT_ROOT)%.c,$(DEP_DIR)/%.d,$(SRCS))

# 最终生成的可执行文件
TARGET := app.elf

# 默认目标
all: $(TARGET)

# 链接生成可执行文件
$(TARGET): $(OBJS)
	$(CC) $(CFLAGS) $(OBJS) -o $@

# 编译源文件,同时生成依赖文件
$(OBJ_DIR)/%.o: $(PROJECT_ROOT)%.c | $(OBJ_DIR) $(DEP_DIR)
	# 自动创建目标文件所在的子目录
	@mkdir -p $(dir $@)
	# 使用-MMMP生成依赖,-MF指定.d文件输出路径
	$(CC) $(CFLAGS) -c $< -o $@ -MMD -MP -MF $(DEP_DIR)/$*.d

# 创建obj和dep目录
$(OBJ_DIR) $(DEP_DIR):
	@mkdir -p $@

# 包含所有生成的.d文件,让Make跟踪头文件变化
-include $(DEPS)

# 清理规则
clean:
	rm -rf $(OBJ_DIR) $(DEP_DIR) $(TARGET)

关键规则说明

  • -MMD:只生成用户自定义头文件的依赖(忽略系统头文件),减少.d文件冗余
  • -MP:自动为每个头文件生成空规则,避免头文件被删除时Make报错
  • -MF:强制指定.d文件的输出路径,确保所有依赖文件统一存放在_build/dep目录下,不会散落在各源码目录

3. 验证效果

执行make后,_build/dep目录下会生成对应每个源文件的.d文件,比如dep/application/src/app_main.d,内容类似:

obj/application/src/app_main.o: ../application/src/app_main.c \
 ../application/inc/app_main.h \
 ../middle/inc/hal_uart.h

此时修改任意跨目录的头文件,Make会自动重新编译依赖该头文件的源文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:01:18