Problem with conditional #include

I have two interchangeable libraries that implicitly define the same object (RTC) and are therefore mutually exclusive. I want to include one or the other, based on a #defined value. The code below seems to act as though both libraries are being included. If I explicitly comment one library or the other out with "//" then I can get it to compile.

This seems simple, I must be missing something fundamental.

#define RTC_TYPE 1

#include <Time.h>           //http://www.arduino.cc/playground/Code/Time
#include <Wire.h>           //http://arduino.cc/en/Reference/Wire

#if RTC_TYPE == 1
#include <DS1307RTC.h>      //http://www.arduino.cc/playground/Code/Time
#else
#include <MCP79412RTC.h>    //https://github.com/JChristensen/MCP79412RTC
#endif

void setup(void)
{
    setSyncProvider(RTC.get);
}

void loop(void)
{
}

Compiler output:

MCP79412RTC\MCP79412RTC.cpp.o:C:\Documents and Settings\Jack\My Documents\arduino\sketchbook\libraries\MCP79412RTC/MCP79412RTC.cpp:551: multiple definition of `RTC'
DS1307RTC\DS1307RTC.cpp.o:C:\Documents and Settings\Jack\My Documents\arduino\sketchbook\libraries\DS1307RTC/DS1307RTC.cpp:112: first defined here

At a quick glance it looks ok. Unless one library includes the other in error (doubt it).

Try this to see what the preprocessing is doing. Change the #define to see what happens... (I would, but I'm not near my compiler)

#if RTC_TYPE == 1
#include <DS1307RTC.h>      //http://www.arduino.cc/playground/Code/Time
#error DS1307RTC
#else
#include <MCP79412RTC.h>    //https://github.com/JChristensen/MCP79412RTC
#error DS1307RTC
#endif

@patduino, I get one #error or the other, not both. Double-checked my library just to verify that it doesn't include the other, and it doesn't.

patduino:
At a quick glance it looks ok. Unless one library includes the other in error (doubt it).

Try this to see what the preprocessing is doing. Change the #define to see what happens... (I would, but I'm not near my compiler)

#if RTC_TYPE == 1

#include <DS1307RTC.h>      //Arduino Playground - Time
#error DS1307RTC
#else
#include <MCP79412RTC.h>    //GitHub - JChristensen/MCP79412RTC: Arduino library for the Microchip MCP79411/12 Real-Time Clock/Calendar
#error MCP79412RTC
#endif

Linker error?

I was thinking compiler...

MCP79412RTC\MCP79412RTC.cpp.o:C:\Documents and Settings\Jack\My Documents\arduino\sketchbook\libraries\MCP79412RTC/MCP79412RTC.cpp:551: multiple definition of `RTC'
DS1307RTC\DS1307RTC.cpp.o:C:\Documents and Settings\Jack\My Documents\arduino\sketchbook\libraries\DS1307RTC/DS1307RTC.cpp:112: first defined here

I get one #error or the other, not both.

That implies that the preprocessor is handling the conditionals correctly. Hmmmmm.

Do you have code somewhere else, like in another tab, that might be compiling too?

patduino:

I get one #error or the other, not both.

That implies that the preprocessor is handling the conditionals correctly. Hmmmmm.

Do you have code somewhere else, like in another tab, that might be compiling too?

Nope, the code I posted is everything, single tab. The problem originally occurred in a larger project with multiple tabs, but I like to pare things down to the minimum that still exhibits the issue. Better for the forum I figure too.

More info:

  1. Checked the build folder, it contains sub-folders for both libraries with object files.

  2. Tried it on another PC (new build) ... same results.

Verbose compiler output attached.

verbose.txt (31.4 KB)

This looks like the infamous IDE trick of blowing #ifdef away.
Try putting char junk; at the front of the file.

Pete

el_supremo:
This looks like the infamous IDE trick of blowing #ifdef away.
Try putting char junk; at the front of the file.

Pete

The library (.h) file?

In your .ino file - it should work as long as it is in front of#if RTC_TYPE == 1

Pete

el_supremo:
In your .ino file - it should work as long as it is in front of#if RTC_TYPE == 1

Pete

Hmmm, no change:

char junk;
#define RTC_TYPE 1

#include <Time.h>           //http://www.arduino.cc/playground/Code/Time
#include <Wire.h>           //http://arduino.cc/en/Reference/Wire

#if RTC_TYPE == 1
#include <DS1307RTC.h>      //http://www.arduino.cc/playground/Code/Time
#else
#include <MCP79412RTC.h>    //https://github.com/JChristensen/MCP79412RTC
#endif

void setup(void)
{
    setSyncProvider(RTC.get);
}

