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

Makefile自动依赖生成仍编译已排除源文件的问题解决

问题根因

两个核心问题叠加导致过滤规则完全失效:

  • 通配符兼容性问题:GNU Make 4.3以下版本(目前绝大多数开发环境的默认版本,比如Ubuntu 20.04、Windows下常见的MinGW配套make都属于这个范围)默认不支持**递归通配符。你写的$(wildcard Core/**/*.c)、$(wildcard Drivers/STM32WBxx_HAL_Driver/**/*.c)实际不会递归遍历子目录找C文件,直接导致CORE_SOURCES、DRIVER_SOURCES变量的枚举结果完全不对——你想过滤的Core/Src/main.c从一开始就没被纳入C_SOURCES的匹配范围,filter-out自然没有任何作用。
  • 旧构建残留干扰:你之前用CubeMX默认生成的Makefile编译过,build目录下残留了大量.d依赖文件。Makefile末尾的-include $(wildcard $(BUILD_DIR)/*.d)会把这些旧依赖全部加载进来,旧依赖里明确记录了Core/Src/main.c以及其他Core、Drivers目录下源文件的编译规则,哪怕你现在的C_SOURCES里没写这些文件,make也会按照旧依赖的规则去编译、链接它们。这也是为什么你改了C_SOURCES之后依然能编译成功——实际参与编译的源文件大部分是旧依赖拉进来的,根本不是你新定义的C_SOURCES列表里的内容。
  • 额外隐患:你用notdir抹除了所有源文件的路径前缀生成.o文件,不同目录下的同名源文件(比如C版main.c和C++版main.cpp)会生成同名的build/main.o,很容易出现旧目标文件残留、规则匹配错乱的问题。
修复步骤
  1. 首先彻底清理旧构建产物,避免残留依赖干扰
    直接执行命令彻底删除build目录,不要只依赖make clean(防止clean规则写漏的情况):
    rm -rf build
    
  2. 修正源文件枚举逻辑,替换不兼容的**通配
    把Makefile里源文件定义部分改成用find做递归枚举(全POSIX环境兼容,不依赖make高版本特性),同时正确过滤不需要的C版main.c:
    # Generated directories
    CORE_SOURCES := $(filter-out Core/Src/main.c,$(shell find Core -type f -name "*.c"))
    DRIVER_SOURCES := $(shell find Drivers/STM32WBxx_HAL_Driver -type f -name "*.c")
    C_SOURCES := $(CORE_SOURCES) $(DRIVER_SOURCES)
    
    # ASM sources
    ASM_SOURCES := startup_stm32wb55xx_cm4.s
    
    # C++ sources
    CXX_SOURCES := $(shell find App -type f -name "*.cpp")
    
    如果不想用find,也可以针对CubeMX的固定目录结构写明确层级的通配,效果一致:
    CORE_SOURCES := $(filter-out Core/Src/main.c,$(wildcard Core/Src/*.c))
    DRIVER_SOURCES := $(wildcard Drivers/STM32WBxx_HAL_Driver/Src/*.c Drivers/STM32WBxx_HAL_Driver/Src/Legacy/*.c)
    CXX_SOURCES := $(wildcard App/*.cpp App/*/*.cpp)
    
  3. (可选但推荐)解决同名目标文件冲突问题
    如果后续可能在不同目录放同名源文件,建议把目标文件的生成规则改成保留源文件的路径层级,从根源避免同名冲突。把原来OBJECTS、vpath、编译规则、目录创建的部分替换为如下内容:
    注意:Makefile中规则下的命令行必须以Tab开头,粘贴时不要替换成空格,否则会报规则错误
    # list of C objects
    OBJECTS := $(addprefix $(BUILD_DIR)/,$(C_SOURCES:.c=.o))
    vpath %.c $(sort $(dir $(C_SOURCES)))
    # list of C++ objects
    OBJECTS += $(addprefix $(BUILD_DIR)/,$(CXX_SOURCES:.cpp=.o))
    vpath %.cpp $(sort $(dir $(CXX_SOURCES)))
    # list of ASM program objects
    OBJECTS += $(addprefix $(BUILD_DIR)/,$(ASM_SOURCES:.s=.o))
    vpath %.s $(sort $(dir $(ASM_SOURCES)))
    
    $(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
    	@mkdir -p $(dir $@)
    	$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(<:.c=.lst) $< -o $@
    
    $(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR)
    	@mkdir -p $(dir $@)
    	$(CXX) -c $(CXXFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(<:.cpp=.lst) $< -o $@
    
    $(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
    	@mkdir -p $(dir $@)
    	$(AS) -c $(CFLAGS) $< -o $@
    
    $(BUILD_DIR):
    	mkdir -p $@
    
验证方法

改完之后先执行dry run,只打印要执行的命令不实际编译,确认输出中没有编译Core/Src/main.c的步骤,只有编译App目录下main.cpp的步骤:

make -n

确认命令输出符合预期后,再正常执行make构建即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 22:09:21