Building a library issue and workaround

Greetings!

I am a happy PlatformIO user - great IDE! I’ve used it for a couple of projects around the house. Decided to refactor the common code into a library. The code is very specific to my in-house environment setup, so I don’t intend to publish it to the PlatformIO registry. Source lives on my local git repo (gitea).

The one problem I had is the insistence of the linker to have setup() and loop():

xtensa-lx106-elf/bin/ld: .pio/build/lib_iot/libFrameworkArduino.a(core_esp8266_main.cpp.o):(.text._ZL12loop_wrapperv+0x8): undefined reference to `setup'
xtensa-lx106-elf/bin/ld: .pio/build/lib_iot/libFrameworkArduino.a(core_esp8266_main.cpp.o):(.text._ZL12loop_wrapperv+0xc): undefined reference to `loop'

Why would a library project need any of those (or main() for that matter) to build successfully? Seems to me that it is trying to build a deployable image, and I can’t figure the reasoning behind it. It’s a library - it needs to be used in proper application code where setup()|loop()|main() will be provided.

I read a number of posts with ideas on how to workaround this issue. Suggestions are around adding example or test code. I don’t believe test/examples should be required so the library builds. (And certainly test/example code shouldn’t get deployed.)

In the end I settled with a workaround I am least unhappy with. It involves having at least a placeholder test code. But I can build just the library without errors. The suboptimal assumption here is that the library is source referenced from the consuming project, rather than as a precompiled binary. And since I didn’t find this particular workaround, I am sharing it here. Answers to my “why” question above would be appreciated, or any comments on a better (simpler) workaround.

The gist is having two separate project environments. One for the lib, and for its tests. When building just the lib (pio run -e lib_iot) dummy setup() and loop() are provided via a compiler define that’s only in the lib environment. When building tests (pio test -e lib_test) proper setup() and loop() are provided.

platformio.ini

[env]
platform = espressif8266
board = nodemcuv2
framework = arduino
lib_deps = bblanchon/ArduinoJson@6.21.3
monitor_speed = 115200

[env:lib_iot]
build_flags = -DLIB_PROJECT

[env:lib_test]
test_build_src = true
build_type = debug
monitor_filters = esp8266_exception_decoder

In some library .cpp file:

#ifdef LIB_PROJECT
void setup() {}
void loop() {}
#endif

Cheers! :slight_smile:

1 Like

PlatformIO doesn’t really have the concept of “library projects”. It always builds a full a firmware – everything is a firmware project. Hence when you create a (PlatformIO/ Arduino) library, the common way to test compilation is by either including the library in a regular firmware project and make use of it there, or use CI commands pio ci / pio run -d .. to test compilation of the library in specific example sketches that the library should have in examples/. See e.g. docs.

Right - I figured/read all that. But why “It always builds a full a firmware”? Restrictions imposed by the hardware platforms? Long establish practice in the SoC industry? Design decision by the PlatformIO team? Lack of resources/people, but ability to build a pure library is on the road map?