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)
修改说明
- 静态模式规则:
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c会逐个匹配$(C_OBJS)中的每个目标,自动找到对应的源文件(将build/替换为src/,.o替换为.c),确保每个源文件单独编译到对应路径。 - 自动创建目录:
@mkdir -p $(dir $@)会自动生成目标文件所在的子目录(比如build/usys),避免编译时因目录不存在报错。 - 变量正确性:
$<现在会取当前目标对应的单个源文件,$@取当前目标文件路径,实现一对一编译。
内容的提问来源于stack exchange,提问作者justynnuff
相关产品推荐
相关产品推荐

