Hi
I鈥檓 testing a newly released version of a library called H4Plugins.
The issue I鈥檓 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 core 1.0.4
PlatformIO build environment:
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
A cutsom library used (installed under /lib):
https://github.com/philbowles/h4plugins/tree/dev
platformio.ini :
[platformio]
default_envs = esp32doit-devkit-v1
[common]
framework = arduino
monitor_speed = 115200
lib_deps =
https://github.com/philbowles/[email protected]
https://github.com/philbowles/[email protected]
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 full copy of the project can be found here :
https://github.com/HamzaHajeir/platformio_test
Log by running : pio run -v >compile1.log :
https://github.com/HamzaHajeir/platformio_test/blob/master/compile1.log
Arduino IDE Log (with verbose) :
https://github.com/HamzaHajeir/platformio_test/blob/master/Arduino%20Compile%20Log.log
Referring to a discussion in PIO Community, It seems it's a PIO related issue, Where it's a wrong order of Include source files to compile (Libraries then Core)
Where Arduino (and the right order is) : (Core then Libraries).
Have we hit accurately the reason ?
I don't see how this problem is solved by difference include order. Looks to me like this is a bug in the library code.
Could you explain to me how Arduino IDE bypasses this code in H4.h and does not give a compiler warning? I haven't spent too much time on this so this isn't too obvious to me. Looking at the code in VScode it simply looks like the printf function is never defined since class delegateSerial is not reachable.
#if defined H4_ARDUINO
#include <Arduino.h>
#define h4GetTick millis
#else
#include <memory.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include "Print.h"
#include<cstdarg>
#include<string>
extern "C" {
int _write(int file, char *data, int len);
}
class delegateSerial: public Print{
public:
delegateSerial(){}
void begin(uint32_t){}
size_t write(uint8_t c){
return _write(1,(char*) &c,1); // 1 is irrlevant
}
size_t write(const char *str)
{
if (str == NULL) return 0;
return _write(1,(char*)str, strlen(str)); // 1 is irrelevant
}
size_t write(const uint8_t *buffer, size_t size)
{
size_t n = 0;
while (size--) {
if (write(*buffer++)) {
n++;
} else {
break;
}
}
return n;
}
size_t printf(const char* fmt,...){ // <------------------------------------ defined here
va_list arg;
va_start(arg, fmt);
size_t rv=vprintf(fmt, arg);
va_end(arg);
return rv;
}
};
extern delegateSerial Serial;
#endif
Well, It's not a bug in library.
#else would never be called, because the definition of H4_ARDUINO is extended from the following definitions:
#if (defined ARDUINO_ARCH_STM32 || defined ARDUINO_ARCH_ESP8266 || defined ARDUINO_ARCH_ESP32)
#define H4_ARDUINO
lib\h4plugins-dev\src\H4P_udpLogger.cpp:47:28: error: 'class HardwareSerial' has no member named 'printf'
Also, The error calls class HardwareSeria has no member named 'printf'
not class delegateSerial has no member named 'printf'
The discussion in PlatformIO community is informative though.
Hmm you're right I tried using exactly the same build flags as Arduino IDE but that didn't work. I'm not convinced the solution in the PlatformIO forum post solves the underlying issue, but the workaround makes sense. I agree that it looks like Arduino.h version of #include "Print.h" is not compiled/built first.
On my end Print.h is located at .platformio/packages/framework-arduinoespressif32/cores/esp32/Print.h
and it includes the desired line: size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
The problem is (_still_) that PIO does not use the correct (same as ArduinoIDE) architecture / board name #defines @build time. For example on ESP8266 targets, ArduinoIDE defines ARDUINO_ARCH_ESP8266, (I'm Guessing) PIO defines some abitraty PIO-specific equivalent (unless its been fixed since the last time I looked)
Any library depending on the correct implementation of 100% ArduinoIDE-compatible #defines to conditionally include / exclude target-specific code will work 100% correctly under ArduinoIDE (as is the case with the H4 / H4Plugins library which are 100% Arduino-compatible and correct) but will fail under PIO because the lib will assume its NOT ESP8266 because ARDUINO_ARCH_ESP8266 is NOT defined and thus it will take the other branch which in the H4 case is to assume ESP32 or STM32...with the obvious subsequent problems of compiling code for the wrong target under PIO. due to PIO's bug.
I first brought this to the attention of the PIO team oooohh maybe four, possibly five? years ago....then again probably every 3-4 months for the next 2-3 years...till I got fed up with being ignored andI finally gave up, as it seemed obvious to me that PIO were not interested in taking the issue seriously or fixing it. MY solution is to make it clear to anyone who uses any of my 100% Arduino-compatible libraries that I refuse to provide any support for PIO users until this glaring bug is finally fixed.
I hope this helps :)
and it includes the desired line:
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
Mine also. There's something I haven't fully grasp.
Most helpful comment
The problem is (_still_) that PIO does not use the correct (same as ArduinoIDE) architecture / board name #defines @build time. For example on ESP8266 targets, ArduinoIDE defines ARDUINO_ARCH_ESP8266, (I'm Guessing) PIO defines some abitraty PIO-specific equivalent (unless its been fixed since the last time I looked)
Any library depending on the correct implementation of 100% ArduinoIDE-compatible #defines to conditionally include / exclude target-specific code will work 100% correctly under ArduinoIDE (as is the case with the H4 / H4Plugins library which are 100% Arduino-compatible and correct) but will fail under PIO because the lib will assume its NOT ESP8266 because ARDUINO_ARCH_ESP8266 is NOT defined and thus it will take the other branch which in the H4 case is to assume ESP32 or STM32...with the obvious subsequent problems of compiling code for the wrong target under PIO. due to PIO's bug.
I first brought this to the attention of the PIO team oooohh maybe four, possibly five? years ago....then again probably every 3-4 months for the next 2-3 years...till I got fed up with being ignored andI finally gave up, as it seemed obvious to me that PIO were not interested in taking the issue seriously or fixing it. MY solution is to make it clear to anyone who uses any of my 100% Arduino-compatible libraries that I refuse to provide any support for PIO users until this glaring bug is finally fixed.
I hope this helps :)