Using external libraries in the lib folder?

Hi to everyone.

Currently, I try to structure my project and have the following problem:

In my lib-folder, I have a folder called “my_display”. Here I have “my_display.h” and a “my_display.c” file.
I include the “my_display.h” file in my “src/main.cpp” file, which works fine. But when I add an external library to my “my_display.h” I cannot build the project anymore.

The “my_display.h” looks like this:

#include <Arduino.h>
#include <TFT_eSPI.h> //by Bodmer v2.4.2
#include <SPI.h>

void newLine();
void drawtext(char *, int16_t, int16_t, uint16_t);

int16_t lastCursorX = 0;
int16_t lastCursorY = 0;

TFT_eSPI tft = TFT_eSPI();

and this is the “my_display.c”

#include "my_display.h"


void newLine() {
  lastCursorX = 0;
  lastCursorY = lastCursorY+11;
}


void drawtext(char *text, int16_t x, int16_t y, uint16_t color) {
  tft.setCursor(x, y);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.print(text);
  lastCursorX = tft.getCursorX();
  lastCursorY = tft.getCursorY();
}

If it is helpful, this is my platformio.ini:

[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
framework = arduino
upload_port = /dev/ttyUSB1
monitor_rts = 0
monitor_dtr = 0
upload_speed = 230400
lib_deps =
    adafruit/DHT sensor library @ 1.3.0
    adafruit/Adafruit Unified Sensor@^1.1.5
    arduino-libraries/NTPClient@^3.1.0
    paulstoffregen/Time@^1.6.1
    bodmer/TFT_eSPI@^2.4.42
    jchristensen/Timezone@^1.2.4
    bodmer/JPEGDecoder@^1.8.1

The error-output looks like this:

Compiling .pio/build/nodemcuv2/lib1fd/my_display/my_display.c.o
In file included from /home/user/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/Print.h:27,
                 from .pio/libdeps/nodemcuv2/TFT_eSPI/TFT_eSPI.h:31,
                 from lib/my_display/my_display.h:2,
                 from lib/my_display/my_display.c:1:
/home/user/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/Printable.h:25:1: error: unknown type name 'class'
   25 | class Print;
      | ^~~~~
/home/user/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/Printable.h:33:1: error: unknown type name 'class'
   33 | class Printable {
      | ^~~~~
/home/user/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/Printable.h:33:17: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
   33 | class Printable {
      |                 ^
In file included from .pio/libdeps/nodemcuv2/TFT_eSPI/TFT_eSPI.h:31,
                 from lib/my_display/my_display.h:2,
                 from lib/my_display/my_display.c:1:
/home/user/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/Print.h:36:1: error: unknown type name 'class'
   36 | class Print {
      | ^~~~~
/home/user/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/Print.h:36:13: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
   36 | class Print {
      |             ^
/home/user/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/Print.h:120:9: error: expected '=', ',', ';', 'asm' or '__attribute__' before '<' token
  120 | template<> size_t Print::printNumber(double number, uint8_t digits);
      |         ^
In file included from .pio/libdeps/nodemcuv2/TFT_eSPI/TFT_eSPI.h:32,
                 from lib/my_display/my_display.h:2,
                 from lib/my_display/my_display.c:1:
/home/user/.platformio/packages/framework-arduinoespressif8266/libraries/SPI/SPI.h:43:1: error: unknown type name 'class'
   43 | class SPISettings {
      | ^~~~~
/home/user/.platformio/packages/framework-arduinoespressif8266/libraries/SPI/SPI.h:43:19: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
   43 | class SPISettings {
      |                   ^
/home/user/.platformio/packages/framework-arduinoespressif8266/libraries/SPI/SPI.h:52:1: error: unknown type name 'class'
   52 | class SPIClass {
      | ^~~~~
/home/user/.platformio/packages/framework-arduinoespressif8266/libraries/SPI/SPI.h:52:16: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
   52 | class SPIClass {
      |                ^
/home/user/.platformio/packages/framework-arduinoespressif8266/libraries/SPI/SPI.h:86:8: error: unknown type name 'SPIClass'
   86 | extern SPIClass SPI;
      |        ^~~~~~~~
In file included from .pio/libdeps/nodemcuv2/TFT_eSPI/Processors/TFT_eSPI_ESP8266.h:35,
                 from .pio/libdeps/nodemcuv2/TFT_eSPI/TFT_eSPI.h:67,
                 from lib/my_display/my_display.h:2,
                 from lib/my_display/my_display.c:1:
/home/user/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/FS.h:24:10: fatal error: memory: No such file or directory
   24 | #include <memory>
      |          ^~~~~~~~
compilation terminated.
*** [.pio/build/nodemcuv2/lib1fd/my_display/my_display.c.o] Error 1
In file included from .pio/libdeps/nodemcuv2/TFT_eSPI/TFT_eSPI.h:868,
                 from lib/my_display/my_display.h:2,
                 from src/main.cpp:17:

My understanding of the problem is, that “TFT_eSPI.h” and/or “SPI.h” have dependencies, which cannot be found, because they are used in another directory (“libs/my_display”) instead of “src/”. And I have no glue how I can fix this.

Does anyone know what I am doing wrong? Am very grateful for any help.

(I’m using the VS-Code-Plugin of Platformio on Ubuntu 21.10.)

So… in a .c file you are include a header which pulls a ton pf C++ classes? Uh?

Try renaming it to my_display.cpp.

Thank you maxgerhardt! This brought me a step further, but sadly didn’t solve my problem completely.
I renamed the my_display.c to my_display.cpp and now I’m getting this warning and error:

/home/user/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld: .pio/build/nodemcuv2/lib1fd/libmy_display.a(my_display.cpp.o):(.bss.lastCursorX+0x0): multiple definition of `lastCursorX'; .pio/build/nodemcuv2/src/main.cpp.o:(.bss.lastCursorX+0x0): first defined here
/home/user/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld: .pio/build/nodemcuv2/lib1fd/libmy_display.a(my_display.cpp.o):(.bss.lastCursorY+0x0): multiple definition of `lastCursorY'; .pio/build/nodemcuv2/src/main.cpp.o:(.bss.lastCursorY+0x0): first defined here
/home/user/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld: .pio/build/nodemcuv2/lib1fd/libmy_display.a(my_display.cpp.o): in function `_Z7newLinev':
my_display.cpp:(.text._Z7newLinev+0x8): multiple definition of `_Z7newLinev'; .pio/build/nodemcuv2/src/main.cpp.o:main.cpp:(.text._Z7newLinev+0x8): first defined here
/home/user/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld: .pio/build/nodemcuv2/lib1fd/libmy_display.a(my_display.cpp.o):(.bss.tft+0x0): multiple definition of `tft'; .pio/build/nodemcuv2/src/main.cpp.o:(.bss.tft+0x0): first defined here
collect2: error: ld returned 1 exit status
*** [.pio/build/nodemcuv2/firmware.elf] Error 1

Continuing the discussion from Using external libraries in the lib folder?:

I was able to solve one error above. multiple definition of _Z7newLinev’;` was easy to find. But now, I’m looking at this:

Linking .pio/build/nodemcuv2/firmware.elf
/home/user/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld: .pio/build/nodemcuv2/lib1fd/libmy_display.a(my_display.cpp.o):(.bss.lastCursorX+0x0): multiple definition of `lastCursorX'; .pio/build/nodemcuv2/src/main.cpp.o:(.bss.lastCursorX+0x0): first defined here
/home/user/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld: .pio/build/nodemcuv2/lib1fd/libmy_display.a(my_display.cpp.o):(.bss.lastCursorY+0x0): multiple definition of `lastCursorY'; .pio/build/nodemcuv2/src/main.cpp.o:(.bss.lastCursorY+0x0): first defined here
/home/user/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld: .pio/build/nodemcuv2/lib1fd/libmy_display.a(my_display.cpp.o):(.bss.tft+0x0): multiple definition of `tft'; .pio/build/nodemcuv2/src/main.cpp.o:(.bss.tft+0x0): first defined here
collect2: error: ld returned 1 exit status
*** [.pio/build/nodemcuv2/firmware.elf] Error 1

I checked multiple times, that lastCursorX, lastCursorY and tft doesn’t have multiple declarations. I assume there is something wrong with my include-statements.

I have #include "my_display.h" in my #include "my_display.cpp"and also in my main.cpp, but when I remove one of them, the IDE is showing me errors instantly (that variables, which are defined in my_display.h, couldn’t be found.)

I was able to solve the problem completely!

I moved the variables from my_display.h to my_display.cpp and created some Getter- and Setter-functions. Afterwards, I replaced the variables-calls with the according Getter- and Setter-functions. This solved my problems, and I was able to compile the code.

So in total I had three mistakes:

  • Wrong file-extension (.c instead of the correct .cpp)
  • A duplicate definition of void newLine() (on in my my_display.cpp-file and the other one in my main.cpp (<- this one was too much.))
  • I used global variables, which were not good. Fixed by using getter and setter functions.