Tuesday, February 18, 2014

$ICECC_VERSION

It's been brought to my attention that the Icecream documentation more or less suggests it is necessary to manually set up $ICECC_VERSION (which also involves creating the environment tarball with the compiler and so on). That is incorrect. I've already updated the documentation to say that, like with pretty much everything, Icecream simply figures it out itself by default.

So if you happen to use $ICECC_VERSION, unless you know why you do that (e.g. cross-compilation), don't. It's not only simpler but also better to leave it up to Icecream to package the system compiler as necessary, as it simply works, and avoids possible problems (such as updating the system compiler and forgetting to update the tarball).

Friday, July 12, 2013

Are you enjoying your Icecream?

A bug has crept into the Icecream 1.0 release that makes the daemon crash on its first start after boot if /var/run is cleared (e.g. it's tmpfs-mounted by systemd). This in practice means that on such systems Icecream does not work unless started manually. So in case your compiles have felt tad a bit slower recently, upgrade to the just released version 1.0.1. If you run openSUSE, an online update with the fix has already been published.

Thursday, July 11, 2013

Clang's AST dump AKA 'WTH is the compiler doing???'

It's no secret that I use the Clang compiler for development. Although GCC is still somewhat better when things like the performance of the resulting code matter, there are other features that matter more during development. And although again competition helps (it's not difficult to guess where the inspiration for the new error reporting in 4.8 comes from), there are features where I expect it'd be hard for GCC to match Clang. The capabilities and ease of writing Clang plugins is one thing, but there are more hidden secrets, like the AST dump.

If Clang is invoked also with -Xclang -ast-dump options, it'll dump its internal representation of the compiled source. Which can be pretty useful when the source code doesn't actually mean what one expects, or if there's something unexpected from elsewhere interfering. Consider the following (simple, for clarity) example:

#include <iostream>
using namespace std;

class A
    {
    };

class B
    {
    public:
        operator A() const { return A(); }
    };

class C
    : public B
    {
    };

void foo( const A& )
    {
    cout << "A" << endl;
    }

void foo( B& )
    {
    cout << "B" << endl;
    }

int main()
    {
    foo( C());
    } 


Looking only at class C, it may perhaps come as a surprise to some that this prints "A" and not "B". And overlooking the missing const or not knowing that it will prevent passing the temporary to the function certainly helps with the surprise, but even if not, still, so what is actually going on? With larger codebase, that can be a lot of time to find out. But finding out what the compiler thinks about the code can help:

$ clang++ -Wall a.cpp -Xclang -ast-dump
...
 `-FunctionDecl 0x90ffb90 <line:29:1, line:32:5> main 'int (void)'
  `-CompoundStmt 0x9100078 <line:30:5, line:32:5>
    `-CallExpr 0x90fffb8 <line:31:5, col:13> 'void'
      |-ImplicitCastExpr 0x90fffa8 <col:5> 'void (*)(const class A &)' <FunctionToPointerDecay>
      | `-DeclRefExpr 0x90fff74 <col:5> 'void (const class A &)' lvalue Function 0x90fec80 'foo' 'void (const class A &)'
      `-MaterializeTemporaryExpr 0x9100068 <col:10, col:12> 'const class A' lvalue
        `-ImplicitCastExpr 0x9100058 <col:10, col:12> 'const class A' <NoOp>
          `-ImplicitCastExpr 0x9100048 <col:10, col:12> 'class A' <UserDefinedConversion>
            `-CXXMemberCallExpr 0x9100028 <col:10, col:12> 'class A'
              `-MemberExpr 0x9100008 <col:10, col:12> '<bound member function type>' .operator A 0x90fe740
                `-ImplicitCastExpr 0x90ffff8 <col:10, col:12> 'const class B' <UncheckedDerivedToBase (B)>
                  `-CXXTemporaryObjectExpr 0x90ffdd8 <col:10, col:12> 'class C' 'void (void)' zeroing


Knowing a bit about how compilers work helps a lot, but even without it this is quite simple to read. From bottom to up, there's a temporary object of class C created and it's cast to its base class B. That's the expected part, the unexpected part is the 3 AST nodes up, which show that the object is converted to class A by a user defined conversion using operator A(). Which, as the rest of this part of the AST dump shows, results in calling foo( const A& ). Mystery solved.

(Fun trivia: I once helped a GCC developer to disentangle a problem in a complex C++ testsuite using this. But don't tell anyone ;) . )



Monday, April 8, 2013

Icecream 1.0.0 released

After almost 10 years since the first version, version 1.0.0 of the Icecream distributed build tool has been released.


Yes, it's been almost a decade with us. And as it usually is with versions 1.0.0 after such a long time, it doesn't actually bring anything breadth-taking. But there of course have been some fixes and improvements since version 0.9.7, and in fact even one larger feature found its way in, out-of-the-box support for the Clang compiler, including support for its plugins. Written by yours truly, after finding out about this compiler and finding out it was pretty difficult to get it to work with 0.9.7 icecream at least in some way. And also being the reason for repeatedly bugging Coolo about another icecream release :) .

And, on the way to 1.0.0, the development repository has been moved to GitHub. Which should be good, as IMO the fact that it used to be developed in the KDE SVN helped to make the false impression that it is somehow specific to KDE, limiting its use among developers of other projects. This is probably actually the biggest feature of the 1.0.0 release.

So, thanks to everyone who has helped to make compiling a much more pleasant experience (possibly even with the added colors in the icecream monitor ;) ).