Problem with conditional #include

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)

Here's the problem ...

The compile isn't done in your sketch directory. All the files in the sketch are copied to a temporary directory, along with any files mentioned in #include in the main sketch.

This is why you have to put (say) "#include <Wire.h>" in the main sketch, even if only a library uses it.

Now since the IDE doesn't honour preprocessor directives (and to be honest, it would probably be hard to) it copies all the files you mention to this temporary directory, and compiles them.

Hence the error message:

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

You'll notice that is a linker error message.

I don't know there is a way around it. I was tempted to suggest you put the conditional includes into a .cpp file (where they would be honoured) but then neither of the included files would be copied, and you would get missing symbol messages.

Maybe if you somehow made your own .h file (which gets copied into the temporary directory) and inside that you have the conditional directives which then include the files you really want, with a full pathname.

I was getting frustrated with exactly the same phenomenon, having seen the conditional Arduino vs WString include code somewhere, but having conditional includes not work with my own sketches.

I have been wondering how hard it would be to turn OFF the IDE "help" that happens, like creating prototypes, etc. A single option checkbox we could uncheck that would allow conditional #includes to work, mostly.

I am going down the

#include <one.h>
//#include <two.h>

route myself.

aarondc:
I was getting frustrated with exactly the same phenomenon, having seen the conditional Arduino vs WString include code somewhere, but having conditional includes not work with my own sketches.

I have been wondering how hard it would be to turn OFF the IDE "help" that happens, like creating prototypes, etc. A single option checkbox we could uncheck that would allow conditional #includes to work, mostly.

It would require more than an off switch to fix this problem. It's not that the IDE's helping is messing it up, it's that it's not being smart enough with the helping. If you turned it off then no -I or -l switches would be passed to gcc at all. Generally in IDEs there's separate configurations for the command line switches.

aarondc:
I have been wondering how hard it would be to turn OFF the IDE "help" that happens, like creating prototypes, etc. A single option checkbox we could uncheck that would allow conditional #includes to work, mostly.

If you make your own .cpp and .h files as part of the project, those files do not seem to be subjected to the IDE "help". For example, this file, which deliberately omits the function prototype:

void test ()
  {
  bar ();
  }
  
void bar ()
  {
  }

... gives me a compile error:

foo.cpp: In function 'void test()':
foo.cpp:3: error: 'bar' was not declared in this scope

I was most interested in the conditional include. If we could have our sketch #define's persist globally (wording is wrong but you know) it would allow for a solution for my goal.

If I #define something in a sketch, that #define is available in the included .h file, but not the corresponding .cpp file. Maybe that's also true for C / C++. It kind of makes sense that it's not available, as you're going back up the source tree, but I don't have to like it.

:smiley:

test.ino:

#define __TESTING
#include <test.h>

void setup() {

    Serial.begin(9600);

    test();

#ifdef __TESTING 
test1();
#else
test2();
#endif
}

void loop() {}

test.h:

#ifndef test_h
#define test_h
#include "Arduino.h"

void test();


#ifdef __TESTING
#warning __TESTING defined in test.h
void test1();
#else
#warning __TESTING UNdefined in test.h
void test2();
#endif
#endif

test.cpp:

#include "Arduino.h"
#include "test.h"

#ifdef __TESTING
#warning __TESTING defined in test.cpp
#else
#warning __TESTING UNdefined in test.cpp
#endif

#ifdef __TESTING
void test(){
    Serial.println("test 1");
}

void test1(){
    Serial.println("test 1::test1()");
}
#else
void test(){
    Serial.println("test 2");
}

void test2(){
    Serial.println("test 2::test2()");
}
#endif

When __TESTING is defined
#define __TESTING

I see the following verbose output:

warning: #warning __TESTING defined in test.h
warning: #warning __TESTING UNdefined in test.h
warning: #warning __TESTING UNdefined in test.cpp

If __TESTING is undefined,
//#define __TESTING

I see the following verbose output:

warning: #warning __TESTING UNdefined in test.h

Granted that the #include processing is (a) misguided and (b) poorly done, the problem here is that the Arduino IDE chooses the set of .cpp files to be compiled and linked based on the set of .h files #included into the sketch. The errors here occur because the set of files selected by the IDE include two definitions for the RTC variable. The only way I can see to resolve that is to find a way to defeat the Arduino's code selection logic. It's ugly, but the only way I can see to do it is to write your own .cpp file that #includes the implementation of the RTC library that you want to use, and write a corresponding .h file that #includes the associated declarations. Since Arduino will then not put the underlying library's source files in the build directory, you'd need to specify the path to the library implementation rather than just #including the filename.

The Arduino project is a nice idea, but I wish time and again that the Arduino runtime libraries had been given more critical peer review by people familiar with best practice for C++ development. This attempt to make C++ look a bit like Java was fundamentally misguided.

PeterH:
Granted that the #include processing is (a) misguided

So you think the arduino IDE should have a configuration file in each sketch directory that says what librarys it includes and where they are, and that users should have to manually put that in? If not, what's a better way to figure out what the -l and -I switches should be?

WizenedEE:

PeterH:
Granted that the #include processing is (a) misguided

So you think the arduino IDE should have a configuration file in each sketch directory that says what librarys it includes and where they are, and that users should have to manually put that in? If not, what's a better way to figure out what the -l and -I switches should be?

There are lots of different ways to do it, but I would have thought it was easy enough to have a scheme for installing a library into the IDE that resulted in the IDE having a list of installed libraries available for the user to choose from for each sketch. Given that the linker seems quite good at optimising out unused functions and data, it might be practical to default new sketches to include all installed libraries. It's not exactly rocket science to create a makefile for each sketch, is it?

Whichever solution was adopted, I'd want it to compile the C++ source code exactly as entered using conventional C++ semantics for specifying #included files, prototyping etc. That would mean that people already familiar with C++ can apply that knowledge directly to Arduino, and developers who get used to development within Arduino will find their new skills apply elsewhere too. As it is, the Arduino IDE teaches some pretty bizarre C++ coding habits.

I'd also want to have an IDE-wide or per-sketch option to select options for the tools used to compile, link and upload the sketch, including the ability to specify arbitrary options. Having user-friendly defaults is all very well, but advanced users should be able to change them. As it is, it seems to me that the IDE is OK for small applications and novice programmers but not suitable for anyone who ever wants to take the training wheels off.