简体   繁体   English

了解与现有C程序的编译和链接

[英]Understanding compiling & linking with an existing C program

I've inherited a mildly-complicated C program for one of the AVR32 32 bit microprocessors. 我为一个AVR32 32位微处理器继承了一个稍微复杂的C程序。

However, I have no information about how to compile it. 但是,我没有有关如何编译它的信息。 I've been trying to put together a make-file for it for a bit now, and have been having no success. 我一直在尝试为它整理一个make-file,但一直没有成功。 Hopefully someone can tell me where I am going wrong. 希望有人可以告诉我我要去哪里错了。


Basically, I have a project structure that looks like this: 基本上,我有一个如下所示的项目结构:

/
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

Basically, ControllerR3.c includes adc.h , gpio.h , etc, and calls functions that are prototyped in those various header files. 基本上, ControllerR3.c包括adc.hgpio.h等,并调用在这些各种头文件中原型化的函数。 The actual functions in the various FRAMEWORK headers are actually defined in the .c files. .c文件中实际上定义了各种FRAMEWORK标头中的实际功能。

All the .h files are wrapped in include protections: 所有.h文件都包含在include保护中:

#ifndef _USART_H_
#define _USART_H_
{snip header file contents}
#endif  // _USART_H_

Now, as I understand it, I have to compile the various .c files into object ( .o ) files, and then call the linker to merge all the object files together in to the final executable (in this case, it's a .elf file). 现在,据我所知,我必须将各种.c文件编译成目标( .o )文件,然后调用链接程序将所有目标文件合并到最终的可执行文件中(在本例中为.elf文件)。
As such, I have written a small makefile: 因此,我编写了一个小的makefile:

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/$@"

This successfully builds all the various object files, and then fails at the linking stage with: 这将成功构建所有各种目标文件,然后在链接阶段失败,并显示以下内容:

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]

So obviously, I have a problem with multiple definitions. 显然,我对多个定义有疑问。

At this point, I'm a bit over my head. 在这一点上,我有点不知所措。 I don't have much experience with C development, and just getting the makefile to the point where it is now took a lot of reading. 我没有太多的C开发经验,只是使makefile达到现在需要大量阅读的程度。

What is causing the multiple definition issues I have here? 是什么导致我在这里遇到多个定义问题? What changes do I need to make to the makefile to prevent this? 为了防止这种情况,我需要对makefile进行哪些更改?

I know this project was built successfully in the past, as we have a hardware device that actually runs it. 我知道这个项目是过去成功构建的,因为我们有一个实际运行它的硬件设备。 However, I need to make some changes, so just using the existing compiled version is no-longer acceptable. 但是,我需要进行一些更改,因此不再需要使用现有的编译版本。

The existing version was built by an external-contractor who is no-longer available, so I can't really ask them how they made it work. 现有版本是由不再可用的外部承包商构建的,因此我无法真正询问他们如何使它工作。

It looks like you have a function implemented in your header files. 看起来您的头文件中实现了一个功能。 When you compile object1 and object2 (say main.o and gpio.o) you have your code duplicated in both object, and those cannot be linked together. 编译object1和object2(例如main.o和gpio.o)时,您的代码在两个对象中都重复了,并且无法将它们链接在一起。

In this situation typically I leave the declaration of the function in the header file and move its implementation in one of the object code (no matter which). 在这种情况下,通常我将函数的声明保留在头文件中,并将其实现移至目标代码之一(无论哪种)中。

Can you confirm that at "gpio.h:507" you have the implementation and not only the signature of the function? 您可以确认在“ gpio.h:507”中您具有实现,而不仅是功能的签名吗?

Well, it turned out I was using too recent an IDE. 好吧,原来我使用的是最近的IDE。

I opened the project in the correct IDE (in this case, the older version of Atmel avr32 studio that's based on eclipse), and it somehow automagically deduced the structure, and put everything together correctly. 我在正确的IDE(在本例中为基于eclipse的Atmel avr32 studio的较早版本)中打开了该项目,它以某种方式自动推断出结构,并将所有内容正确地组合在一起。

Anyways, while it's not so much that I solved the problem as avoided it, I'm marking this question as answered. 无论如何,虽然解决问题并不能避免,但是我将这个问题标记为已回答。 I've already spent too much time trying to figure out what eclipse is doing. 我已经花了太多时间试图弄清楚日食正在做什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM