arduino ethernet libraries macro selector

Hi.

I'm tring to use an websocket librarie that have macro to selec with ethernet librarie it use.

i want to add to that macro selection of Ethernet2.h .

But I got collision of definition:

(x86)\Arduino\libraries\Ethernet\src/Dhcp.cpp:31: multiple definition of `DhcpClass::reset_DHCP_lease()'

libraries\Ethernet2\Dhcp.cpp.o:C:\Users\...\Documents\Arduino\libraries\Ethernet2\src/Dhcp.cpp:32: first defined here

How should I define macro so that include a libraries in sketch define witch one is use inside libraries?

Here what I got so far...:

#ifndef WEBSOCKETS_H_
#define WEBSOCKETS_H_

#include <Arduino.h>

//#define DEBUG_WEBSOCKETS(...) Serial1.printf( __VA_ARGS__ )

#ifndef DEBUG_WEBSOCKETS
#define DEBUG_WEBSOCKETS
#define NODEBUG_WEBSOCKETS
#endif

#ifdef ESP8266
#define WEBSOCKETS_MAX_DATA_SIZE  (15*1024)
#define WEBSOCKETS_USE_BIG_MEM
#else
//atmega328p has only 2KB ram!
#define WEBSOCKETS_MAX_DATA_SIZE  (1024)
#endif

#define WEBSOCKETS_TCP_TIMEOUT    (1500)

#define NETWORK_ESP8266     (1)
#define NETWORK_W5100       (2)
#define NETWORK_ENC28J60    (3)
#define NETWORK_W5500       (4)


// select Network type based
#ifdef ESP8266
#define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP8266
#elif defined W5500_H_INCLUDED
#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5500
#else
#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100
#endif


#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)

#ifndef ESP8266
#error "network type ESP8266 only possible on the ESP mcu!"
#endif

#include <ESP8266WiFi.h>
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer

#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100)

#include <Ethernet.h>
#include <SPI.h>
#define WEBSOCKETS_NETWORK_CLASS EthernetClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer

#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_W5500)
//#pragma message ( "w5500 network selected" )
#include "Ethernet2.h"
#include <SPI.h>
#define WEBSOCKETS_NETWORK_CLASS EthernetClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer

#else
#error "no network type selected!"
#endif

Thanks

Nitrof

The error indicates that you are including both the Ethernet and Ethernet2 libraries. It doesn't look like that would happen from the code you posted but maybe there is another part of your code that also contains an #include directive for one or the other. It's also not clear where W5500_H_INCLUDED would be defined.

Seems not... I looked.

more testing: if I mute ethernet.h if... dhcp is not double included but then, EthernetClient and Ethernet server is not well included.

To test if something else could cause the trouble, I muted every define macro and rewrite them to ethernet2, and it compile.. :

#define WEBSOCKETS_MAX_DATA_SIZE  (1024)
#define WEBSOCKETS_TCP_TIMEOUT    (1500)
#define NETWORK_W5500       (4)
#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5500

#include <Ethernet2.h>
//#include <EthernetClient.h>
//#include <EthernetServer.h>
#include <SPI.h>
#define WEBSOCKETS_NETWORK_CLASS EthernetClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer

the original code came fro that git repo on branch ATmega: arduinoWebSockets/tree/ATmega

I wonder what can cause the compiler to not respsct, or dont how to call it, the define macro....

I've ran into a problem when doing something of this sort before. Let's say I have some code like so:

Sketch.ino:

#define SOME_MACRO
#include <Foo.h>

Foo.h:

#ifdef SOME_MACRO
//do something
#else
//do something else
#endif

Foo.cpp:

#include <Foo.h>

Now what happens is that when Foo.h is included from Sketch.ino SOME_MACRO is defined and so the "do something" code is executed but then Foo.h is included from Foo.cpp SOME_MACRO is not defined and so the "do something else" code is executed. This is a bit confusing because we're used to thinking that the Foo.h code will always be the same.

A useful technique for troubleshooting preprocessor conditionals is to use #warning to get some debug output. Make sure you have File > Preferences > Compiler warnings turned on so that you can see the #warning output.

I tried to put some #pragma message into those define, And I got only the one I was expecting.

I tough that it will be ok because this is the only place that #define macro is selected, and the rest of the library use that macro reference...

It is even more strange that I lose reference to object event with the include file is correct.

an example that not compile... with as less code possible to illustrate.

.ino

/////Ethernet W5100

#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
//#include <EthernetClient.h>
//#include <EthernetServer.h>



////Ethernet2 W5500
/*
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet2.h>
//#include <EthernetClient.h>
//#include <EthernetServer.h>
*/


#include <testlib.h>


void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

testlib.h

#ifndef TESTLIB
#define TESTLIB

#ifdef W5100_H_INCLUDED
#include "Ethernet.h"
#pragma message ( "W5100 network" )

#elif defined W5500_H_INCLUDED
#include "Ethernet2.h"
#pragma message ( "W5100 network" )

else
	#pragma message ( "no network" )
#error "No or invalid network selected"
#endif

#include "Arduino.h"


class Testlib {
	Testlib();
};

#endif

.cpp

#include "testlib.h"

Testlib::Testlib(){}

But I think it do not work because the only define variable different on the 2 lib is on the util folder in the w5100 and w550.h file that are deeper #included into the lib... maybe I should try to make a define inside each ethernet.h file to see what I got...

Humm.. I tried couple of thing, but I think that it is not possible to control that by outside macro.

If the definition condition is inside the libraries, it work but not outside.

It is maybe not the case if those 2 libraries does not have the same naming for their content.

Is there something else I did not think about ?

it should work like this

#include <Ethernet2.h>
#include <Websockets.h>

the #define W5500_H_INCLUDED is in Ethernet2 library in w5500.h

nitrof:
I tried to put some #pragma message into those define, And I got only the one I was expecting.

Maybe because you messed up:

nitrof:

#elif defined W5500_H_INCLUDED

#include "Ethernet2.h"
#pragma message ( "W5100 network" )

Note that the libraries are cached after the first successful compilation so after that you need to change the Tools > Board selection to clear the cache to get warnings from the library again.

@Juraj taht was my own code and it don't work.

@pert yes the message was wrong... but I don't even get it...

if I define something outside the header, and check for it with ifdef, I get nothing... :

as far as I can understand, the compiler doesn't if the define is or will be call, so it don't work...

in my example, all I get is:

#error "No or invalid network selected"

W5100_H_INCLUDED is defined in w5100.h but that file is not included from Ethernet.h, Dhcp.h, or Dns.h (I'm not sure why you're including the last two). You'll need to do this:

#if defined(ethernet_h) && !defined(W5500_H_INCLUDED)
#include "Ethernet.h"
#pragma message ( "W5100 network" )

#elif defined(W5500_H_INCLUDED)
#include "Ethernet2.h"
#pragma message ( "W5500 network" )

#else
#pragma message ( "no network" )
#error "No or invalid network selected"
#endif

But, as I explained in #3, then you'll still run into the problem of testlib.h being included by testlib.cpp, which is a separate translation unit from your .ino file, and thus will not have the macros defined. You could resolve that by moving the code from testlib.cpp to testlib.h.

5100_H_INCLUDED is defined in w5100.h but that file is not included from

I didn't notice it was on ethernet1.. it is not on 2... it is only use by socket I think... good point

I'm not sure why you're including the last two

when you do an automatic include via windows menu of ethernet library, it does include it. I ask myself eater if it is needed... :stuck_out_tongue:

You could resolve that by moving the code from testlib.cpp to testlib.h

did you more think of moving the code from ino to header ?
I think this is what I will do.

[EDIT] the bug of compiler that see multiple def of dhcp and dns and blabla... that was in fact cause by my inclusion of dhcp and dsn on sketch !! good point. remove it make thing easier.

Ah, I forgot about what this thread was about originally. I see now the whole thing with the macros was only an attempted workaround for that and of course that code is completely unnecessary now that the underlying issue is resolved. It definitely turned into an X-Y problem discussion but I think it's good to learn about translation units anyway.

Yes. But the problem was haft solve.

If I didn't get anymore the problem of duplicate include, I still can't chose witch dependency to use outside of the
libraries.

it's good to learn about translation units anyway

Because of this, I understand that it is not possible... It is a bit frustrating when I have a couple of libraries that ethernet dependency.

At least with macro, I can change now every reference inside one libraries with one keyword...

Thank a lot for the help. Always grateful.

Regards.
Nitrof

It's not completely clear to me what the issue is now.

Remember that if you move the code to the .h file then it will be in the same translation unit since the #include in the sketch essentially just inserts the contents of the .h file. That's not typically considered best practices but it does allow some things that would not otherwise be possible.

Ethernet, Ethernet2, UIPEthernet all use the Client class. So if you write your library so that the Client object is created by the user in the sketch and then passed to the library via a function then the library will not be dependent on any specific library. That will allow your library to be also used with any other library that uses the Client class, such as WiFi, ESP8266WiFi, EspWiFi, etc.

It's not completely clear to me what the issue is now.

It is to select with ethernet to chose for the compiler without have to edit a #define inside .h file.

because the libraries concern could not have only .h file cause of size and/or complexity, For translation unit, i did not see a solution.

For the idea of only include client or server, for one of my libraries, that will be possible I think.

But for the websocket I try to use, it need more of ethernet like tcp and socket class.