arduino / arduino-preprocessor

Parses an Arduino Sketch and converts it into valid C++ source code
49 stars 13 forks source link

Adafruit_ASFcore library compilation failure #6

Open per1234 opened 6 years ago

per1234 commented 6 years ago

Using Arduino IDE Beta build 31 with Windows 7 64 bit

  1. Download https://github.com/adafruit/Adafruit_ASFcore/archive/master.zip
  2. Sketch > Include Library > Add .ZIP Library > Select the downloaded file > Open
  3. Tools > Board > Arduino/Genuino Zero
  4. Compile the following sketch:
    #include "tc.h"
    void setup() {}
    void loop() {}

Error output:

In file included from E:\Stuff\misc\electronics\arduino\libraries\Adafruit_ASFcore-master/system_interrupt.h:139:0,

                 from E:\Stuff\misc\electronics\arduino\libraries\Adafruit_ASFcore-master/tc.h:543,

                 from E:\Stuff\misc\electronics\arduino\temp\tc\tc.ino:2:

E:\Stuff\misc\electronics\arduino\libraries\Adafruit_ASFcore-master/system_interrupt_features.h:149:55: error: expected '}' before '(' token

                                                       ^

E:\Stuff\misc\electronics\arduino\libraries\Adafruit_ASFcore-master/system_interrupt_features.h:149:68: error: expected ')' before ',' token

                                                                    ^

E:\Stuff\misc\electronics\arduino\libraries\Adafruit_ASFcore-master/system_interrupt_features.h:149:76: error: expected initializer before ')' token

                                                                            ^

In file included from E:\Stuff\misc\electronics\arduino\libraries\Adafruit_ASFcore-master/tc.h:543:0,

                 from E:\Stuff\misc\electronics\arduino\temp\tc\tc.ino:2:

E:\Stuff\misc\electronics\arduino\libraries\Adafruit_ASFcore-master/system_interrupt.h:714:1: error: expected declaration before '}' token

exit status 1
Error compiling for board Arduino/Genuino Zero (Programming Port).

arduino-preprocessor -debug output: https://gist.githubusercontent.com/per1234/57cbaf86646e4639b209dc99b9a6a7ac/raw/6ce21f489027fd8eac4114032e3ae764f25dd12e/arduino-preprocessor_debug_output.txt

The issue does not occur with Arduino IDE 1.8.5 or Arduino IDE 1.8.6 Hourly Build 2017/11/13 11:33.

Originally reported at http://forum.arduino.cc/index.php?topic=517758

facchinm commented 6 years ago

ASFcore preprocessor folder is a macro hell, and one of those (MREPEAT) requires multiple preprocessor iterations. The main problem, here, is not the invalid code but the fact that the code is totally expanded while being preprocessed. This is useful (necessary) for autocompletion but doesn't add anything to sketch preprocessing. I believe this should be modified at arduino-builder level but it's not super clear how. @cmaglie any idea on how to handle this?

Jomelo commented 6 years ago

I have the same problem with my librarys "lcdmenulib" and "lcdmenulib2". I use the MREPEAT macros to generate some functions.

For example: https://github.com/Jomelo/LCDMenuLib/blame/master/src/LCDMenuLib_makros.h#L975

The error message is this: LCDML_serialmonitor:98:414: error: 'LCDML_BACK_help_setup_repeat_1' was not declared in this scope

To reproduce the problem include the library from the librarymanager and open the example: File > Examples > LCDMenuLib2 > 00_beginners > LCDML_000_serialMonitor

The issue does not occur with Arduino IDE 1.8.5

cmaglie commented 6 years ago

What makes me wonder here is that there are a lot of nested macros elsewhere that don't produce the error. So I studied more deeply this case and I found that the reason why this macro fails is in the comment in the same line of the macro definition (comments are preserved due to the -CC flag in the gcc -E -CC call).

I had a very hard time to create a small example to reproduce the same behaviour, but here it is:

#define TPASTE2(a, b) a##b
#define THREE 3 /* Remove this comment and it will compile... */
#define PRINT3(x) Serial.print(x)
#define TEST(x, y) TPASTE2(x, y) ("A")

void setup() {
  TEST(PRINT, THREE);
  // TPASTE2(x,y) ("A")
  // TPASTE2(PRINT, THREE) ("A")
  // PRINT##3 /* Remove this comment and it will compile... */ ("A")
}

void loop() {
}

after running gcc -E -CC we get:

[...]
void setup() {
  PRINT3 /* Remove this comment and it will compile... */ ("A");
[...]

as you can see the comment inserted between PRINT3 and the parameter ("A") will make the preprocessor fail to expand PRINT3 further.

We put the -CC it to allow passing doxygen comments to arduino-preprocessor and have them in autocompletion, but this is not optimat yet, we should preserve also #defines that are removed in this case. So IMHO we can remove -CC and find another way around for autocompletion....