Pages: 1 [2]   Go Down
Author Topic: Problem with conditional #include  (Read 1725 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 178
Posts: 12288
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I was thinking compiler...

Code:
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

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.
Logged

Offline Offline
God Member
*****
Karma: 21
Posts: 650
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

« Last Edit: November 25, 2012, 11:31:18 pm by pico » Logged

WiFi shields/Yun too expensive? Embeddedcoolness.com is now selling the RFXduino nRF24L01+ <-> TCP/IP Linux gateway: Simpler, more affordable, and even more powerful wireless Internet connectivity for *all* your Arduino projects! (nRF24L01+ shield and dev board kits available too.)

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 71
Posts: 3538
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Right, right, makes sense.

Quote
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! smiley-yell

Thanks!
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 71
Posts: 3538
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Quote
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.

Quote
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" smiley-razz

Quote
There. My spleen feels a little better now.
smiley-grin
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Offline Offline
Edison Member
*
Karma: 17
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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)
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

Code:
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.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Melbourne, Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 567
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: May 31, 2013, 10:16:36 pm by aarondc » Logged

Windows serial port monitor: Tellurium | Arduino serial port debugging library: DBG | Cusom LCD char generator | Technical questions will only be answered in forum threads

Offline Offline
Edison Member
*
Karma: 17
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

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

... gives me a compile error:

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

Melbourne, Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 567
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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-grin
Logged

Windows serial port monitor: Tellurium | Arduino serial port debugging library: DBG | Cusom LCD char generator | Technical questions will only be answered in forum threads

Melbourne, Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 567
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

test.ino:
Code:
#define __TESTING
#include <test.h>

void setup() {

    Serial.begin(9600);

    test();

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

void loop() {}

test.h:
Code:
#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:
Code:
#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
Logged

Windows serial port monitor: Tellurium | Arduino serial port debugging library: DBG | Cusom LCD char generator | Technical questions will only be answered in forum threads

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11197
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Edison Member
*
Karma: 17
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11197
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pages: 1 [2]   Go Up
Jump to: