2016-07-11 2 views
2

Я пытаюсь создать аккуратно организованный шаблон проекта makefile, используя библиотеку mbed. Я уже решил несколько проблем (see this post), связанных с путями файлов заголовков. Однако теперь у меня возникают проблемы с компоновщиком. Моя цель - иметь источники и заголовки в src, объектные файлы в obj и конечные двоичные файлы в любом отлаживать или релиз.Ссылка на файл Makefile: неопределенная ссылка на _exit

Здесь ошибка я получаю ...

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 параметры ПРОЕКТ = Nucleo_blink ОБЪЕКТЫ = OBJ/main.o DEST = отлаживать VPATH = ЦСИ 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) 

Прежде чем спросить, я уже попытался изменить --specs=nano.specs к --specs=nosys.specs , Он ничего не делает. Странная часть заключается в том, что настройки компоновщика выше работают отлично для автоматически созданного mbed-файла.

Вот рабочий файл. Он компилируется без ошибок ...

# 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) 

Я думаю, что моя проблема в том, какая-то ошибка пути ... - The _exit символ может быть определен, но недоступны main.o - Там могут быть некоторые Основная ошибка в make-файле отсутствует. - Что-то совсем другое?

Не стесняйтесь, прокомментируйте предложенные изменения в этом вопросе.

EDIT: все, что я должен был устранить, было исправлено: CFLAGS - CCFLAGS. Ответ, который я обозначил как решение, объяснил, что происходит, и потенциальный способ его исправить. Хотя мне не нужно было использовать предлагаемое решение, объяснение того, почему оно не работает, полезно, и информация, предоставленная обоими ответами, полезна.

+0

Где $ CC_FLAGS приходит от вашего Makefile? Вы определяете $ CFLAGS, но никогда не ссылаетесь на AFAICS. Вы пытаетесь использовать отдельный шаг ссылки, но по ошибке, по-видимому, не передаете '-c' на этапе компиляции. – Notlikethat

+0

@Notlikethat Это было частью моей проблемы. Исправление этого результата привело к некоторым другим несвязанным ошибкам. –

ответ

1

Символ _exit может быть определен, но недоступен по умолчанию main.o - Может быть какая-то серьезная ошибка в make-файле, который мне не хватает - что-то совсем другое?

Это происходит, когда вызов стандартного метода библиотеки косвенно имеет зависимость от 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

_exit - системный вызов, а также некоторые другие функции, которые вам, вероятно, понадобятся позже. Когда вы компилируете двоичный файл для (например) Linux, эти вызовы обслуживаются операционной системой. В проекте с незащищенным железом вам необходимо определить эти функции самостоятельно. Обычный способ - создать файл с именем syscalls.c или что-то в этом роде и поместить туда все необходимые системные вызовы. Посмотрите на пример такого файла, быстро найденному Google: https://github.com/bjornfor/stm32-test/blob/master/STM32L1xx_StdPeriph_Lib_V1.1.1/syscalls.c

В качестве бонуса, если вы правильно реализовать _read и _write для работы с UART, вы получите последовательную консоль, способную делать отформатирован IO через printf и scanf ,

+0

Спасибо за быстрый ответ. Я мог видеть, что ваш совет полезен, но это не было решением в моем конкретном случае. Я думаю, что mbed заботится о системных вызовах. –

1

Добавление --specs=nosys.specs в параметры компоновщика может также решить эту проблему.

Вы можете видеть, что именно это делает, просматривая файл nosys.specs, который будет где-то в вашем каталоге компилятора.

Смотрите также: exit.c:(.text+0x18): undefined reference to `_exit' when using arm-none-eabi-gcc

Смежные вопросы