Files in lib compile but linker can't find them (resolved)

I created an example project to demonstrate this problem (likely a misunderstanding on my part). It seems that if I add libraries in my project’s lib/ folder that they compile, but the linker can’t find functions within them. Hopefully someone can slap some knowledge on me.

$ tree
.
├── include
│   └── README
├── lib
│   ├── README
│   └── foo
│       └── src
│           ├── foo.c
│           └── foo.h
├── platformio.ini
├── src
│   └── main.cpp
└── test
    └── README

6 directories, 7 files

$ cat lib/foo/src/foo.h lib/foo/src/foo.c src/main.cpp

--- foo.h
void fooCall();
--- foo.c
void fooCall() {
        int x = 0;
}
--- main.cpp
#include "Arduino.h"
#include <foo.h>

void setup()
{
}

void loop()
{
  fooCall();
}
$ pio run
Processing nodemcuv2 (platform: espressif8266; board: nodemcuv2; framework: arduino)
---------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif8266/nodemcuv2.html
PLATFORM: Espressif 8266 2.2.3 > NodeMCU 1.0 (ESP-12E Module)
HARDWARE: ESP8266 80MHz, 80KB RAM, 4MB Flash
PACKAGES: toolchain-xtensa 2.40802.190218 (4.8.2), tool-esptool 1.413.0 (4.13), tool-esptoolpy 1.20600.0 (2.6.0), framework-arduinoespressif8266 2.20502.0 (2.5.2)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 32 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <foo>
Building in release mode
Linking .pio/build/nodemcuv2/firmware.elf
/Users/nebulous/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: .pio/build/nodemcuv2/src/main.cpp.o:(.text.loop+0x0): undefined reference to `fooCall()'
/Users/nebulous/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: .pio/build/nodemcuv2/src/main.cpp.o: in function `loop':
main.cpp:(.text.loop+0xa): undefined reference to `fooCall()'
collect2: error: ld returned 1 exit status
*** [.pio/build/nodemcuv2/firmware.elf] Error 1
======================================================== [FAILED] Took 1.48 seconds ========================================================
$

It looks like a C / C++ mismatch. foo.h is included both from C files (foo.c) and C++ (main.cpp). The two languages by default use different rules to generate the function names for the linker and therefore a mismatch occurs.

There are two ways to fix it:

  • Use C++ only (or use C only)
  • Mark the functions implemented in C with extern "C" so C++ applies to correct naming rules.

The latter option looks like so (for foo.h):

#ifdef __cplusplus
extern "C" {
#endif

void fooCall();

#ifdef __cplusplus
}
#endif
2 Likes

Right you are, @manuelbl! Thanks.