1

Boardcomputer.h:

#ifndef BOARDCOMPUTER_H
#define BOARDCOMPUTER_H

#include <Arduino.h>
#include <TFT_eSPI.h>

TFT_eSPI disp = TFT_eSPI();

...

#endif

Boardcomputer.cpp:

#include <Boardcomputer.h>

^^use disp functions^^
...

Error:

.pio\build\EmmaChip\lib782\libBoardcomputer.a(Boardcomputer.cpp.o):(.bss.disp+0x0): multiple definition of `disp'
.pio\build\EmmaChip\src\main.cpp.o:(.bss.disp+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\EmmaChip\firmware.elf] Error 1

Here is what I tried:

  • make an extra Header-File and add #pragma once at the top
  • make an extra Lib and add the typical #ifndef; #define; #endif lines

Do you have some ideas to fix this problem? I don't define 'disp' multiple times. Just in one Header.

hyde
  • 60,639
  • 21
  • 115
  • 176
Levi
  • 31
  • 6
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/243406/discussion-on-question-by-levi-how-do-i-avoid-the-multiple-definition-of-e). – Samuel Liew Mar 29 '22 at 10:25

1 Answers1

3

The problem is here:

#ifndef BOARDCOMPUTER_H
#define BOARDCOMPUTER_H

#include <Arduino.h>
#include <TFT_eSPI.h>

TFT_eSPI disp = TFT_eSPI();    
...    
#endif

You define disp in a header file. Defining variables in header files is plain wrong, it cannot work (except if you include the .h file in a single .c file, but then the .h file is pretty pointless anyway) and it leads to these "multiple definition" issues at link time.

This happens here:

  • you include Boardcomputer.h in foo.c, therefore foo.o will contain a variable disp. The code compile fine.
  • you include Boardcomputer.h in bar.c, therefore bar.o will contain a variable disp. The code compile fine.
  • you link foo.o and bar.o in order to produce an executable, and the linker sees two variables disp, one in bar.o and one in foo.o, hence the multiple definition error

You want this:

Boardcomputer.h

#ifndef BOARDCOMPUTER_H
#define BOARDCOMPUTER_H

#include <Arduino.h>
#include <TFT_eSPI.h>

extern TFT_eSPI disp;     // declare it here
    
#endif

Boardcomputer.c

#include "Boardcomputer.h"
...
TFT_eSPI disp = TFT_eSPI();   // define it here
...
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • I still don't understand why the linker complains. Shouldn't the header guards make sure that there is only one global "disp" defined? If `foo.c` includes `Boardcomputer.h` then `bar.c` won't include it because of the header guard. Hence, the shouldn't be a second definition of "disp". What's the mistake in my thoughts here? – Joerg Apr 19 '23 at 18:59
  • @Joerg no, the linker has no knowledge of header guards at all. Your favorite C text book should explain the process of compiling and linking. You can also read this: https://stackoverflow.com/questions/3322911/what-do-linkers-do – Jabberwocky Apr 19 '23 at 20:12
  • I've just read this: "Note that the goal of header guards is to prevent a code file from receiving more than one copy of a guarded header. By design, header guards do not prevent a given header file from being included (once) into separate code files." in https://www.learncpp.com/cpp-tutorial/header-guards/ Maybe it helps others too who have become a bit rusty in their C++. – Joerg Apr 19 '23 at 20:21