2016-07-11 7 views
2

Ich habe versucht, eine übersichtliche Makefile-Projektvorlage mithilfe der ARM mbed-Bibliothek zu erstellen. Ich habe bereits einige der Probleme gelöst (see this post) im Zusammenhang mit Header-Datei-Pfade. Allerdings habe ich jetzt Probleme mit dem Linker. Mein Ziel ist Quellen und Header in src, Objektdateien in obj, und die letzte Binärdateien in beide debug oder Release.Makefile-Verknüpfung: undefinierter Verweis auf _exit

Hier ist der Fehler ich erhalte ...

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 

das ist meine Make-Datei. ich bezeichnet haben, wo das Problem (e) auch sein mag, aber ich bin mir nicht sicher #Project Parameter PROJECT = Nucleo_blink OBJEKTE = obj/main.o DEST = debug 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 [email protected] $< 

obj/%.o: %.cc 
     $(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o [email protected] $< 

obj/%.o: %.cpp 
     $(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o [email protected] $< 

obj/%.o: %.asm 
     $(CC) $(CPU) -c -x assembler-with-cpp -o asm/[email protected] $< 

#OR HERE 
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS) 
     $(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $(DEST)/[email protected] $^ $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS) 

$(PROJECT).bin: $(PROJECT).elf 
     $(OBJCOPY) -O binary $< [email protected] 

$(PROJECT).hex: $(PROJECT).elf 
     @$(OBJCOPY) -O ihex $< [email protected] 

$(PROJECT).lst: $(PROJECT).elf 
     @$(OBJDUMP) -Sdh $< > [email protected] 

lst: $(PROJECT).lst 

size: $(PROJECT).elf 
     $(SIZE) $(PROJECT).elf 

DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d) 
-include $(DEPS) 

Bevor Sie fragen, ich habe schon versucht --specs=nano.specs zu --specs=nosys.specs Wechsel . Es tut nichts. Der seltsame Teil ist, dass die obigen Linker-Einstellungen für das automatisch generierte mbed-Makefile funktionieren.

Hier ist das funktionierende Makefile. Es ohne Fehler kompiliert ...

# 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 [email protected] $< 
.s.o: 
     $(CC) $(CPU) -c -x assembler-with-cpp -o [email protected] $< 
.S.o: 
     $(CC) $(CPU) -c -x assembler-with-cpp -o [email protected] $< 

.c.o: 
     $(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu99 $(INCLUDE_PATHS) -o [email protected] $< 

.cpp.o: 
     $(CPP) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu++98 -fno-rtti $(INCLUDE_PATHS) -o [email protected] $< 



$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS) 
     $(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o [email protected] $^ -Wl,--start-group $(LIBRARIES) $(LD_SYS_LIBS) -Wl,--end-group 


$(PROJECT).bin: $(PROJECT).elf 
     $(OBJCOPY) -O binary $< [email protected] 

$(PROJECT).hex: $(PROJECT).elf 
     @$(OBJCOPY) -O ihex $< [email protected] 

$(PROJECT).lst: $(PROJECT).elf 
     @$(OBJDUMP) -Sdh $< > [email protected] 

lst: $(PROJECT).lst 

size: $(PROJECT).elf 
     $(SIZE) $(PROJECT).elf 

DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d) 
-include $(DEPS) 

Ich glaube, mein Problem eine Art Pfad Fehler ist ... - Das _exit Symbol kann definiert werden, aber unzugänglich durch main.o - Es kann etwas sein Hauptfehler im Makefile Ich vermisse - Etwas total anderes?

Fühlen Sie sich frei, alle vorgeschlagenen Änderungen zu dieser Frage zu kommentieren.

EDIT: Alles, was ich tun musste, um den Fehler zu beheben war CFLAGS-CCFLAGS ändern. Die Antwort, die ich als Lösung markierte, erklärte, was geschehen war, und einen möglichen Weg, es zu beheben. Obwohl ich die vorgeschlagene Lösung nicht verwenden musste, ist die Erklärung, warum sie nicht funktionierte, nützlich, und die Informationen beider Antworten sind nützlich.

+0

Wo ist CC_FLAGS von in Ihrem Make-Datei kommt $? Sie definieren $ CFLAGS, verweisen aber niemals auf diese AFAICS. Sie versuchen, einen separaten Verknüpfungsschritt zu verwenden, aber entsprechend dem Fehler, der beim Kompilierungsschritt anscheinend nicht "-c" übergibt. – Notlikethat

+0

@Notlikethat Das war Teil meines Problems. Die Behebung dieses Problems führte zu einigen anderen Fehlern, die nichts miteinander zu tun hatten. –

Antwort

1

Das _exit-Symbol kann definiert werden, aber von main.o nicht erreichbar - Es kann zu einem größeren Fehler im Makefile kommen, das fehlt - Etwas völlig anderes?

Dies geschieht, wenn ein Aufruf einer Standardbibliotheksmethode indirekt eine Abhängigkeit von exit() hat. Oftmals aus automatisch generierten Ausnahme-Abwicklungscode, der Ihren Prozess beim Beenden abbrechen soll, der offensichtlich eine andere Semantik in einer Bare-Metal-Anwendung hat. Die Division-durch-Null-Gleitkommaausnahme ist ein solches Beispiel. -fno-exceptions hilft nicht dabei.

Sie können natürlich einen Do-Nothing-Handler exit() liefern, aber Ihr Code wäre kleiner, wenn der Code zum Auslösen der Ausnahme nicht an erster Stelle eingefügt wurde.

entdeckte ich durch den erzeugten Assembler untersuchen, dass Sie die Exception-Handler mit do-nothing-Versionen wie dies in einer Übersetzungseinheit ersetzen:

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

und verknüpfen Sie dann mit diesen zusätzlichen denen als Ersatz zur Verknüpfungszeit Linker Argumente.

Ein weiterer Vorteil ist, dass Ihr Code als Ergebnis schrumpfen sollte. Möglicherweise möchten Sie sogar Ihre eigenen Implementierungen einfügen, die die MCU zurücksetzen.

3

_exit ist ein Systemanruf, sowie einige andere Funktionen, die Sie wahrscheinlich später brauchen werden. Wenn Sie eine Binärdatei für (z. B.) Linux kompilieren, werden diese Aufrufe vom Betriebssystem bedient. Im Bare-Metal-Embedded-Projekt müssen Sie diese Funktionen selbst definieren. Der übliche Weg besteht darin, eine Datei namens syscalls.c oder etwas ähnliches zu erstellen und alle benötigten Systemaufrufe dorthin zu stellen. Hier finden Sie aktuelle Beispiel für eine solche Datei, schnell durch google gefunden: https://github.com/bjornfor/stm32-test/blob/master/STM32L1xx_StdPeriph_Lib_V1.1.1/syscalls.c

Als Bonus, wenn Sie richtig _read und _write implementieren mit UART zu arbeiten, werden Sie eine serielle Konsole erhalten fähig zu tun IO formatiert über printf und scanf .

+0

Danke für die schnelle Antwort. Ich könnte Ihren Rat als nützlich ansehen, aber in meinem speziellen Fall war das nicht die Lösung. Ich denke, mbed kümmert sich um die Systemaufrufe. –