void loop(void)
{
}
MCP79412RTC\MCP79412RTC.cpp.o:C:\Documents and Settings\Jack\My Documents\arduino\sketchbook\libraries\MCP79412RTC/MCP79412RTC.cpp:552: multiple definition of `RTC'
DS1307RTC\DS1307RTC.cpp.o:C:\Documents and Settings\Jack\My Documents\arduino\sketchbook\libraries\DS1307RTC/DS1307RTC.cpp:112: first defined here

This is a well documented and well known failing of the Arduino IDE preprocessor. It doesn't respect (or simply ignores) the preprocessor conditionals, and will aggressively match any line starting with #include for a library inclusion.

It's been reported as a problem for years. Like many other problems with the IDE preprocessor, Team Arduino don't think it's a big deal, apparently, so it's not going to be fixed.

My solution is to simply not use the IDE to avoid the numerous bugs and problems in the IDE preprocessor altogether. I use makefiles that do the build. I need to declare my own prototypes, and put a list of user libraries I'm using in a makefile script for that project. Done. No IDE preprocessor. Real C/C++ preprocessor directives all work as expected again. Life is better that way.

pico:
This is a well documented and well known failing of the Arduino IDE preprocessor. It doesn't respect (or simply ignores) the preprocessor conditionals, and will aggressively match any line starting with #include for a library inclusion.

It's been reported as a problem for years. Like many other problems with the IDE preprocessor, Team Arduino don't think it's a big deal, apparently, so it's not going to be fixed.

Understood, thanks. Guess I'd missed that one.

My solution is to simply not use the IDE to avoid the numerous bugs and problems in the IDE preprocessor altogether. I use makefiles that do the build. I need to declare my own prototypes, and put a list of user libraries I'm using in a makefile script for that project. Done. No IDE preprocessor. Real C/C++ preprocessor directives all work as expected again. Life is better that way.

I've read various threads on this approach, and made a couple half-hearted attempts but didn't stick to it long enough to get it working. I'd probably be happier working that way, too. Declaring prototypes is another thing I don't appreciate the IDE doing for me; it doesn't always get it right.

[quote author=Jack Christensen link=topic=134226.msg1009795#msg1009795 date=1353898194]I was thinking compiler...

MCP79412RTC\MCP79412RTC.cpp.o:C:\Documents and Settings\Jack\My Documents\arduino\sketchbook\libraries\MCP79412RTC/MCP79412RTC.cpp:551: multiple definition of `RTC'
DS1307RTC\DS1307RTC.cpp.o:C:\Documents and Settings\Jack\My Documents\arduino\sketchbook\libraries\DS1307RTC/DS1307RTC.cpp:112: first defined here

[/quote]

Nope. Dot-oh files are the domain of the linker.

In my case, I use // comments to "remove" one of the libraries. It's horribly annoying but it works.

pico:
This is a well documented and well known failing of the Arduino IDE preprocessor. It doesn't respect (or simply ignores) the preprocessor conditionals, and will aggressively match any line starting with #include for a library inclusion.

It's been reported as a problem for years. Like many other problems with the IDE preprocessor, Team Arduino don't think it's a big deal, apparently, so it's not going to be fixed.

Actually, this isn't entirely true, on reflection. The one time that the conditional #include does work is if you say

#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

When I first saw this , I thought "Yay! They finally fixed the IDE preprocessor to respect conditional #include!"

But no. They just fixed it for this one special case for their convenience. The rest of the plebs can just suffer. LOL.

It's "design decisions" like these that earn them the opprobrium amongst serious software developers they so justly deserve. Disgraceful, really.

They did do some important fixes in 0023->1.0, however, like renaming the .pde files to become .ino, and "WProgram.h" to become "Arduino.h". All an exercise in branding, of course. Which shows where their priorities lie, I suppose.

There. My spleen feels a little better now.

Right, right, makes sense.

In my case, I use // comments to "remove" one of the libraries. It's horribly annoying but it works.

Probably will go the same route. Agree it's annoying! :stuck_out_tongue_closed_eyes:

Thanks!

pico:
Actually, this isn't entirely true, on reflection. The one time that the conditional #include does work is if you say

#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

When I first saw this , I thought "Yay! They finally fixed the IDE preprocessor to respect conditional #include!"

But no. They just fixed it for this one special case for their convenience. The rest of the plebs can just suffer. LOL.

Wow, that is terrible. I have of course used that very construct. Maybe that was part of my confusion, I just couldn't see what was wrong.

It's "design decisions" like these that earn them the opprobrium amongst serious software developers they so justly deserve. Disgraceful, really.

On the one hand I get making things easy for beginners, but when it results in departure from well established standards and undesirable behavior that is not easy to fix, I have to draw the line.

They did do some important fixes in 0023->1.0, however, like renaming the .pde files to become .ino, and "WProgram.h" to become "Arduino.h". All an exercise in branding, of course. Which shows where their priorities lie, I suppose.

I've noticed how much better my code runs with these "fixes" :stuck_out_tongue:

There. My spleen feels a little better now.

:smiley:

pico:

pico:
This is a well documented and well known failing of the Arduino IDE preprocessor. It doesn't respect (or simply ignores) the preprocessor conditionals, and will aggressively match any line starting with #include for a library inclusion.

It's been reported as a problem for years. Like many other problems with the IDE preprocessor, Team Arduino don't think it's a big deal, apparently, so it's not going to be fixed.

Actually, this isn't entirely true, on reflection. The one time that the conditional #include does work is if you say

#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

When I first saw this , I thought "Yay! They finally fixed the IDE preprocessor to respect conditional #include!"

But no. They just fixed it for this one special case for their convenience. The rest of the plebs can just suffer. LOL.

Er. No. The gcc preprocessor actually includes the file, which has always worked correctly with the conditionals. The IDE just figures out what -I (minus-eye) switches to use so the preprocessor can figure out where "Wire.h" is on your computer (which doesn't screw up anthing when it fails) and also which .cpp files to compile and link in (which in your case can screw things up). It doesn't need to do either of those for WProgram.h or Arduino.h (although I guess it does have built-in rules to deal with the files in the arduino/hardware/cores/arduino directory)