Понимание компиляции и связывания с существующей C-программой
Я унаследовал слегка сложную C-программу для одного из 32-битных микропроцессоров AVR32.
Тем не менее, у меня нет информации о том, как его скомпилировать. Я уже пытался собрать для этого файл make-файла, но безуспешно. Надеюсь, кто-нибудь скажет мне, где я иду не так.
По сути, у меня есть структура проекта, которая выглядит следующим образом:
/
ControllerR3.c # This is the main program file
/FRAMEWORK
/DRIVERS
/ADC
adc.c
adc.h
/GPIO
gpio.c
gpio.h
{another 6 hardware drivers}
/SERVICES
/DELAY
delay.c
delay.h
В принципе, ControllerR3.c
включает в себя adc.h
, gpio.h
и т. д., и вызывает функции, которые создаются в этих различных заголовочных файлах. Актуальные функции в различных FRAMEWORK
Заголовки на самом деле определены в .c
файлы.
Все .h
файлы обернуты в защиту включений:
#ifndef _USART_H_
#define _USART_H_
{snip header file contents}
#endif // _USART_H_
Теперь, насколько я понимаю, я должен скомпилировать различные .c
файлы в объект (.o
), а затем вызвать компоновщик для объединения всех объектных файлов в конечный исполняемый файл (в данном случае это .elf
файл).
Поэтому я написал небольшой make-файл:
CC = avr32-gcc
CFLAGS = -mpart=uc3a0512 -O1 -ffunction-sections -masm-addr-pseudos -g3 -Wall -c -std=gnu99
COMP_INC = -I"./FRAMEWORK/UTILS" \
-I"./FRAMEWORK/UTILS/PREPROCESSOR"
LIB_INC = -I"./FRAMEWORK/UTILS/LIBS/NEWLIB_ADDONS/INCLUDE" \
-I"./FRAMEWORK/SERVICES/DELAY" \
-I"./FRAMEWORK/DRIVERS/USART" \
-I"./FRAMEWORK/DRIVERS/TC" \
-I"./FRAMEWORK/DRIVERS/SPI" \
-I"./FRAMEWORK/DRIVERS/PWM" \
-I"./FRAMEWORK/DRIVERS/PM" \
-I"./FRAMEWORK/DRIVERS/INTC" \
-I"./FRAMEWORK/DRIVERS/GPIO" \
-I"./FRAMEWORK/DRIVERS/FLASHC" \
-I"./FRAMEWORK/DRIVERS/CPU/CYCLE_COUNTER" \
-I"./FRAMEWORK/BOARDS" \
-I"./FRAMEWORK/DRIVERS/ADC"
DRIVER_PATH = ./FRAMEWORK/DRIVERS
all: libraries main
main:
$(CC) $(CFLAGS) $(COMP_INC) $(LIB_INC) -o"Debug/$@.o" "ControllerR3.c"
$(CC) "Debug/adc.o" "Debug/flashc.o" "Debug/gpio.o" "Debug/intc.o" "Debug/pm.o" "Debug/pwm.o" "Debug/tc.o" "Debug/usart.o" "Debug/spi.o" "Debug/main.o" "Debug/delay.o" \
-o Debug/CookerControlR3.elf
libraries: adc.c flashc.c gpio.c intc.c pm.c pwm.c spi.c tc.c usart.c delay.c
adc.c:
$(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/ADC/$@"
flashc.c:
$(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/FLASHC/$@"
gpio.c:
$(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/GPIO/$@"
intc.c:
$(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/INTC/$@"
pm.c:
$(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/PM/$@"
pwm.c:
$(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/PWM/$@"
spi.c:
$(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/SPI/$@"
tc.c:
$(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/TC/$@"
usart.c:
$(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/USART/$@"
delay.c:
$(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" -I"FRAMEWORK/DRIVERS/CPU/CYCLE_COUNTER" "FRAMEWORK/SERVICES/DELAY/$@"
Это успешно создает все различные объектные файлы, а затем завершается ошибкой на этапе связывания с помощью:
C:\[snip - private]/./FRAMEWORK/DRIVERS/GPIO/gpio.h:507: multiple definition of `gpio_local_clr_gpio_open_drain_pin'
Debug/gpio.o:C:\[snip - private]/./FRAMEWORK/DRIVERS/GPIO/gpio.h:507: first defined here
Debug/main.o: In function `gpio_local_tgl_gpio_open_drain_pin':
C:\[snip - private]/./FRAMEWORK/DRIVERS/GPIO/gpio.h:525: multiple definition of `gpio_local_tgl_gpio_open_drain_pin'
Debug/gpio.o:C:\[snip - private]/./FRAMEWORK/DRIVERS/GPIO/gpio.h:525: first defined here
Debug/main.o: In function `usart_reset_status':
C:\[snip - private]/./FRAMEWORK/DRIVERS/USART/usart.h:409: multiple definition of `usart_reset_status'
Debug/usart.o:C:\[snip - private]/./FRAMEWORK/DRIVERS/USART/usart.h:409: first defined here
Debug/main.o: In function `usart_parity_error':
[snip a hundred or so lines]
Очевидно, у меня проблема с несколькими определениями.
На данный момент, я немного над моей головой. У меня нет большого опыта разработки на C, и просто доводить make-файл до того места, где он сейчас находится, потребовалось много чтения.
Что вызывает многократные проблемы определения, которые я имею здесь? Какие изменения мне нужно внести в make-файл, чтобы предотвратить это?
Я знаю, что этот проект был успешно построен в прошлом, так как у нас есть аппаратное устройство, которое фактически выполняет его. Тем не менее, мне нужно внести некоторые изменения, так что просто использование существующей скомпилированной версии больше не приемлемо.
Существующая версия была построена внешним подрядчиком, который больше не доступен, поэтому я не могу спросить их, как они сделали это.
2 ответа
Хорошо, оказалось, что я использовал слишком свежую IDE.
Я открыл проект в правильной среде IDE (в данном случае, в более старой версии студии Atmel avr32, основанной на Eclipse), и он каким-то образом автоматически определил структуру и собрал все правильно.
В любом случае, хотя я не столько решил проблему, сколько избежал ее, я отмечаю этот вопрос как ответ. Я уже потратил слишком много времени, пытаясь понять, что делает затмение.
Похоже, у вас есть функция, реализованная в ваших заголовочных файлах. Когда вы компилируете object1 и object2 (скажем, main.o и gpio.o), ваш код дублируется в обоих объектах, и они не могут быть связаны друг с другом.
В этой ситуации обычно я оставляю объявление функции в заголовочном файле и перемещаю ее реализацию в один из объектных кодов (независимо от того, какой).
Можете ли вы подтвердить, что по адресу "gpio.h:507" у вас есть реализация, а не только подпись функции?