Makefile 链接:对 _exit 的未定义引用
Makefile linking: undefined reference to _exit
我一直在尝试利用 ARM mbed 库创建一个组织整齐的 makefile 项目模板。我已经解决了一些与头文件路径相关的问题(。但是,现在我遇到了链接器问题。我的目标是在 src、obj 中的目标文件,以及 debug 或 release.[= 中的最终二进制文件19=]
这是我遇到的错误...
make
arm-none-eabi-g++ -DTARGET_M4 -DMBED_BUILD_TIMESTAMP=1453683815.81 -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_FF_ARDUINO -DTARGET_STM32F446RE -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4 -std=c++98 -fno-rtti -I lib/ -I lib/mbed/ -I lib/mbed/TARGET_NUCLEO_F446RE/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/ -I lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE/ -o obj/main.o src/main.cc
/usr/lib/gcc/arm-none-eabi/6.1.1/../../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): In function `exit':
exit.c:(.text.exit+0x2c): undefined reference to `_exit'
collect2: error: ld returned 1 exit status
make: *** [makefile:54: obj/main.o] Error 1
这是我的生成文件。我已经指出问题可能出在哪里,但我不确定。
#项目参数
项目 = Nucleo_blink
对象 = obj/main.o
DEST = 调试
VPATH = 源库 $DEST
目标 = NUCLEO_F446RE
#Compilation options
DEBUG = 1
#Tools
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CXX = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
include $(TARGET).mk
CFLAGS = $(INCLUDE_PATHS) $(CC_SYMBOLS) $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
ifeq ($(HARDFP),1)
FLOAT_ABI = hard
else
FLOAT_ABI = softfp
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -O0
else
CFLAGS += -DNDEBUG -Os
endif
#MY PROBLEM MAY BE HERE
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
#`-u _printf_float -u _scanf_float` after -specs for floating point I/O
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
LIBRARIES = -lmbed
.PHONY: all clean lst size
all: $(PROJECT).bin $(PROJECT).hex
clean:
rm -f debug/* obj/* asm/* $(DEPS)
obj/%.o: %.c
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=c99 $(INCLUDE_PATHS) -o $@ $<
obj/%.o: %.cc
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $<
obj/%.o: %.cpp
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $<
obj/%.o: %.asm
$(CC) $(CPU) -c -x assembler-with-cpp -o asm/$@ $<
#OR HERE
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $(DEST)/$@ $^ $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS)
$(PROJECT).bin: $(PROJECT).elf
$(OBJCOPY) -O binary $< $@
$(PROJECT).hex: $(PROJECT).elf
@$(OBJCOPY) -O ihex $< $@
$(PROJECT).lst: $(PROJECT).elf
@$(OBJDUMP) -Sdh $< > $@
lst: $(PROJECT).lst
size: $(PROJECT).elf
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)
在你问之前,我已经尝试将 --specs=nano.specs
更改为 --specs=nosys.specs
。它什么都不做。奇怪的是上面的链接器设置对于自动生成的 mbed makefile 工作正常。
这是工作生成文件。它编译没有错误...
# This file was automagically generated by mbed.org. For more information,
# see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded
GCC_BIN =
PROJECT = Nucleo_blink
OBJECTS = ./source/main.o
SYS_OBJECTS = #Long list of object files
INCLUDE_PATHS = -I. -I./source -I./mbed -I./mbed/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4 -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM
LIBRARY_PATHS = -L./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM
LIBRARIES = -lmbed
LINKER_SCRIPT = ./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/STM32F446XE.ld
###############################################################################
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CPP = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
ifeq ($(HARDFP),1)
FLOAT_ABI = hard
else
FLOAT_ABI = softfp
endif
CPU = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=$(FLOAT_ABI)
CC_FLAGS = $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
CC_SYMBOLS = -DTARGET_M4 -DTARGET_FF_ARDUINO -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_LIKE_MBED -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_LIKE_CORTEX_M4 -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DMBED_BUILD_TIMESTAMP=1468213384.59 -DTARGET_STM32F446RE -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4
#My makefile above copies these two lines
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
ifeq ($(DEBUG), 1)
CC_FLAGS += -DDEBUG -O0
else
CC_FLAGS += -DNDEBUG -Os
endif
.PHONY: all clean lst size
all: $(PROJECT).bin $(PROJECT).hex size
clean:
rm -f $(PROJECT).bin $(PROJECT).elf $(PROJECT).hex $(PROJECT).map $(PROJECT).lst $(OBJECTS) $(DEPS)
.asm.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $@ $<
.s.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $@ $<
.S.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $@ $<
.c.o:
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu99 $(INCLUDE_PATHS) -o $@ $<
.cpp.o:
$(CPP) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $<
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $@ $^ -Wl,--start-group $(LIBRARIES) $(LD_SYS_LIBS) -Wl,--end-group
$(PROJECT).bin: $(PROJECT).elf
$(OBJCOPY) -O binary $< $@
$(PROJECT).hex: $(PROJECT).elf
@$(OBJCOPY) -O ihex $< $@
$(PROJECT).lst: $(PROJECT).elf
@$(OBJDUMP) -Sdh $< > $@
lst: $(PROJECT).lst
size: $(PROJECT).elf
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)
我认为我的问题是某种路径错误...
- 可以定义 _exit
符号,但 main.o 无法访问
- 我遗漏的 makefile 中可能存在一些重大错误
- 完全不同的东西?
如果对此问题有任何建议的更改,请随时发表评论。
编辑:修复错误所需要做的就是将 CFLAGS
更改为 CCFLAGS
。我标记为解决方案的答案解释了正在发生的事情,以及解决它的潜在方法。虽然我不需要使用建议的解决方案,但它为什么不起作用的解释很有用,而且两个答案提供的信息也很有用。
_exit
是一个系统调用,以及您稍后可能需要的其他一些功能。当您为(例如)Linux 编译二进制文件时,这些调用由操作系统提供服务。在裸机嵌入式项目中,您需要自己定义这些功能。常见的方法是创建一个名为 syscalls.c
或类似名称的文件,并将所有需要的系统调用放在那里。看一下 google 快速找到的此类文件的示例:https://github.com/bjornfor/stm32-test/blob/master/STM32L1xx_StdPeriph_Lib_V1.1.1/syscalls.c
作为奖励,如果您正确实施 _read
和 _write
以使用 UART,您将获得一个能够通过 printf
和 [=15 进行格式化 IO 的串行控制台=].
The _exit symbol may be defined, but inaccessible by main.o - There may be some major error in the makefile I'm missing - Something totally different?
当对标准库方法的调用间接依赖于 exit()
时,就会发生这种情况。通常来自自动生成的异常展开代码,这些代码应该在退出时中止您的进程,这在裸机应用程序中显然具有不同的语义。除零浮点异常就是这样的一个例子。 -fno-exceptions
对此没有帮助。
您当然可以提供一个什么都不做的 exit()
处理程序,但如果没有首先插入异常展开代码,您的代码会更小。
我通过检查生成的汇编程序发现,您可以在编译单元中用这样的无操作版本替换异常处理程序:
extern "C" void __wrap___aeabi_unwind_cpp_pr0() {}
extern "C" void __wrap___aeabi_unwind_cpp_pr1() {}
extern "C" void __wrap___aeabi_unwind_cpp_pr2() {}
然后 link 那些在 link 时间用这些额外的 linker 参数替换。
-Wl,-wrap,__aeabi_unwind_cpp_pr0,
-Wl,-wrap,__aeabi_unwind_cpp_pr1
-Wl,-wrap,__aeabi_unwind_cpp_pr2
另一个好处是您的代码应该因此而缩小。您甚至可能想要插入您自己的重置 MCU 的实现。
将 --specs=nosys.specs
添加到您的链接器选项也可以解决此问题。
您可以通过查看编译器目录中某处的 nosys.specs 文件来准确了解它的作用。
另请参阅:exit.c:(.text+0x18): undefined reference to `_exit' when using arm-none-eabi-gcc
对我来说,它在编译器标志中同时使用了 -fno-exceptions
和 --specs=nosys.specs
。
你好像用的是stdlib。系统调用 exit(int)
调用系统内函数 _exit(int)
.
我决定应用 -nostdlib
选项,因为我不打算使用 stdlib
。
谢谢,UserHuman,
我一直在尝试利用 ARM mbed 库创建一个组织整齐的 makefile 项目模板。我已经解决了一些与头文件路径相关的问题( 这是我遇到的错误... 这是我的生成文件。我已经指出问题可能出在哪里,但我不确定。
#项目参数
项目 = Nucleo_blink
对象 = obj/main.o
DEST = 调试
VPATH = 源库 $DEST
目标 = NUCLEO_F446RE 在你问之前,我已经尝试将 这是工作生成文件。它编译没有错误... 我认为我的问题是某种路径错误...
- 可以定义 如果对此问题有任何建议的更改,请随时发表评论。 编辑:修复错误所需要做的就是将 make
arm-none-eabi-g++ -DTARGET_M4 -DMBED_BUILD_TIMESTAMP=1453683815.81 -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_FF_ARDUINO -DTARGET_STM32F446RE -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4 -std=c++98 -fno-rtti -I lib/ -I lib/mbed/ -I lib/mbed/TARGET_NUCLEO_F446RE/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/ -I lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE/ -o obj/main.o src/main.cc
/usr/lib/gcc/arm-none-eabi/6.1.1/../../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): In function `exit':
exit.c:(.text.exit+0x2c): undefined reference to `_exit'
collect2: error: ld returned 1 exit status
make: *** [makefile:54: obj/main.o] Error 1
#Compilation options
DEBUG = 1
#Tools
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CXX = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
include $(TARGET).mk
CFLAGS = $(INCLUDE_PATHS) $(CC_SYMBOLS) $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
ifeq ($(HARDFP),1)
FLOAT_ABI = hard
else
FLOAT_ABI = softfp
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -O0
else
CFLAGS += -DNDEBUG -Os
endif
#MY PROBLEM MAY BE HERE
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
#`-u _printf_float -u _scanf_float` after -specs for floating point I/O
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
LIBRARIES = -lmbed
.PHONY: all clean lst size
all: $(PROJECT).bin $(PROJECT).hex
clean:
rm -f debug/* obj/* asm/* $(DEPS)
obj/%.o: %.c
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=c99 $(INCLUDE_PATHS) -o $@ $<
obj/%.o: %.cc
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $<
obj/%.o: %.cpp
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $<
obj/%.o: %.asm
$(CC) $(CPU) -c -x assembler-with-cpp -o asm/$@ $<
#OR HERE
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $(DEST)/$@ $^ $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS)
$(PROJECT).bin: $(PROJECT).elf
$(OBJCOPY) -O binary $< $@
$(PROJECT).hex: $(PROJECT).elf
@$(OBJCOPY) -O ihex $< $@
$(PROJECT).lst: $(PROJECT).elf
@$(OBJDUMP) -Sdh $< > $@
lst: $(PROJECT).lst
size: $(PROJECT).elf
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)
--specs=nano.specs
更改为 --specs=nosys.specs
。它什么都不做。奇怪的是上面的链接器设置对于自动生成的 mbed makefile 工作正常。# This file was automagically generated by mbed.org. For more information,
# see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded
GCC_BIN =
PROJECT = Nucleo_blink
OBJECTS = ./source/main.o
SYS_OBJECTS = #Long list of object files
INCLUDE_PATHS = -I. -I./source -I./mbed -I./mbed/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4 -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM
LIBRARY_PATHS = -L./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM
LIBRARIES = -lmbed
LINKER_SCRIPT = ./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/STM32F446XE.ld
###############################################################################
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CPP = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
ifeq ($(HARDFP),1)
FLOAT_ABI = hard
else
FLOAT_ABI = softfp
endif
CPU = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=$(FLOAT_ABI)
CC_FLAGS = $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
CC_SYMBOLS = -DTARGET_M4 -DTARGET_FF_ARDUINO -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_LIKE_MBED -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_LIKE_CORTEX_M4 -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DMBED_BUILD_TIMESTAMP=1468213384.59 -DTARGET_STM32F446RE -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4
#My makefile above copies these two lines
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
ifeq ($(DEBUG), 1)
CC_FLAGS += -DDEBUG -O0
else
CC_FLAGS += -DNDEBUG -Os
endif
.PHONY: all clean lst size
all: $(PROJECT).bin $(PROJECT).hex size
clean:
rm -f $(PROJECT).bin $(PROJECT).elf $(PROJECT).hex $(PROJECT).map $(PROJECT).lst $(OBJECTS) $(DEPS)
.asm.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $@ $<
.s.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $@ $<
.S.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $@ $<
.c.o:
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu99 $(INCLUDE_PATHS) -o $@ $<
.cpp.o:
$(CPP) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $<
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $@ $^ -Wl,--start-group $(LIBRARIES) $(LD_SYS_LIBS) -Wl,--end-group
$(PROJECT).bin: $(PROJECT).elf
$(OBJCOPY) -O binary $< $@
$(PROJECT).hex: $(PROJECT).elf
@$(OBJCOPY) -O ihex $< $@
$(PROJECT).lst: $(PROJECT).elf
@$(OBJDUMP) -Sdh $< > $@
lst: $(PROJECT).lst
size: $(PROJECT).elf
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)
_exit
符号,但 main.o 无法访问
- 我遗漏的 makefile 中可能存在一些重大错误
- 完全不同的东西?CFLAGS
更改为 CCFLAGS
。我标记为解决方案的答案解释了正在发生的事情,以及解决它的潜在方法。虽然我不需要使用建议的解决方案,但它为什么不起作用的解释很有用,而且两个答案提供的信息也很有用。
_exit
是一个系统调用,以及您稍后可能需要的其他一些功能。当您为(例如)Linux 编译二进制文件时,这些调用由操作系统提供服务。在裸机嵌入式项目中,您需要自己定义这些功能。常见的方法是创建一个名为 syscalls.c
或类似名称的文件,并将所有需要的系统调用放在那里。看一下 google 快速找到的此类文件的示例:https://github.com/bjornfor/stm32-test/blob/master/STM32L1xx_StdPeriph_Lib_V1.1.1/syscalls.c
作为奖励,如果您正确实施 _read
和 _write
以使用 UART,您将获得一个能够通过 printf
和 [=15 进行格式化 IO 的串行控制台=].
The _exit symbol may be defined, but inaccessible by main.o - There may be some major error in the makefile I'm missing - Something totally different?
当对标准库方法的调用间接依赖于 exit()
时,就会发生这种情况。通常来自自动生成的异常展开代码,这些代码应该在退出时中止您的进程,这在裸机应用程序中显然具有不同的语义。除零浮点异常就是这样的一个例子。 -fno-exceptions
对此没有帮助。
您当然可以提供一个什么都不做的 exit()
处理程序,但如果没有首先插入异常展开代码,您的代码会更小。
我通过检查生成的汇编程序发现,您可以在编译单元中用这样的无操作版本替换异常处理程序:
extern "C" void __wrap___aeabi_unwind_cpp_pr0() {}
extern "C" void __wrap___aeabi_unwind_cpp_pr1() {}
extern "C" void __wrap___aeabi_unwind_cpp_pr2() {}
然后 link 那些在 link 时间用这些额外的 linker 参数替换。
-Wl,-wrap,__aeabi_unwind_cpp_pr0,
-Wl,-wrap,__aeabi_unwind_cpp_pr1
-Wl,-wrap,__aeabi_unwind_cpp_pr2
另一个好处是您的代码应该因此而缩小。您甚至可能想要插入您自己的重置 MCU 的实现。
将 --specs=nosys.specs
添加到您的链接器选项也可以解决此问题。
您可以通过查看编译器目录中某处的 nosys.specs 文件来准确了解它的作用。
另请参阅:exit.c:(.text+0x18): undefined reference to `_exit' when using arm-none-eabi-gcc
对我来说,它在编译器标志中同时使用了 -fno-exceptions
和 --specs=nosys.specs
。
你好像用的是stdlib。系统调用 exit(int)
调用系统内函数 _exit(int)
.
我决定应用 -nostdlib
选项,因为我不打算使用 stdlib
。
谢谢,UserHuman,