Mon, 02/03/2014 - 23:58
Time flies… The extremely productive hack sprint at the friendly Blue Systems office in Barcelona is over for more than a week. I haven’t had time to blog about the last days yet which I hereby make good for!
I spent a lot of time at the sprint polishing the KDevelop Clang plugin. A up-to-now semi-secretly developed language plugin based on clang which will replace our current C++ language support in KDevelop in the long-run.
Code completion of
std::string in a
Showing a clang-generated warning inside the editor.
Nested clang diagnostics with browsing support.
KDevelop’s current C++ plugin
But a bit of history first: KDevelop’s current C++ language plugin can pull off what it does by essentially implementing (parts of) the C++ standard. We have our own C++ parser, we have our own implementation of the C++ template mechanism, we have our own share of “compiler bugs”, …. It should not surprise anyone that this is a maintenance nightmare. And indeed, with C++11 and the wealth of changes it came with our language simply fails in many areas. The current codebase is big (~55k sloc) and adding support for complicated features such as variadic templates or constexpr is extremely hard and fragile. So instead of doing that, my colleague Olivier JG started looking into using clang of LLVM fame instead. It promises an API for third-party tools to steer a C/C++/Objective-C compiler to their needs. Its the magic bullet which we waited for, and which did not exist back when KDevelop 4.0 was started initially.
So Olivier started hacking on
kdev-clang. In his initial prototyping he experimented with the C++ API to clang but eventually found that the
clang-c API suffices for our needs. The big advantage is that the latter comes with an API/ABI guarantee which is important for us as a consumer. After some failed attempts in getting clang to parse medium-sized projects at reasonable speeds, he eventually found the magic flags and options. So after the hard work was done, I started contributing by playing the plumber who massages the output of clang-c into the existing KDevelop framework.
kdev-clang plugin consists of ca. 2000 lines of code. Add a bit more than 600 lines of tests and you are still a magnitude below our current C++ plugin. Sure, if you count the lines of code in clang/LLVM this won’t stand anymore, but from a maintenance point of view this is a blessing. We can actually concentrate on making our IDE shine instead of playing catchup with the compiler.
The plugin already supports:
- parsing of full projects, supporting all C++ features that clang supports
- semantic highlighting
- code browsing
- basic code completion, including macros
- embedding of clang diagnostics, even supporting navigation between nested diagnostics
What’s currently missing:
- assistants: rename, add type, synchronize signature, …
- refactoring: move to source, rename, …
- more advanced code completion: implement function, override virtual function, …
- context-browsing for macros
- switches for plain C, Objective-C support
I always feared that using clang instead of our hand-written parser would lead to abysmal performance. I’ve heard bad stories about XCode 4.0 which was the first IDE to use clang internally. And the Qt-Creator guys also said they don’t want to use clang for their code model as its performance was not good enough. Thankfully, all of this turned out to be false alarm: On one hand Apple invested a lot into clang and made it much faster, also for the usage in XCode apparently. Secondly, Qt-Creator’s blazingly fast status-quo comes at the cost of only supporting a (relatively small) subset of C++. So yes, clang is slower at parsing a big project than doing the same in QtCreator. But more importantly: clang is faster than the old KDevelop C++ support! The reason is that it scales far batter with multiple cores than our old language plugin. So yes, it uses more instructions to analyse a code sample. At the same time it gives us much more than we had in terms of language support and diagnostics. But since it can do so in parallel, it finishes parsing quicker!
A bit of technical background: In our
parsesession.cpp we invoke
clang_parseTranslationUnit(). We configure it to use a
CXTranslationUnit_PrecompiledPreamble and cache the resulting translation unit for future
clang_reparseTranslationUnit() when the document is currently open. Combined, this allows for extremely fast updates when the user types something in his editor. In addition, we can use our internal cache to minimize the amount of times we must invoke clang. And I plan to investigate how to generate precompiled headers, which one could then do for third-party libraries such as the STL, Qt or the KDE frameworks. This would speed up clang even more, both inside KDevelop and while parsing! Even better, eventually we’ll get C++ modules and all of this will become extremely fast and easy to handle!
TAKE MY CODE
So the above is like a fairy tale come true from my pov! If you are thinking “shut up and tell me how to use this awesome stuff” despite of the shortcomings I listed above, then the following is just what you want.
But, first a big warning: The old C++ plugin and
kdev-clang don’t like each other, in the sense of leading to runtime asserts when both are loaded into the same KDevelop session. See below for how to circumvent this.
- compile KDevplatform/KDevelop from current master: http://techbase.kde.org/Projects/KDevelop4/HowToCompile
- grab the sources for kdev-clang: https://projects.kde.org/projects/playground/devtools/plugins/kdev-clang
- compile it, run
- run KDevelop but disable the old C++ plugin, also wipe your cache:
CLEAR_DUCHAIN_DIR=1 KDEV_DISABLE_PLUGINS=kdevcppsupport kdevelop -s ...
- alternatively, uninstall the old C++ plugin (search and delete
*kdev*cpp*in your install prefix). You can also disable compilation of the old C++ plugin by passing
AGAIN: Don’t run KDevelop with both, kdev-clang and kdevcppsupport!
Otherwise: Happy hacking and make sure to keep an eye on
kdev-clang! I’m sure its going to progress nicely and I’m eagerly awaiting the day where I can close all C++-related bug reports and delete over 55 thousand lines of code :)
Many thanks to Olivier for spearheading this plugin! And thanks already to the first contributors and early-adapters. Finally, once more many thanks to Aleix for organizing this awesome KDevelop/Kate sprint in Barcelona. Looking forward to the next time! Thanks also to his employer Blue Systems for providing the hack space. And as usual my gratitude to the KDE e.V. for sponsoring this event and to all the donors.
If you like Kate and/or KDevelop, please consider Joining the Game to ensure sprits such as this one can continue to take place in the future!