X-Developer Cross-platform development in C++, Flight Simulation

7Sep/11Off

Fun with clang or: How to build Qt 4.8 with clang 3 without going insane

Given that XCode 4 on Mac ships with the the clang frontend for LLVM now, I wanted to give this new compiler a try and see if it can replace gcc for me.

To compile the CRJ plugin, I need Qt of course, and given this entry in the Qt blogs I thought it would be fairly easy to get this to work.

I was wrong.

First try: I checked out the Qt 4.8 branch from gitorious, and configured with -platform unsupported/macx-clang but I soon ran into a compile error complaining about an undeclared identifier "SetRect".

Second try: I checked out the specific git revision mentioned in the blog post, and re-configured. Build stops with the same error.

Thrid try: Given that the most recent clang is the 3.0 branch and that Apple ships 2.1, I decided to get myself a more recent clang. I checked out the llvm sources via svn, then the clang sources in the appropriate subdirectory, configured for a release-optimzed build (to boldly go...) and make'd. Some 10 or 20 minutes later I had a clang 3.0. I edited the mkspecs/common/clang.conf to point to my freshly compiled clang in /usr/local/bin and reconfigured Qt (I checked out master/HEAD before).  Now the built took longer before it stopped, this time everything of QtCore compiled, but when linking, I got an "undefined symbol for architecture i386: ___eprintf". Oh well.

Fourth try: Google pointed me to this thread which indicated I must built the compiler runtime also. So I did another svn checkout (compiler-rt into llvm/projects/), make clean'd, re-configured and built llvm/clang/compiler-rt again. The built aborted mocking about some missing headers for ARM.

Fifth try: I reconfigured llvm with --enable-architecture=x86 instead of the default --enable-architecture=all, which would built all kinds of backend. The next built took somewhat longer and perhaps 30 minutes later I was ready to try again: with the freshly installed clang I went ahead to compile Qt again. This time it actually linked QtCore, but when compiling QtGui it stopped again with a compiler error:

src/gui/kernel/qt_cocoa_helpers_mac_p.h:218:10: error:
cannot initialize return object of type 'NSString *'
with an rvalue of type 'const NSString *'

Apparently, clang doesn't like Cocoa.

Sixth try: I make confclean'd and re-configured Qt to build with -carbon. Unfortunately, the next make stopped at exactly the same location, at the Cocoa-helpers. Apparently this header is pulled in every time regardless whether we actually use Cocoa or not.

At this point, I decided to give up on OSX and try my luck on Linux.

I svn co'd llvm, clang and compiler-rt to my Suse, configured for optimzed built and started make. Short time after that *KABOOOM!*. No, not a compile error. GCC crashed. My compiler trapped during compiling. Seriously, WTF? I was first confused by the print output of GCC, that referred to a source file that I wasn't compiling at all, until it occurred to me that the indicated source was a source of GCC, a GCC function that crashed.

Oh the humanity! I went to the #clang channel on irc.freenode.net and luckily some helpful soul indicated what I should do. GCC would break regularly during optimized clang compiles. The way to go would be to build clang with clang

  1. First, build clang in debug mode without optimizations with gcc
  2. Then, use the un-optimized clang to build an optimized clang

Luckicly, this guy was spot on. I had encountered this error that prevents GCC 4.5.0 to build clang with -ftree-vectorize. So the non-optimized built succeeded, and then I was able to bootstrap the optimized clang from it.

I checked out Qt master again and configured with -platform unsupported/linux-clang. Build was uneventful, and my minimal testing-Qt (without webkit, Javascript, QtScript, QDeclarative, etc...) was ready within some 30 or 45 minutes.

Configuring Qt-Creator 2.3 to recognize clang as compiler and display its warnings was straightforward.

Now I took a deep breath and compiled my airnav library on -Wall, which is a lot more pedantic than the -Wall of gcc. And bingo!!
The -Wall -Wextra compile however showed some minor warnings that I've never seen with gcc - it complained about an explicit template instantiation outside the namespace of the template. This was fixed changing two lines of code, and after that I got it through -Werror -Wall -Wextra. W00t!

Lessons learned:

  • clang is not yet ready to be used on a regular day-to-day basis and still requires lots of fiddling
  • Qt's codebase is relatively clean, as it compiles with clang with relatively few warnings
  • the Cocoa headers of the 10.7 SDK however are not
  • It is great to have yet another reference compiler to check for code-cleanliness

So I reached at least one of my goals: I have another reference compiler I can test my code against: I regularly compile my whole codebase with Visual C++ 10 and gcc 4. Now I have another testing point that reveals more potential issues (portability, unsafe assumptions).

I won't ship clang-compiled plugins to end-users soon, but I will definitely use clang-build plugins myself now for testing purposes.

  • del.icio.us
  • Digg
  • email
  • Facebook
  • Google Buzz
  • Identi.ca
  • MisterWong
  • MySpace
  • Orkut
  • Print
  • Reddit
  • RSS
  • Slashdot
  • StumbleUpon
  • Technorati
  • Twitter
Tagged as: , , Comments Off
Comments (0) Trackbacks (0)

Sorry, the comment form is closed at this time.

Trackbacks are disabled.