'undefined reference'-Error when using 'extern'

Hello,
I’m having some trouble on my Smarthome ESP32 project.
First of all, the link to the github repository:

After educating myself about propper C++ coding im currently applying a propper code style guideline to the code at the moment, if you want to take a look at the most current code check out “fb_9_refactor_codebase”.

The project uses global instances of two classes, a logger that provides formatted outputs and a system timer that syncs time via network to correctly timestamp received signals.

Before refactoring (having all code inside of the .h files) we were able to simply write ConsoleLogger logger; at the end of the console_logger.h and include the file in every other file and use logger.println() to print messages.
Now, however, when doing this we get a ton of multiple definition of 'logger'-Erros when the linker tries to link all the files, because there is a instance of ConsoleLogger called logger created for every seperate .cpp-File created.

Using static works, but there is still an instance for every .cpp file created, which in case of the logger bricks format (since the indentation is not synced between classes) and the timer doesn’t work at all.

The propper way to do this seems to be using extern - but doing so creates the following error:

Linking .pio/build/esp32cam/firmware.elf
.pio/build/esp32cam/src/connectors/connectors.cpp.o:(.literal._ZN12IR_Connector9sendRawIREPKth+0x4): undefined reference to `logger'
collect2: error: ld returned 1 exit status

The logger is included in the connectors.cpp.

Im really thankful for every tip anyone of you can provide, a already got some great help with another issue :slight_smile:

Thanks in advance,
J. Klink

I didn’t look into your project in detail. But it sounds like a simple C++ issue.

You need both a declaration and a definition.

The declaration (variable with extern or function without body) can be used in many places as it just informs about the existence of a variable or function.

The definition (variable without extern or function with body) is required exactly once as it creates the variable or function.

Declaration

In console_logger.h:

extern ConsoleLogger logger;

Definition

In console_logger.cpp:

ConsoleLogger logger;
1 Like

Read up on the difference between a definition and a declaration.
Basically a name (function, variable, whatever) should be defined once in a .c (or .cpp or whatever) source file. It can be declared (i.e. just the name, type etc.) in a .h (or .hpp…) file that is included in all of the other source files that want to access the variable/function/…
The uses of ‘static’ and ‘extern’ are also different (and also can differ between C and C++). ‘static’ means that the name is visible only in that source file (remember in that included files are simply read in as text into the file that includes them) and therefore it must apply to a definition. ‘extern’ means that the name can be used in this file BUT it is actually defined in another file (where is cannot be ‘static’).
Susan

1 Like

Thank you so much @manuelbl and @aussiesusan!

The Problem was exactly what you suspected, when changing the static to extern i did not bother to add the definition to the .cpp-file.

In general i guess i have a good understanding what declaration and definitions are, but using extern for the first time i did not think about needing a separate definition since static worked without one :roll_eyes: