Pico Core - Compilation breaks if Ethernet.h is included in an disabled code segment

I don’t know if this is a PlatformIO or Arduino Core problem but if a add the following code to any code file the compilation breaks when it is compiled for the Raspberry Pi Pico Core

//#define FUU
#ifdef FUU
#include <Ethernet.h>
#endif 

it should not make a difference if the block is inside an not enabled ifdef.

  • exact platformio.ini?
  • exact error message?
  • usage of different lib_ldf_mode makes the error go away?

the error can be reproduced by just creating an empty project and add the code anywhere.

here my platformio.ini

[platformio]

default_envs = pico

[env]
;platform = https://github.com/platformio/platform-raspberrypi.git
platform = raspberrypi

framework = arduino

monitor_speed = 115200

[env:pico]
board = pico
upload_port = D:\

compiler errors are:

Client.cpp.o
Compiling .pio\build\pico\lib187\SocketWrapper\SocketHelpers.cpp.o
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp: In member function 'int arduino::MbedClient::connectSSL(SocketAddress)':
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:123:16: error: expected type-specifier before 'TLSSocket'
  123 |     sock = new TLSSocket();
      |                ^~~~~~~~~
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:134:19: error: 'TLSSocket' does not name a type; did you mean 'DTLSSocket'?
  134 |   if (static_cast<TLSSocket *>(sock)->open(getNetwork()) != NSAPI_ERROR_OK) {
      |                   ^~~~~~~~~
      |                   DTLSSocket
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:134:29: error: expected '>' before 
'*' token
  134 |   if (static_cast<TLSSocket *>(sock)->open(getNetwork()) != NSAPI_ERROR_OK) {
      |                             ^
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:134:29: error: expected '(' before 
'*' token
  134 |   if (static_cast<TLSSocket *>(sock)->open(getNetwork()) != NSAPI_ERROR_OK) {
      |                             ^
      |                             (
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:134:30: error: expected primary-expression before '>' token
  134 |   if (static_cast<TLSSocket *>(sock)->open(getNetwork()) != NSAPI_ERROR_OK) {
      |                              ^
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:134:39: error: 'class Socket' has no member named 'open'
  134 |   if (static_cast<TLSSocket *>(sock)->open(getNetwork()) != NSAPI_ERROR_OK) {
      |                                       ^~~~
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:134:76: error: expected ')' before 
'{' token
  134 |   if (static_cast<TLSSocket *>(sock)->open(getNetwork()) != NSAPI_ERROR_OK) {
      |      ~                                                                     ^~
      |                                                                            )
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:138:26: warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
  138 |   address = socketAddress;
      |                          ^
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:141:42: error: 'TLSSocket' does not name a type; did you mean 'DTLSSocket'?
  141 |   nsapi_error_t returnCode = static_cast<TLSSocket *>(sock)->connect(socketAddress);
      |                                          ^~~~~~~~~
      |                                          DTLSSocket
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:141:52: error: expected '>' before 
'*' token
  141 |   nsapi_error_t returnCode = static_cast<TLSSocket *>(sock)->connect(socketAddress);
      |                                                    ^
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:141:52: error: expected '(' before 
'*' token
  141 |   nsapi_error_t returnCode = static_cast<TLSSocket *>(sock)->connect(socketAddress);
      |                                                    ^
      |                                                    (
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:141:53: error: expected primary-expression before '>' token
  141 |   nsapi_error_t returnCode = static_cast<TLSSocket *>(sock)->connect(socketAddress);
      |                                                     ^
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedClient.cpp:141:84: error: expected ')' before 
';' token
  141 |   nsapi_error_t returnCode = static_cast<TLSSocket *>(sock)->connect(socketAddress);
      |                                                                                    ^
      |                                                                                    )
In file included from C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedSSLClient.cpp:1:
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedSSLClient.h: In member function 'int arduino::MbedSSLClient::setRootCA()':
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedSSLClient.h:46:14: error: 'TLSSocket' was not 
declared in this scope; did you mean 'DTLSSocket'?
   46 |     return ((TLSSocket*)sock)->set_root_ca_cert_path("/wlan/");
      |              ^~~~~~~~~
      |              DTLSSocket
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedSSLClient.h:46:24: error: expected primary-expression before ')' token
   46 |     return ((TLSSocket*)sock)->set_root_ca_cert_path("/wlan/");
      |                        ^
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\MbedSSLClient.h:46:25: error: expected ')' before 
'sock'
   46 |     return ((TLSSocket*)sock)->set_root_ca_cert_path("/wlan/");
      |            ~            ^~~~
      |                         )
*** [.pio\build\pico\lib187\SocketWrapper\MbedClient.cpp.o] Error 1
*** [.pio\build\pico\lib187\SocketWrapper\MbedSSLClient.cpp.o] Error 1
In file included from C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\SocketHelpers.cpp:104:
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:82:27: error: expected ')' before '*' token
   82 |     HttpsRequest(TLSSocket* socket,
      |                 ~         ^
      |                           )
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h: In constructor 'HttpsRequest::HttpsRequest(NetworkInterface*, const char*, http_method, const char*, mbed::Callback<void(const char*, long unsigned int)>)':      
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:62:23: error: expected type-specifier before 'TLSSocket'
   62 |         _socket = new TLSSocket();
      |                       ^~~~~~~~~
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:63:11: error: 'TLSSocket' 
was not declared in this scope; did you mean 'DTLSSocket'?
   63 |         ((TLSSocket*)_socket)->open(network);
      |           ^~~~~~~~~
      |           DTLSSocket
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:63:21: error: expected primary-expression before ')' token
   63 |         ((TLSSocket*)_socket)->open(network);
      |                     ^
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:63:22: error: expected ')' before '_socket'
   63 |         ((TLSSocket*)_socket)->open(network);
      |         ~            ^~~~~~~
      |                      )
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:65:23: error: expected primary-expression before ')' token
   65 |           ((TLSSocket*)_socket)->set_root_ca_cert(ssl_ca_pem);
      |                       ^
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:65:24: error: expected ')' before '_socket'
   65 |           ((TLSSocket*)_socket)->set_root_ca_cert(ssl_ca_pem);
      |           ~            ^~~~~~~
      |                        )
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:67:23: error: expected primary-expression before ')' token
   67 |           ((TLSSocket*)_socket)->set_root_ca_cert_path("/wlan/");
      |                       ^
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:67:24: error: expected ')' before '_socket'
   67 |           ((TLSSocket*)_socket)->set_root_ca_cert_path("/wlan/");
      |           ~            ^~~~~~~
      |                        )
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h: In member function 'virtual nsapi_error_t HttpsRequest::connect_socket(char*, uint16_t)':
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:103:18: error: 'TLSSocket' was not declared in this scope; did you mean 'DTLSSocket'?
  103 |         return ((TLSSocket*)_socket)->connect(socketAddress);
      |                  ^~~~~~~~~
      |                  DTLSSocket
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:103:28: error: expected primary-expression before ')' token
  103 |         return ((TLSSocket*)_socket)->connect(socketAddress);
      |                            ^
C:\Users\Save_\.platformio\packages\framework-arduino-mbed\libraries\SocketWrapper\src\utility/https_request.h:103:29: error: expected ')' before '_socket'
  103 |         return ((TLSSocket*)_socket)->connect(socketAddress);
      |                ~            ^~~~~~~
      |                             )
*** [.pio\build\pico\lib187\SocketWrapper\SocketHelpers.cpp.o] Error 1

The Ethernet library is definitely causing the compile error. The dependency graph looks like

Dependency Graph
|-- <Ethernet> 1.0.0
|   |-- <SocketWrapper> 1.0

And yields your error above.

When I add

lib_ldf_mode = chain+

at the bottom of your platformio.ini, the library is removed from the build (since the LDF now evaluates the #ifdef logic) and the build goes through.

PACKAGES:
 - framework-arduino-mbed 2.4.1
 - tool-rp2040tools 1.0.2
 - toolchain-gccarmnoneeabi 1.90201.191206 (9.2.1)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain+, Compatibility ~ soft
Found 30 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
..
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [==        ]  18.6% (used 50240 bytes from 270336 bytes)
Flash: [          ]   3.4% (used 72152 bytes from 2097152 bytes)
Building .pio\build\pico\firmware.bin
====================== [SUCCESS] Took 11.39 seconds ======================

That of course doesn’t explain why the build explodes when the Ethernet library (built into the Arduino core) fails compilation like that.

Okay actually the error is understandable since the library is meant for Portenta (ArduinoCore-mbed/libraries/Ethernet at master · arduino/ArduinoCore-mbed · GitHub), not a Raspberry Pico.

But why does the library get included if it is in an code segment that is disabled.

the Websockets lib i’m working with is crossplatform and supports ESP, STM32 etc. only the STM32 part includes Ethernet.
this way its impossible to write cross platform code that exchanges librarys per ifdef like this:

...
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100)
#ifdef STM32_DEVICE

#define WEBSOCKETS_NETWORK_CLASS TCPClient

#define WEBSOCKETS_NETWORK_SERVER_CLASS TCPServer

#else

//#include <Ethernet.h>

#include <SPI.h>

#define WEBSOCKETS_NETWORK_CLASS EthernetClient

#define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer

#endif

#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ENC28J60)

#include <UIPEthernet.h>

#define WEBSOCKETS_NETWORK_CLASS UIPClient

#define WEBSOCKETS_NETWORK_SERVER_CLASS UIPServer

#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)

#include <WiFi.h>

#include <WiFiClientSecure.h>

#define SSL_AXTLS

#define WEBSOCKETS_NETWORK_CLASS WiFiClient

#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure

#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer

#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32_ETH)

#include <ETH.h>

#define WEBSOCKETS_NETWORK_CLASS WiFiClient

#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer

#else

#error "no network type selected!"

#endif

Carefully read through the LDF manual. Python code interprets the C/C++ code, and depending on the LDF mode, does not care about #ifdef. If the #include is there it’ll by default include the lib.

If Ethernet is really not needed for the build and lib_ldf_mode doesn’t get rid of it, use lib_ignore = Ethernet. If it was needed after all, you should be getting compile errors.

first thanks for the fast resposes. Love the great support in the PlatformIO forum ;]

I raised the issue just in case it is unintended behaviour pointing to a unterlying problem. i personally can just uncomment the line as I don’t use the lib for STM32.
I was surprised that the code breaks with an include inside an disabled #ifdef. The code does compile fine with the line uncommented which means it is not needed. It might overrite class names and then looks to the compiler as a include that is needed.

C Compiler are Black magic after all x]