arkhipenko / TaskScheduler

Cooperative multitasking for Arduino, ESPx, STM32, nRF and other microcontrollers
http://playground.arduino.cc/Code/TaskScheduler
BSD 3-Clause "New" or "Revised" License
1.2k stars 221 forks source link

"multiple definition of" linker errors if TaskScheduler.h included in multiple header/source files #189

Closed mattbaker-digital closed 2 weeks ago

mattbaker-digital commented 2 weeks ago

For example:

main.cpp

#include <TaskScheduler.h>
int main() {}

foo.cpp

#include <TaskScheduler.h>

Causes the following error when compiled using PlatformIO:

Linking .pio\build\teensy41\firmware.elf
c:/users/matt.baker/.platformio/packages/toolchain-gccarmnoneeabi-teensy/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld.exe: .pio\build\teensy41\src\main.cpp.o: in function `TS::Task::~Task()':
main.cpp:(.text._ZN2TS4TaskD2Ev+0x0): multiple definition of `TS::Task::~Task()'; .pio\build\teensy41\src\foo.cpp.o:foo.cpp:(.text._ZN2TS4TaskD2Ev+0x0): first defined here
c:/users/matt.baker/.platformio/packages/toolchain-gccarmnoneeabi-teensy/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld.exe: .pio\build\teensy41\src\main.cpp.o: in function `TS::Task::~Task()':
main.cpp:(.text._ZN2TS4TaskD2Ev+0x0): multiple definition of `TS::Task::~Task()'; .pio\build\teensy41\src\foo.cpp.o:foo.cpp:(.text._ZN2TS4TaskD2Ev+0x0): first defined here
c:/users/matt.baker/.platformio/packages/toolchain-gccarmnoneeabi-teensy/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld.exe: .pio\build\teensy41\src\main.cpp.o: in function `TS::Task::~Task()':
main.cpp:(.text._ZN2TS4TaskD0Ev+0x0): multiple definition of `TS::Task::~Task()'; .pio\build\teensy41\src\foo.cpp.o:foo.cpp:(.text._ZN2TS4TaskD0Ev+0x0): first defined here
...

The same applies if using TScheduler.hpp

Based on some quick testing, I believe this is due to not inlining the methods inside TaskScheduler.h and trying to rely on the inlines in TaskSchedulerDeclarations.h instead.

mattbaker-digital commented 2 weeks ago

Would it not be better to have a cpp file with this stuff in instead of just headers?

mattbaker-digital commented 2 weeks ago

I see this is a duplicate. However, based on how many times this has been raised before, I do wonder if there is a better way?

https://github.com/arkhipenko/TaskScheduler/issues?q=is%3Aissue+is%3Aclosed++multiple+definition

arkhipenko commented 2 weeks ago

There is a better way, but it requires total redesign of the library. There are a number of compile options driven by #define statements Arduino IDE ignores defines unless the entire library is in one header file. If I move back to h/cpp I will lose compile options. Given the workaround it is not that bad/critical to sacrifice backward-compatibility.

mattbaker-digital commented 2 weeks ago

@arkhipenko thanks for the explanation. I was unaware of the Arduino IDE limitation.