Building Qt with LLVM

Hello, Everyone.

Just few notes for everyone, who wants to build Qt with llvm.

Everything was tested with shiny-new Qt 4.2.2 (X11 version) and
llvm-gcc4 & LLVM from head. Instructions written here should also work
on 1.9 release, as I've tested Qt build last time just before 1.9
release.

1. Specs
Qt uses it's own configuration and build system called "qmake". We
should slightly change its configuration to allow usage of llvm-gcc4
instead of original gcc.

--- mkspecs/common/g++.conf 2006-11-27 20:26:01.000000000 +0300
+++ mkspecs/common/g++.conf 2006-12-15 01:20:47.993289310 +0300
@@ -1,5 +1,5 @@

-QMAKE_CC = gcc
+QMAKE_CC = /path/to/llvm-gcc/llvm-gcc
QMAKE_LEX = flex
QMAKE_LEXFLAGS +=
QMAKE_YACC = yacc
@@ -18,7 +18,7 @@
QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses
QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden

-QMAKE_CXX = g++
+QMAKE_CXX = /path/to/llvm-gcc/llvm-g++
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS
QMAKE_CXXFLAGS_DEPS += $$QMAKE_CFLAGS_DEPS
QMAKE_CXXFLAGS_WARN_ON += $$QMAKE_CFLAGS_WARN_ON
@@ -30,8 +30,8 @@
QMAKE_CXXFLAGS_YACC += $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS
-fvisibility-inlines-hidden

-QMAKE_LINK = g++
-QMAKE_LINK_SHLIB = g++
+QMAKE_LINK = /path/to/llvm-gcc/llvm-g++
+QMAKE_LINK_SHLIB = /path/to/llvm-gcc/llvm-g++
QMAKE_LFLAGS +=
QMAKE_LFLAGS_RELEASE +=
QMAKE_LFLAGS_DEBUG +=

LLVM does not support inline FP assembler well. Workaround it:

--- mkspecs/common/linux.conf 2006-11-27 20:26:01.000000000 +0300
+++ mkspecs/common/linux.conf 2006-12-15 01:20:55.509146726 +0300
@@ -1,4 +1,4 @@
-QMAKE_CFLAGS_THREAD += -D_REENTRANT
+QMAKE_CFLAGS_THREAD += -D_REENTRANT -D__NO_MATH_INLINES
QMAKE_CXXFLAGS_THREAD += $$QMAKE_CFLAGS_THREAD

QMAKE_INCDIR =

2. Configure
LLVM itself does not support mmx/sse intrinsics. Due to unknown reason
Qt's own configure was unable to detect it. So, we just force "sse=no":

--- configure 2006-11-27 20:26:42.000000000 +0300
+++ configure 2006-12-15 02:02:36.669912494 +0300
@@ -2144,12 +2144,7 @@
     fi
fi

-# detect sse support
-if "$unixtests/sse.test" "$TEST_COMPILER" "$OPT_VERBOSE"; then
- CFG_HAVE_SSE=no
-else
- CFG_HAVE_SSE=yes
-fi
+CFG_HAVE_SSE=no

# check iwmmxt support
if [ "$CFG_IWMMXT" = "yes" ]; then

I've configured Qt with -no-exceptions -no-stl -static. I haven't tried
shared built yet. Probably, enabling exception will break the build,
since llvm-gcc4 does not support exceptions well yet.

3. Workaround some llvm-gcc4 "not supported yet" stuff
3.1 Inline FP assembler:

--- src/gui/painting/qmath_p.h 2006-11-27 20:26:07.000000000 +0300
+++ src/gui/painting/qmath_p.h 2006-12-16 01:16:41.169530170 +0300
@@ -57,7 +57,7 @@
{ return d >= 0.0 ? int(d) : int(d - 0.9999); }

#ifdef Q_WS_X11
-#if defined(Q_CC_GNU) && defined(__i386__)
+#if defined(Q_CC_GNU) && defined(__i386__) && !defined(__llvm__)

inline double qCos_x86(double a)
{

3.2 Multiple specs in inline assembler:
--- src/corelib/arch/qatomic_i386.h 2006-11-27 20:26:05.000000000 +0300
+++ src/corelib/arch/qatomic_i386.h 2006-12-15 01:45:07.097471758 +0300
@@ -36,7 +36,7 @@
     asm volatile("lock\n"
                  "cmpxchgl %2,%3\n"
                  "sete %1\n"
- : "=a" (newval), "=qm" (ret)
+ : "=a" (newval), "=m" (ret)
                  : "r" (newval), "m" (*ptr), "0" (expected)
                  : "memory");
     return static_cast<int>(ret);
@@ -65,7 +65,7 @@
     asm volatile("lock\n"
                  "incl %0\n"
                  "setne %1"
_ : "=m" (*ptr), "=qm" (ret)
+ : "=m" (*ptr), "=m" (ret)
                  : "m" (*ptr)
                  : "memory");
     return static_cast<int>(ret);
@@ -77,7 +77,7 @@
     asm volatile("lock\n"
                  "decl %0\n"
                  "setne %1"
- : "=m" (*ptr), "=qm" (ret)
+ : "=m" (*ptr), "=m" (ret)
                  : "m" (*ptr)
                  : "memory");
     return static_cast<int>(ret);

Now Qt builds fine and (even more!) runs (see attached screenshot).

PS: mingw32 build is broken due to http://llvm.org/PR1015

Everything was tested with shiny-new Qt 4.2.2 (X11 version) and
llvm-gcc4 & LLVM from head. Instructions written here should also work
on 1.9 release, as I've tested Qt build last time just before 1.9
release.

Nice!

2. Configure
LLVM itself does not support mmx/sse intrinsics. Due to unknown reason
Qt's own configure was unable to detect it. So, we just force "sse=no":

LLVM does support SSE intrinsics, but does not yet support MMX. Can you file a bug with information about this? I believe the other issues already have bugs. Thanks!

-Chris