Undefined reference error during linking happened sadly

Hello everyone,

I successfully compiled a project in Arduino IDE, and now I want to migrate it to PlatformIO for development. However, I encountered the following issue:

Linking .pio\build\due\firmware.elf
.pio\build\due\src\main.cpp.o: In function `mapEmptyBuffers()':
main.cpp:(.text._Z15mapEmptyBuffersv+0x78): undefined reference to `bool_output'
main.cpp:(.text._Z15mapEmptyBuffersv+0x80): undefined reference to `int_output'
main.cpp:(.text._Z15mapEmptyBuffersv+0x84): undefined reference to `bool_input'
main.cpp:(.text._Z15mapEmptyBuffersv+0x88): undefined reference to `int_input'
.pio\build\due\src\main.cpp.o: In function `modbusTask()':
main.cpp:(.text._Z10modbusTaskv+0xb8): undefined reference to `bool_output'
main.cpp:(.text._Z10modbusTaskv+0xbc): undefined reference to `int_output'
main.cpp:(.text._Z10modbusTaskv+0xc4): undefined reference to `int_input'
main.cpp:(.text._Z10modbusTaskv+0xc8): undefined reference to `bool_input'
.pio\build\due\src\main.cpp.o: In function `plcCycleTask()':
main.cpp:(.text._Z12plcCycleTaskv+0x2): undefined reference to `updateInputBuffers'
main.cpp:(.text._Z12plcCycleTaskv+0xe): undefined reference to `config_run__'
main.cpp:(.text._Z12plcCycleTaskv+0x12): undefined reference to `updateOutputBuffers'
main.cpp:(.text._Z12plcCycleTaskv+0x1a): undefined reference to `updateTime'
.pio\build\due\src\main.cpp.o: In function `setup':
main.cpp:(.text.setup+0xe): undefined reference to `config_init__'
main.cpp:(.text.setup+0x12): undefined reference to `glueVars'
main.cpp:(.text.setup+0x16): undefined reference to `hardwareInit'
main.cpp:(.text.setup+0x54): undefined reference to `common_ticktime__'
.pio\build\due\lib1a8\libModbusSlave.a(ModbusSlave.cpp.o): In function `debugInfo()':
ModbusSlave.cpp:(.text._Z9debugInfov+0x2): undefined reference to `get_var_count'
.pio\build\due\lib1a8\libModbusSlave.a(ModbusSlave.cpp.o): In function `debugSetTrace(unsigned short, unsigned char, unsigned short, void*)':
ModbusSlave.cpp:(.text._Z13debugSetTracethtPv+0xc): undefined reference to `get_var_count'
ModbusSlave.cpp:(.text._Z13debugSetTracethtPv+0x38): undefined reference to `set_trace'
.pio\build\due\lib1a8\libModbusSlave.a(ModbusSlave.cpp.o): In function `debugGetTrace(unsigned short, unsigned short)':
ModbusSlave.cpp:(.text._Z13debugGetTracett+0x8): undefined reference to `get_var_count'
ModbusSlave.cpp:(.text._Z13debugGetTracett+0x24): undefined reference to `get_var_size'
ModbusSlave.cpp:(.text._Z13debugGetTracett+0x3c): undefined reference to `get_var_addr'
.pio\build\due\lib1a8\libModbusSlave.a(ModbusSlave.cpp.o): In function `debugGetTraceList(unsigned short, unsigned char*)':
ModbusSlave.cpp:(.text._Z17debugGetTraceListtPh+0x8): undefined reference to `get_var_count'
ModbusSlave.cpp:(.text._Z17debugGetTraceListtPh+0x8e): undefined reference to `get_var_size'
ModbusSlave.cpp:(.text._Z17debugGetTraceListtPh+0xa0): undefined reference to `get_var_addr'
.pio\build\due\lib1a8\libModbusSlave.a(ModbusSlave.cpp.o): In function `debugGetMd5(void*)':
ModbusSlave.cpp:(.text._Z11debugGetMd5Pv+0x10): undefined reference to `set_endianness'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\due\firmware.elf] Error 1

I have followed the README instructions to create subfolders in the lib folder and moved all files except main.cpp into these subfolders. Here is my project.

If anyone has time, please help me solve this problem. I sincerely appreciate it!

You are having very fundamental problems with understanding C/C++ interworking and the PlatformIO library build system. Let’s go through them.

grafik

Why does the debug.h header not declare the functions with extern "C" if it is included by a C file? Since you wrote it as debug.c and not debug.cpp, when calling functions from a C file from a C++ file, the C functions have to be declared as being extern "C" for C++ files.

https://isocpp.org/wiki/faq/mixing-c-and-cpp#include-c-hdrs-personal

Due to name mangling, the expected symbols will be different.

Of course, it could also be that you mean to name all these files as .cpp and not .c.

Further, it is problematic that you have libraries which don’t have any include files, like the “glueVars” “library”.

grafik

With PlatformIO, a library is only compiled if a library is actively detected as being included. When a library has no header file to include, it can also not be detected. Thoroughly read through

https://docs.platformio.org/en/latest/librarymanager/index.html

to understand this. This glueVars.c should probably be either in the src/ folder or in the library that needs these variables.

As a quickfix, you can add

lib_ldf_mode = deep+
lib_deps =
  glueVars ; force this library to be built
  arduino ; same goes for this library

to the platformio.ini. In this case, lib_ldf_mode “deep+” is needed because otherwise this no-header library does not detect the usage of the iec_std_lib.h library.

Same goes for the arduino library. However, since arduino.cpp additionally wants

#if defined(__SAM3X8E__) || defined(__SAMD21G18A__)
    #include "SAMD_PWM.h"
#else
    #include "AVR_PWM.h"
#endif

which likely means https://registry.platformio.org/libraries/khoih-prog/SAMD_PWM this library, you need to

  1. add a reference to that library with lib_deps (khoih-prog/SAMD_PWM@^1.2.0)
  2. due to the usage of conditional #if defined(..), you need deep+ LDF mode to detect the inclusion properly.

Which directly leads us to the next problem: The SAMD_PWM.h does not work for a Due. A Arduino Due does not have an Atmel SAMD chip on it.

Soo… how does this compile in the Arduino IDE? Did you select a different board there, or a modified version of the SAMD_PWM.h that works for a SAM3X8E chip?

FYI I made the project build artificially by just commenting out all lines related to the SAMD_PWM.h. This will of course not work during runtime. I’m very sure you have a different board selected in the Arduino IDE, it’s not a Due.

https://github.com/maxgerhardt/PlatformIO-project

See diff: https://github.com/Slidecarefully/PlatformIO-project/compare/main...maxgerhardt:PlatformIO-project:main

You should restructure the project. Just don’t use the lib/ folder, put everything in src/, your life will be easier for this project. No weird “libraries” that don’t even have a header file that you then artificially have to force-include in the build. I’m sure that, in the Arduino IDE, you also didn’t create “libraries” (as placed in e.g. C:\Users\<user>\Documents\Arduino\libraries), but those code files were just inside the sketch. Which, if true, means you’re not equivalently doing the same thing in PlatformIO: You’re converting them (wrongly) into libraries.

Hello Maxgerhardt,

Thank you so much for your prompt response—there’s no doubt you are an absolute genius in this field! I do have a few things to explain:

  1. In the Arduino IDE, I am not using the Arduino Due, but rather the Arduino Zero.I did this because I plan to use the Arduino Due later, but I obviously forgot that I was originally using the Arduino Zero in the Arduino IDE.But anyway, what I want to consult you about now is all related to the Arduino Zero board.
  2. After migrating all the files from the lib folder to src, the entire project actually worked! What you said was absolutely correct!

Now, I have a new question. Even though my code works smoothly on the Arduino Zero after applying your modifications, I noticed that the Inspect feature in PIO Home provided the following feedback about my project:

Should I address these issues? They don’t seem to affect my program’s functionality on the Arduino Zero, but they do appear to be potential bugs.