Makefile链接:对_exit

时间:2016-07-11 05:42:06

标签: makefile arm stm32

我一直在尝试使用ARM mbed库创建一个整齐有序的makefile项目模板。我已经解决了一些与头文件路径相关的问题(see this post)。但是,现在我遇到链接器问题。我的目标是在 src 中有源和头, obj 中的目标文件,以及 debug release 中的最终二进制文件。

这是我得到的错误......

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

这是我的makefile。我已经说明了问题所在,但我不确定。     #Project参数     PROJECT = Nucleo_blink     OBJECTS = obj / main.o     DEST =调试     VPATH = src lib $ DEST     TARGET = 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。

这是工作的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。我标记为解决方案的答案解释了发生了什么,以及解决问题的潜在方法。虽然我不需要使用建议的解决方案,但解释它为什么不起作用是有用的,并且这两个答案提供的信息都很有用。

4 个答案:

答案 0 :(得分:4)

_exit是系统调用,以及稍后您可能需要的其他一些函数。为(例如)Linux编译二进制文件时,这些调用由操作系统提供服务。在裸机嵌入式项目中,您需要自己定义这些功能。常见的方法是创建一个名为syscalls.c的文件或类似的文件,并将所有需要的系统调用放在那里。看一下这样的文件示例,由google快速找到:https://github.com/bjornfor/stm32-test/blob/master/STM32L1xx_StdPeriph_Lib_V1.1.1/syscalls.c

作为奖励,如果您正确实施_read_write以使用UART,您将获得一个能够通过printfscanf执行格式化IO的串行控制台

答案 1 :(得分:4)

--specs=nosys.specs添加到链接器选项也可以解决此问题。

通过查看位于编译器目录中某处的 nosys.specs 文件,您可以确切了解其功能。

另请参阅:exit.c:(.text+0x18): undefined reference to `_exit' when using arm-none-eabi-gcc

答案 2 :(得分:2)

  

可以定义_exit符号,但是main.o无法访问 - 在我丢失的makefile中可能存在一些重大错误 - 完全不同的东西?

当对标准库方法的调用间接依赖exit()时会发生这种情况。通常来自自动生成的异常展开代码,它应该在退出时中止您的进程,这显然在裸机应用程序中具有不同的语义。除零浮点异常就是一个这样的例子。 -fno-exceptions对此没有帮助。

您当然可以提供无操作exit()处理程序,但如果首先未插入异常展开代码,则代码会更小。

我通过检查生成的汇编程序发现,你可以在编译单元中用这样的do-nothing版本替换异常处理程序:

extern "C" void __wrap___aeabi_unwind_cpp_pr0() {} 
extern "C" void __wrap___aeabi_unwind_cpp_pr1() {} 
extern "C" void __wrap___aeabi_unwind_cpp_pr2() {} 

然后在链接时将那些作为替换链接到这些额外的链接器参数。

-Wl,-wrap,__aeabi_unwind_cpp_pr0,
-Wl,-wrap,__aeabi_unwind_cpp_pr1
-Wl,-wrap,__aeabi_unwind_cpp_pr2

另一个好处是您的代码应该缩小。您甚至可能希望插入自己的实现来重置MCU。

答案 3 :(得分:0)

对我来说,在编译器标志中同时占用了-fno-exceptions--specs=nosys.specs

相关问题