Compile error for ESP32 target

Hi

I’m testing a newly released version of a library called H4Plugins.

The issue I’m facing is the following error code at compile :

lib\h4plugins-dev\src\H4P_udpLogger.cpp:47:28: error: 'class HardwareSerial' has no member named 'printf'

The same example compiles successfully on :

  • Arduino IDE 1.8.13.
  • ESP32 Arduino Core 1.0.4

PlatformIO Home : * 3.3.1
PlatformIO Core : * 5.0.4
VSCode About :

Version: 1.52.1 (user setup)
Commit: ea3859d4ba2f3e577a159bc91e3074c5d85c0523
Date: 2020-12-16T16:34:46.910Z
Electron: 9.3.5
Chrome: 83.0.4103.122
Node.js: 12.14.1
V8: 8.3.110.13-electron.0
OS: Windows_NT x64 10.0.18362

cutsom library used (installed under /lib):

platformio.ini :

[platformio]
default_envs = esp32doit-devkit-v1

[common]
framework = arduino
monitor_speed = 115200
lib_deps = 
  https://github.com/philbowles/PangolinMQTT@1.0.0
  https://github.com/philbowles/H4@1.0.0
  https://github.com/philbowles/ESPAsyncWebServer
upload_speed = 921600


[env:esp32doit-devkit-v1]
framework = ${common.framework}
platform = espressif32
board = esp32doit-devkit-v1

monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed}
build_flags = -w
  
lib_ldf_mode = deep+
lib_deps = ${common.lib_deps}
  https://github.com/me-no-dev/AsyncTCP
  https://github.com/plerup/espsoftwareserial

main.cpp :

#include<H4Plugins.h> // << Includes Arduino.h internally.
H4_USE_PLUGINS(115200,20,false) // Serial baud rate, Q size, SerialCmd autostop

H4P_FlasherController h4fc;
/*
Tested on STM32NUCLEO-F429ZI that has red, green dn blue LEDs onboard.
You will probably need to wire your own
and e.g #define LED_RED 99, LED_GREEN 23... etc
*/

#define LED_RED     20
#define LED_GREEN   27
#define LED_BLUE    14

void h4setup() { // H4 constructor starts Serial
    Serial.println("H4P_FlasherController Basic Example v"H4P_VERSION);
    pinMode(LED_RED,OUTPUT); // not required if H4P_GPIOManager used
    pinMode(LED_GREEN,OUTPUT);// not required if H4P_GPIOManager used
    pinMode(LED_BLUE,OUTPUT);// not required if H4P_GPIOManager used

    h4.everyRandom(5000,10000,[](){ 
        Serial.print(millis());Serial.println(" RUDE INTERRUPTION");
        h4fc.pulseLED(100,LED_BLUE);
    },nullptr,4);

    h4fc.flashLED(250,LED_GREEN);
    h4fc.flashMorse("... --- ...",150,LED_RED);
}

A sample of the project can be found here :
https://github.com/HamzaHajeir/platformio_test

Log by running : pio run -v >compile1.log :

Arduino IDE Log (with verbose) :

I can find a pattern, That’s these Serial.printf’s are called within Lambda’s.

Am I hitting right ?
What’s the solution ?

If you follow the definitions of VSCode for Serial and then into Stream and then into Print you will see that the library provides its own Print.h version

which overrides and conflicts with the Arduino-ESP32’s Print.h version. The library’s version gets included before the Arduino-ESP32’s core one.

Adding the line

    size_t printf(const char * format, ...)  __attribute__ ((format (printf, 2, 3)));

in https://github.com/philbowles/H4/blob/master/src/Print.h#L63 fixes the problem.


Checking size .pio\build\esp32doit-devkit-v1\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [=         ]   6.5% (used 21172 bytes from 327680 bytes)
Flash: [====      ]  37.7% (used 494363 bytes from 1310720 bytes)
esptool.py v3.0
================ [SUCCESS] Took 24.02 seconds ================

The library is attempting to fill in Arduino functionality on other platforms while overwriting the core’s functionality. The Print.h header should be called something differently to not conflict with the core, or do a #include_next if it detects that it’s running in the Arduino framework.

The Arduino IDE probably gets lucky having a different order of -I include flags that prioritizes the core’s files instead of the library one’s.

Hi, Thanks for your reply,

But it doesn’t seem that library calls #include<Print.h> in its own. following the definitions :

and :

At my side : VSCode lead me to HardwareSerial Serial(0); Arduino core definition.

This line is not called out because of ARDUINO definition guard :

In addition : Previous version of H4 (0.5.4) had Print.h* also, But successfully compiles the whole project in VSCode.

  • It was nested under src/inc/ instead of src/ as newer version. Would that make any changes in building ?

The pure existence of the file Print.h is the problem, it has 0 to do with if the file is being used by the library. The problem is that the way PlatformIO orders the -I include flags, when another library is built such as these plugins, the include order will be Arduino.h -> HardwareSerial.h -> Stream.h -> Print.h (from H4 library) and in that version there’s no printf().

In hindsight I thought of another thing: The library creates this Print.h header so that the printing API is unified across all platforms, like Linux Desktop, STM32, Raspbi, ESP8266. So a library should probably also only ever used this “agreed upon” API and do it with Serial.println() calls with the formatting being done by + String(someIntParam) etc. Either that or expand the Print.h and Print.cpp and check if printf() is also available on all other platforms, to ensure compilibility in all cases.

I see, It’s somehow PIO related issue, about build-system, where 99.99% of the cases won’t be any issue.

Can I re-order Includes in some-way at building stage, maybe using platformio.ini ?
Because It’s preferable also that we use core’s libraries instead of adding to the binary size.

I think it’s the straight-forward solution, How do you think ?

Well if you do fix the include order to use the core’s library, again you run into this issue where it’s e.g. not implemented by the AVR version of the Arduino core and fails to compile.

And what speaks against “expansion” of the printing API with printf() is that printf() is extremely large in flash and RAM, single String() conversions should be less intensive.

I see that the same way. That would be something to write to the devs at Issues · platformio/platformio-core · GitHub so that that may be equalized among PlatformIO and Arduino IDE.

I can’t see it a problem, where the library doesn’t support AVR boards in the essence.

For what’s matter, printf is hugely preferable to me over print,println. as it’s mainly used for debugging, Usage is straight-forward and makes the code ‘neat’ .

Thank you for the suggestion, I’ll file the issue to platformio-core repo very soon.