Clang + Arduino = ♥

So… Clang.

Anyone who codes in C, C++ or Obj-C should know it. If you don’t, read about it. Seriously, stop reading this post and google it. Check my video to see a quick overview of its features.

Now you should know that Clang (+LLVM) is awesome. It’s steadily shaking the still waters of C compilers, and in my opinion, gradually replacing GCC as the de-facto C compiler. I’d like to talk a bit about Clang’s syntax analysis. Let’s assume this sample code:

#include<stdio.h>

int main(void)
{
  int myVar = 5
  int myVar2 = myVar;
  int hello1 = 4;
  printf("hello is %d", hello);
  if(myVar = myVar2)
    printf("they are equal");
}

There are quite a few errors in this code. First of all, there’s a missing ‘;’ in the 3rd line. The variable we are passing in the first printf doesn’t exist, and we are using an ‘=’ operator instead of a ‘==’ inside the if statement. The last one is not a syntax error, rather a logical one, but we will see how Clang helps us find those as well.

Now, let’s see what GCC has to say about the above code. This is the output we get when we try to compile it.

test.c: In function ‘main’:
test.c:6: error: expected ‘,’ or ‘;’ before ‘int’
test.c:8: error: ‘hello’ undeclared (first use in this function)
test.c:8: error: (Each undeclared identifier is reported only once
test.c:8: error: for each function it appears in.)
test.c:9: error: ‘myVar2’ undeclared (first use in this function)

GCC did find our errors, but it’s not giving us a lot of info on how to fix them, or even the exact line in the first case. Let’s see what Clang has to say about it:

test.c:5:15: error: expected ';' at end of declaration
        int myVar = 5
                     ^
                     ;
test.c:8:24: error: use of undeclared identifier 'hello'; did you mean 'hello1'?
        printf("hello is %d", hello);
                              ^~~~~
                              hello1
test.c:7:6: note: 'hello1' declared here
        int hello1 = 4;
            ^
test.c:9:11: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
        if(myVar = myVar2)
           ~~~~~~^~~~~~~~
test.c:9:11: note: place parentheses around the assignment to silence this warning
        if(myVar = myVar2)
                 ^
           (             )
test.c:9:11: note: use '==' to turn this assignment into an equality comparison
        if(myVar = myVar2)
                 ^
                 ==
1 warning and 2 errors generated.

Much more verbose. First of all, it’s telling us exactly where to add the missing semicolon. It is also showing us exactly which variable is undeclared, and it has recognized that we probably meant ‘hello1′ instead of ‘hello’. Last but not least, it’s warning us that we probably want to do a logical comparison instead of assignment in the if statement, and it suggests fixing it, or add an extra set of parentheses if we really do want an assignment, to let Clang know about it and leave us alone. The real output is also beautifully colored, but I can’t show that here :)

These are only some of Clang’s awesome features, but I’ll focus on this for now and go back to the Arduino. We all know that the Arduino IDE is not the best IDE in the world, actually far from it. I’ll show you how you can use Clang’s syntax analyzer to get all this awesome information about your errors. This is only a step in the right direction. I intend to use Clang to compile the Arduino code itself. Hopefully, I will make it, although the state of LLVM’s AVR backend is unknown to me.

So, first things first. In order to use Clang for your Arduino sketches, you must first convert them to the equivalent .cpp project. There are a lot of ways to do that, but I suggest using my python script (modified from a SCons file i found in this blog post). You can download my script here. You invoke it like this:
./preprocess.py your_filename.ino

This generates the intermediate C++ file that the Arduno IDE then normally sends to avr-gcc for compilation. We will run this file in Clang to check for errors.

clang -fsyntax-only -Os -I/path/to/your/includes/directory -I/path/to/your/variants/directory -I/path/to/your/arduino/core/files/directory -D__AVR_ATmega328P__ -DARDUINO=100 -DF_CPU=16000000L -Wno-unknown-attributes -Wno-attributes filename.cpp

In my case (OS X), this is:
clang -fsyntax-only -Os -I/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/avr/include -I/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/variants/standard -I/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino -D__AVR_ATmega328P__ -DARDUINO=100 -DF_CPU=16000000L -Wno-unknown-attributes -Wno-attributes filename.cpp

Which results in the following output:

tempfiles/OzZnnTkbaY:4:19: error: expected ';' at end of declaration
        int helloWorld= 6
                         ^
                         ;
1 error generated.

Ah, There’s my error! :P

Now this may be a long command, but it’s well worth it. I’d like to see Clang being used in the official Arduino IDE, but I’m also working on other ways to make it easy to use. Just stay tuned ;)

6 Responses to “Clang + Arduino = ♥”

  1. AlexNo Gravatar said:

    Jun 15, 12 at 2:18 am

    This is really slick, thanks for posting. I would love to see an AVR backend for LLVM – do you know if one is being built by anyone?

  2. Georgitzikis VasilisNo Gravatar said:

    Jun 15, 12 at 5:16 pm

    Yes, there is an AVR-LLVM backend being developed, which you can find here: http://sourceforge.net/projects/avr-llvm/

    From what I understand, after being contacted by Atmel, although not functional, it is under active development. I hope to find the time to try and contribute. It’s such a cool project.

  3. micheleNo Gravatar said:

    Nov 28, 12 at 1:06 pm

    Your preprocess.py file is “moved or deleted”.

  4. Georgitzikis VasilisNo Gravatar said:

    Nov 28, 12 at 10:43 pm

    You’re right, of course! Unfortunately, I can’t seem to find it anymore. I’d suggest trying http://codebender.cc where we have already incorporated Clang’s error output as the default error output

  5. AntonNo Gravatar said:

    Apr 13, 13 at 5:58 am

    Hi, thanks for great post!

    I’d like to use Clang for autocomplete or smart code parsing in ArduinoDroid app (https://play.google.com/store/apps/details?id=name.antonsmirnov.android.arduinodroid). Would you like to take part in it?

  6. Georgitzikis VasilisNo Gravatar said:

    Apr 13, 13 at 4:22 pm

    Hi Anton, I’m currently focusing my efforts on http://codebender.cc which is an online Arduino IDE that allows you to code and flash your Arduino from a browser. But since we also want to add Clang support there too, we could possibly work together.


Leave a Reply


Tzikis is using WP-Gravatar