MightyPork
MightyPork

Reputation: 18881

Multiple definitions of - GCC bogus error

I have a header file lcd.h with this (shortened):

#pragma once
// ...
const uint8_t LCD_ROW_ADDR[] = {0x00, 0x40, 0x14, 0x54};
// ... other prototypes and macros...

And a file lcd.c where this variable is used:

#include <stdbool.h>
#include <stdint.h>
// ...

#include "lcd.h"

// ...

/** Set cursor position */
void lcd_xy(const uint8_t x, const uint8_t y)
{
    lcd_set_addr(LCD_ROW_ADDR[y] + (x));
}

I include lcd.h in main.c, and lcd.c is compiled separately using makefile.

I'm getting this error: "multiple definition of `LCD_ROW_ADDR'"

avr-gcc -std=gnu99 -mmcu=atmega328p -DF_CPU=16000000UL -I. -Ilib/ -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wno-main -Wno-strict-prototypes -Wno-comment -g2 -Wextra -Wfatal-errors -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax -DDEBO_CHANNELS=6 -DDEBO_TICKS=1 -Os main.c lib/debounce.c lib/lcd.c lib/adc.c  --output main.elf
/tmp/ccgfa1iK.o: In function `lcd_xy':
/home/ondra/git/avr-projects/devel/lcdsnake/lib/lcd.c:203: multiple definition of `LCD_ROW_ADDR'
/tmp/cc0iT39O.o:/home/ondra/git/avr-projects/devel/lcdsnake/main.c:424: first defined here
/usr/bin/avr-ld: Disabling relaxation: it will not work with multiple definitions
collect2: error: ld returned 1 exit status
Makefile:87: recipe for target 'main.elf' failed
make: *** [main.elf] Error 1

I have checked the files multiple times and there is no other definition of the variable. The "first defined here" is a lie, the line in main.c contains an infinite loop code, nothing related to this.

What's going on here?

(ps. If I move the variable into the lcd.c file, it compiles OK - but I want to have it in the header file, so it can be accessed from elsewhere, too)

Upvotes: 1

Views: 3845

Answers (1)

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798884

ld is correct. You have the same variable defined in two separate compilation units thanks to the header.

The way to fix this is to declare it extern in the header, and have only one of the units redeclare it without the extern qualifier in its .c file.

Upvotes: 5

Related Questions