Defining variables within #if #else #endif in Arduino IDE

17,584

Solution 1

The reason is that the Arduino IDE sucks. Under the hood it generates c code like so

#define DEBUG 0 //DEBUG=1 works, DEBUG=0 causes compiler error

#if DEBUG == 1
  int x = 123;
  //Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
  int x = 567;
  //Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif

void setup() {  }

void loop() {  }

Thus the compiler will not see the generated function prototypes if debug==0. Just set the compiler output to verbose and have a look yourself at the generated code in the build directory.

The solution to all this pain is to find some means to stop the IDE to mess with you stuff. I had some similar issue with function prototypes in the past that I solved with the TRICK17 macro (see here for the details). I will not go into the messy implementation of this macro as by now I found a significantly superior solution.

  • The IDE does not know about namespaces
  • As a consequence it does not touch anything inside namespaces
  • An empty namespace name is admissible this will establish an anonymous namespace. Entities in this namespace require no prefixes to address them.

Thus the new solution is

namespace {
// name of namespace left empty --> this is the anonymous namespace
// now the IDE will not mess with our stuff

#define DEBUG 0 //DEBUG=1 works, DEBUG=0 causes compiler error

#if DEBUG == 1
  int x = 123;
  //Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
  int x = 567;
  //Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif
}

void setup() {  }

void loop() {  }

Solution 2

ok! figured it out with Udo's help.

Whats happening: When the Arduino IDE compiles, it automatically creates all the header declarations for all the functions you have in your *.ino file. I'm assuming that when it does this, it must trigger on the first variable encountered. But if you do what I did and you use the #if,#else directives on the first variable in the code and omit it, then it will fail to create all the proper declarations for loop, setup, foo, bar(), etc.. If the first variable is "visible", it creates everything properly.

The Solution: create a nonsense variable at the top of the code before the #if,#else stuff.

The Now-working example:

byte nonsense_var = 0;  //this line solves everything!

#define DEBUG 0         //DEBUG=1 works, DEBUG=0 works now!

#if DEBUG == 1
    Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
    Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif

void setup() {  }

void loop() {  }
Share:
17,584
Chris
Author by

Chris

Updated on June 04, 2022

Comments

  • Chris
    Chris almost 2 years

    I was hoping that someone could shed light on why this code does not compile in Arduino IDE (using 1.0.5). The following code only compiles if DEBUG=1 but not if it is set to 0.

    What I was hoping to achieve was just a simple way to use the same code when i swap LED drivers and just flip the DEBUG bit prior to recompiling and uploading.

    Note: this sample is the whole code to be compiled in the IDE (no other code is required).

    problem code:

    #define DEBUG 0 //DEBUG=1 works, DEBUG=0 causes compiler error
    
    #if DEBUG == 1
      int x = 123;
      //Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
    #else
      int x = 567;
      //Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
    #endif
    
    void setup() {  }
    
    void loop() {  }
    

    error:

    core.a(main.cpp.o): In function `main':
    C:\arduino\hardware\arduino\cores\arduino/main.cpp:11: undefined reference to `setup'
    C:\arduino\hardware\arduino\cores\arduino/main.cpp:14: undefined reference to `loop'