RISC-V GCC编译报错:main.o已生成但无main函数,提示undefined reference to 'main'
RISC-V编译链接错误:undefined reference to 'main'
问题场景
使用RISC-V GCC工具链为微控制器编译项目,项目包含多文件及一个main.c,main.c代码如下:
int main(void) { return 0; }
错误信息
编译时链接器抛出错误:
riscv-none-embed/bin/ld.exe : in startup.S : undefined reference to 'main'
排查结果
- 编译器已生成
main.o目标文件,但该文件中未包含main函数 - 对
main.o执行nm工具得到如下输出:
0000018e t .L0 00000196 t .L0 0000019c t .L0 000001a4 t .L0 000001aa t .L0 000001c2 t .L0 000001c4 t .L0 000001c8 t .L0 000001ce t .L0 000001ce t .L0 00000076 t .L4 00000104 t .L5 000001e7 N .LASF0 000001ac N .LASF1 00000224 N .LASF10 000000e1 N .LASF11 . . . 00000469 N .LASF57 000000e9 N .LASF58 00000151 N .LASF59 0000008a N .LASF6 000004a2 N .LASF60 0000026c N .LASF61 00000000 d some_global_variable 00000000 T some_function0 0000017c T some_function1 00000110 T some_function2 00000050 T some_function3 U some_function4 U some_function5
注:所有some_functionX及全局变量均来自其他C文件,未在main.c中定义
Makefile核心内容(已脱敏)
STARTUP_FILE := $(ROOT_DIR)/../startup.S STARTUP_OBJ := $(ROOT_DIR)/../startup.o TOOL_DIR := $(ROOT_DIR)/../../riscv_gcc/riscv-none-embed-gcc/bin GCC := $(TOOL_DIR)/riscv-none-embed-gcc-10.2.0 LD := $(TOOL_DIR)/riscv-none-embed-ld GDB := $(TOOL_DIR)/riscv-none-embed-gdb OBJCOPY := $(TOOL_DIR)/riscv-none-embed-objcopy OBJDUMP := $(TOOL_DIR)/riscv-none-embed-objdump READELF := $(TOOL_DIR)/riscv-none-embed-readelf CODESIZE := $(TOOL_DIR)/riscv-none-embed-size NMINFO := $(TOOL_DIR)/riscv-none-embed-nm LIB := $(LIB_DIR)/lib$(TARGET).a ELF := $(BIN_DIR)/$(TARGET).elf BIN := $(BIN_DIR)/$(TARGET).bin HEX := $(BIN_DIR)/$(TARGET).hex DASM := $(BIN_DIR)/$(TARGET).dasm EN_OPTIMIZE = -O0 OPTFLAGS := -march=rv32imc -mabi=ilp32 -mno-strict-align --specs=nano.specs $(EN_OPTIMIZE) AFLAGS := -D__STACK_SIZE=$(STACK_SIZE) -nostartfiles --entry Reset_Handler LDFLAGS := $(LINKER_FILE) -Xlinker -Map=$(BIN_DIR)/$(TARGET).map -L$(LIB_DIR) LDFLAGS += -falign-functions=4 -falign-jumps -falign-loops -falign-labels # The -MMD flags additionaly creates a .d file as header dependency with the same name as the .o file. CFLAGS := -g -Wall -MMD -Wtype-limits -Woverflow -Wabsolute-value -Wno-unused-label $(INC_DIR) $(EN_OPTIMIZE) CFLAGS += -falign-functions=4 -falign-jumps -falign-loops -falign-labels -mno-relax .PHONY: all all: $(ELF) $(BIN) $(HEX) $(DASM) # build object files $(OBJ): $(SRC) ifeq ($(wildcard $(OBJ_DIR)),) mkdir -p $(OBJ_DIR) endif $(GCC) $(CFLAGS) -c $< -o $@ # Build the library .a $(LIB): $(OBJ) ifeq ($(wildcard $(LIB_DIR)),) mkdir -p $(LIB_DIR) endif $(TOOL_DIR)/riscv-none-embed-ar -crs $@ $(OBJ) # Build .elf $(ELF): $(LIB) $(OBJ) ifeq ($(wildcard $(BIN_DIR)),) mkdir -p $(BIN_DIR) endif $(GCC) $(CFLAGS) $(STARTUP_FILE) $(LDFLAGS) $(AFLAGS) -l$(TARGET) -o $@ # Build .bin $(BIN): $(ELF) ifeq ($(wildcard $(BIN_DIR)),) mkdir -p $(BIN_DIR) endif $(OBJCOPY) -O binary $< $@ # Build .hex $(HEX): $(ELF) ifeq ($(wildcard $(BIN_DIR)),) mkdir -p $(BIN_DIR) endif $(OBJCOPY) -O ihex $< $@ #Build disassembly file .dasm $(DASM): $(ELF) ifeq ($(wildcard $(BIN_DIR)),) mkdir -p $(BIN_DIR) endif $(OBJDUMP) -d -S $< > $@ .PHONY: clean clean: rm -rf $(OUTPUT_DIR)
排查与解决方向
- 检查
main.c是否被纳入编译:确认Makefile中SRC变量包含main.c,$(OBJ)对应的目标文件列表里存在正确的main.o(而非其他文件重名覆盖) - 验证库文件内容:用
ar t $(LIB)命令查看静态库lib$(TARGET).a,确认main.o被正确打包进库中 - 调整链接顺序:链接时库文件
-l$(TARGET)应放在引用它的文件之后,将链接命令修改为$(GCC) $(CFLAGS) $(STARTUP_FILE) $(LDFLAGS) $(AFLAGS) -l$(TARGET) -o $@改为$(GCC) $(CFLAGS) $(STARTUP_FILE) $(LDFLAGS) $(AFLAGS) -l$(TARGET) -o $@(若startup.S依赖库中符号,库需后置) - 排查宏定义干扰:检查
main.c及引用的头文件,是否存在#define main之类的宏重命名main函数 - 确认编译选项无异常:虽然使用
-O0,但排查是否存在-ffunction-sections配合--gc-sections导致未被识别引用的main被误删
内容的提问来源于stack exchange,提问作者user12312425
相关产品推荐
相关产品推荐

