Difference between build_flags -I and lib_deps and collect2: error: ld returned 1 exit status *** [.pio/build/nano_33_iot/firmware.elf] Error 1

Hi All

I’m new with Platformio in VSCode and encountered a Problem:

Error while Building:

collect2: error: ld returned 1 exit status
*** [.pio/build/nano_33_iot/firmware.elf] Error 1

Hardware : Arduino Nano 33 IoT
Lib_To_Use: https://github.com/BriscoeTech/Arduino-FreRTOS-SAMD21

So I First Setup a simply Project to communicate with Arduino Nano which worked.

I downloaded the Repo from “Lib_To_Use” and unzipped it. I then added to Platformio.ini

platform = atmelsam
board = nano_33_iot
framework = arduino
build_flags = 
	-I  /Volumes/Cyberrange/Cyberrange/misc/ICS/Development/Arduino/Ressources/Arduino-FreeRTOS-SAMD21-master/src

While building the following Error Raised:

 *  Task wird ausgeführt: platformio run 

Processing nano_33_iot (platform: atmelsam; board: nano_33_iot; framework: arduino)
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelsam/nano_33_iot.html
PLATFORM: Atmel SAM (8.1.0) > NANO 33 IoT
HARDWARE: SAMD21G18A 48MHz, 32KB RAM, 256KB Flash
DEBUG: Current (atmel-ice) External (atmel-ice, blackmagic, jlink)
 - framework-arduino-samd @ 1.8.13 
 - framework-cmsis @ 1.40500.0 (4.5.0) 
 - framework-cmsis-atmel @ 1.2.2 
 - toolchain-gccarmnoneeabi @ 1.70201.0 (7.2.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 12 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
Linking .pio/build/nano_33_iot/firmware.elf
.pio/build/nano_33_iot/src/main.cpp.o: In function `taskMonitor(void*)':
main.cpp:(.text._Z11taskMonitorPv+0x10): undefined reference to `vTaskDelay'
main.cpp:(.text._Z11taskMonitorPv+0x34): undefined reference to `xPortGetFreeHeapSize'
main.cpp:(.text._Z11taskMonitorPv+0x54): undefined reference to `xPortGetMinimumEverFreeHeapSize'
main.cpp:(.text._Z11taskMonitorPv+0x8c): undefined reference to `vTaskGetRunTimeStats'
main.cpp:(.text._Z11taskMonitorPv+0xb8): undefined reference to `vTaskList'
main.cpp:(.text._Z11taskMonitorPv+0xde): undefined reference to `uxTaskGetStackHighWaterMark'
main.cpp:(.text._Z11taskMonitorPv+0xfa): undefined reference to `uxTaskGetStackHighWaterMark'
main.cpp:(.text._Z11taskMonitorPv+0x116): undefined reference to `uxTaskGetStackHighWaterMark'
.pio/build/nano_33_iot/src/main.cpp.o: In function `threadB(void*)':
main.cpp:(.text._ZL7threadBPv+0x20): undefined reference to `vTaskDelay'
.pio/build/nano_33_iot/src/main.cpp.o: In function `threadA(void*)':
main.cpp:(.text._ZL7threadAPv+0x24): undefined reference to `vTaskDelay'
main.cpp:(.text._ZL7threadAPv+0x36): undefined reference to `vTaskDelete'
.pio/build/nano_33_iot/src/main.cpp.o: In function `setup':
main.cpp:(.text.setup+0x4c): undefined reference to `vSetErrorLed'
main.cpp:(.text.setup+0x52): undefined reference to `vSetErrorSerial(arduino::Stream*)'
main.cpp:(.text.setup+0x68): undefined reference to `xTaskCreate'
main.cpp:(.text.setup+0x7e): undefined reference to `xTaskCreate'
main.cpp:(.text.setup+0x96): undefined reference to `xTaskCreate'
main.cpp:(.text.setup+0x9a): undefined reference to `vTaskStartScheduler'
collect2: error: ld returned 1 exit status
*** [.pio/build/nano_33_iot/firmware.elf] Error 1

After this I copied the content of [Path_To_Development]/Development/Arduino/Ressources/Arduino-FreeRTOS-SAMD21-master/src to the Projects src directory. And Like Magic it worked.

After Reading your docu I also learned that I can import lib_deps directly via git. So next I again deleted the files from the Project src Folder and changed my Platformio.ini to

platform = atmelsam
board = nano_33_iot
framework = arduino
lib_deps =

And Again it worked.

So my Question is:

What is the difference between those options. I Thought the "build_flags = -I […] just adds a include path to the compiler. Shouldn’t the result be the same as copying it to the Project src File ?



Not like magic. -I is not a “please include this library into my project” flag. It strictly adds a path to the include search-path of the compile. Include in the sense that a header file (.h) will then be found when referenced in a #include <filename.h> statement. It does not add potential source files (.c/.cpp) in that folder to the build process. It does not trigger that the compiler takes these library source files, compiles them to object files (.o), optionally creates an archive file (.a) out of those and links them into the final firmware (.elf). None of that happens when you use -I.

That does however happen when you reference a library with lib_deps, or (less standard) add these files to the build system using an additive src_filter statement.

The rule is simple: If you want to include a library that does not only have .h files but also .c/.cpp files, using -I will not work and you get exactly “undefined references” errors, meaning the compiler couldn’t find any actual implementation / code of the things it was told about in the header, because the .c/.cpp files that implement the functions, variables etc were never compiled and linked in the first place :slight_smile:

There are “header-only” libraries, no source files, in which this does work, but even then, try to use the regular library dependency system.

Thanks for this explaination :star_struck: