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

Makefile编译出现多重定义错误,如何修正目标文件生成逻辑?

解决ARM交叉编译Makefile多重定义错误

问题根源

你当前的Makefile编译规则存在逻辑错误:

$(C_OBJS): $(SRC_FILES_C)
    $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@

这条规则会让所有C目标文件都依赖所有C源文件,而自动变量$<只会取第一个依赖文件(即src/usys/startup.c)。最终不管目标是build/usys/startup.o还是build/usys/usys.o,都会编译同一个源文件并覆盖输出,导致两个目标文件内容完全一致,链接时必然出现多重定义错误。

修改方案

将编译规则替换为静态模式规则,实现每个源文件对应生成指定路径的目标文件,同时确保build目录下的子目录自动创建:

TARGET = main.elf
BUILD_DIR = build
SRC_DIR = src

CC = arm-none-eabi-gcc -std=gnu17
CXX = arm-none-eabi-g++ -std=c++17 
LINKER = arm-none-eabi-g++
OBJDUMP = arm-none-eabi-objdump
OBJCOPY = arm-none-eabi-objcopy

INCLUDES = -I./src/inc \
           -I./src/usys/inc

SRC_FILES_C =   $(SRC_DIR)/usys/startup.c \
                $(SRC_DIR)/usys/usys.c

SRC_FILES_CXX = $(SRC_DIR)/main.cpp

LINKER_FILE = $(SRC_DIR)/usys/flash.ld

CFLAGS = -Wall -Wextra -g3 -O0
CFLAGS += -c -mthumb -fdata-sections -ffunction-sections -DARM
CFLAGS += -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -mfloat-abi=hard --specs=nano.specs

LFLAGS = -mcpu=cortex-m33 --specs=nosys.specs --specs=nano.specs
LFLAGS += -T$(LINKER_FILE) -Wl,-Map="$(TARGET).map" -Wl,--gc-sections -static
LFLAGS += -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -lstdc++ -lsupc++ -Wl,--end-group

C_OBJS = ${subst $(SRC_DIR),$(BUILD_DIR),$(SRC_FILES_C:.c=.o)}
CXX_OBJS = ${subst $(SRC_DIR),$(BUILD_DIR),$(SRC_FILES_CXX:.cpp=.o)}

ALL_OBJS = $(CXX_OBJS) $(C_OBJS)

.PHONY: clean

all: $(TARGET)

# 修改后的编译规则:静态模式规则匹配每个源文件与目标文件
$(C_OBJS): $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
	@mkdir -p $(dir $@)
	$(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@

$(CXX_OBJS): $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
	@mkdir -p $(dir $@)
	$(CXX) $(INCLUDES) $(CFLAGS) -c $< -o $@

# Link
$(TARGET): $(ALL_OBJS)
	$(CXX) $(LFLAGS) $(ALL_OBJS) -o $@

# Clean
clean:
	@rm -f $(ALL_OBJS) $(TARGET)

修改说明

  1. 静态模式规则:$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c会逐个匹配$(C_OBJS)中的每个目标,自动找到对应的源文件(将build/替换为src/,.o替换为.c),确保每个源文件单独编译到对应路径。
  2. 自动创建目录:@mkdir -p $(dir $@)会自动生成目标文件所在的子目录(比如build/usys),避免编译时因目录不存在报错。
  3. 变量正确性:$<现在会取当前目标对应的单个源文件,$@取当前目标文件路径,实现一对一编译。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 18:40:00