Arduino compiler problem with #ifdefs solved.

In C, “#ifdef” or “#if defined()” are used to hide or include portions of code only if certain conditions are met. For example, my recent *ALL RAM* BBS experiment contains code for using the SD card library as well as the Ethernet library. I used #ifdef around specific blocks of code so I could compile versions with or without either of those libraries. But all is not well in Arduino land. Consider this following, simple example:

#if defined(FOO)
byte mac[] = { 0x2A, 0xA0, 0xD8, 0xFC, 0x8B, 0xEE };
#endif

void setup()
{
  Serial.begin(9600);
  while(!Serial); 
  Serial.println("Test...");
}

void loop()
{
}

This is supposed to only include the “byte mac[] =” line if “FOO” is defined, such as with:

#define FOO

However, on the current Arduino IDE (1.0.4), this simple code will fail with:

ifdef.ino: In function ‘void setup()’:
ifdef:18: error: ‘Serial’ was not declared in this scope

What? Suddenly “Serial.println()” won’t work? Moving the byte declaration outside of the #if def make it work. Very weird.

I also found a similar example, where I tried to comment out a function that used SD library variable types:

void setup()
{
  Serial.begin(9600);
  while(!Serial); 
  Serial.println("Test...");
}

void loop()
{
}

#ifdef FOO
byte fileReadln(File myFile, char *buffer, byte count)
{
}
#endif

In this example, I did not want the fileReadln() function to be included unless I had defined FOO. But, compiling this produces:

ifdef:15: error: ‘File’ was not declared in this scope
ifdef:15: error: expected primary-expression before ‘char’
ifdef:15: error: expected primary-expression before ‘count’
ifdef:15: error: initializer expression list treated as compound expression

Unhelpful. And after wasting some time on this, I started a topic in the Arduino.cc forums to ask if others were experiencing the same thing. And they were. A helpful post from parajew pointed me to this site which helped explain the problem, and offered a workaround:

http://www.a-control.de/arduino-fehler/?lang=en

The pre-processor does some stuff behind the scenes, creating prototypes and including header files where needed, and it just does it wrong. The A-Control site figured out a simple workaround, which I trimmed a bit to just adding this at the top of my scripts:

// BOF preprocessor bug prevent - insert me on top of your arduino-code
// From: http://www.a-control.de/arduino-fehler/?lang=en
#if 1
__asm volatile ("nop");
#endif

…and now either of my examples will compile as intended. Thank you, parajew and A-Control! I can now move on to my next problem…

Hope it helps you, too.

10 thoughts on “Arduino compiler problem with #ifdefs solved.

  1. Pingback: Arduino IDE preprocessor bug prevent workaround – Kommentare deaktiviert | tlfong01

  2. Pingback: Arduino #include and #define learning notes | tlfong01

  3. John Smith

    It doesn’t work for me still? I added that fix at the top, and defined my sd card pin, but it still gets this error:

    BBS.ino: In function ‘void loadMsgBase()’:
    BBS:1189: error: ‘fileReadln’ was not declared in this scope
    BBS.ino: At global scope:
    BBS:1220: error: expected unqualified-id before ‘{‘ token

    Reply
    1. Allen Huffman Post author

      If this is the ALLRAM BBS from GitHub, be sure to uncomment the “byte fileReadNln()” declaration. I had commented that out in frustration when initially dealing with this. I will have to check it in, uncomments.

      But still, it looks like something has changed. I can’t get it to build now, either. Try this — although everyone will say “you don’t need prototypes”, yet again, here is a situation where you must. The auto-generated junk the Arduino IDE is doing is getting in the way. Around line 65 of ALLRAMBBS.ino, add a prototype inside of the #if defined(SD_PIN) block:

      #if definedf(SD_PIN)
      #include

      // Prototypes…
      byte fileReadln(File myFile, char *buffer, byte count);
      #endif

      That resolves the error (and the #if 1 workaround is still not needed at the top of THIS file). If you have sesTelnetServer in your project, it will try to link that too (and there’s not enough room for both SD and ENET) so you have to #if defined(ENET_PORT) around all that code to prevent the IDE from linking it in, then it should built.

      I will get the GitHub sources updated.

      Reply
  4. wb8nbs

    Thanks 10e6 for that. I wasted hours trying to find why my ifdefs wouldn’t work. IDE version is 1.0.6. I hope there is a bug report for this.

    Reply
    1. Allen Huffman Post author

      After upgrading to the 1.60 IDE, I found more changes needed with PROGMEM data in flash. They have to be specified with “const” now (which, looking back, I should have been doing anyway). I had to go through and update several of my Github projects. Fortunately, that change should also still work on the older IDEs.

      Reply
  5. Reivax

    Hi,

    It looks like an #include in a .ino file will be processed regardless of any #if it might be enclosed in :(

    This results on big memory waste.
    I have IDE 1.61
    I thought I would group my includes in an includes.h file because I read that only .ino was incorrecty pre-processed, but then the libraries are not found.

    Any idea about how to solve this ?
    Thanks !

    Reply

Leave a Reply