Search code examples
c++classredefinitionplatformio

How do I avoid the "multiple definition of ..." Error in this case


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.


Solution

  • 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
    ...