7

I encountered a strange bug when I tried to use libclang in a Qt application.

test.cpp

#include <QApplication>
#include <QMainWindow>

#include <clang-c/Index.h>

int main (int argc, char *argv[]) {
    QApplication a(argc, argv);

    QMainWindow w;
    w.show();

    CXIndex index = clang_createIndex(0, 0);
    Q_UNUSED(index)

    return a.exec();
}

test.pro

QT += core widgets

TARGET = test
TEMPLATE = app

SOURCES += test.cpp

LIBS += -lclang

Shell commands and output:

$ ls
test.cpp test.pro
$ qmake
$ make
g++ -c -pipe -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -Wall -W -D_REENTRANT -fPIE -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt/mkspecs/linux-g++ -I. -I/usr/include/qt -I/usr/include/qt/QtWidgets -I/usr/include/qt/QtGui -I/usr/include/qt/QtCore -I. -o test.o test.cpp
g++ -Wl,-O1,--sort-common,--as-needed,-z,relro -Wl,-O1 -o test test.o   -lclang -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 
$ ./test
Two passes with the same argument (-alloca-hoisting) attempted to be registered!
Segmentation fault

If I manually run g++ without using qmake, I get the same error:

$ g++ -fPIE test.cpp -o test -I/usr/include/qt -I/usr/include/qt/QtWidgets -lQt5Widgets -lclang
$ ./test
Two passes with the same argument (-alloca-hoisting) attempted to be registered!
Segmentation fault
  • If I comment the w.show(); line the program compiles and runs even if it enters the main loop without the window shown.
  • If I comment the CXIndex index = clang_createIndex(0, 0); and Q_UNUSED(index) lines, the program compiles and runs. It enters the main loop with the window visible.
  • I also compiled this with clang and I get the same error message.
  • I searched the web and I found only this result with a similar error message but I don't know if and how it can help me: http://comments.gmane.org/gmane.comp.compilers.llvm.devel/34647 .

I am using Qt 5.1 and ArchLinux, I have the clang package (version 3.3) installed which includes the libclang headers and the files /usr/lib/libclang.so and /usr/lib/libclang.a.

What is the reason why this program does not work and how can I fix it?


Update: I've found this page. Running LIBGL_ALWAYS_INDIRECT=1 ./test works well, but I want more than this. I shouldn't have to set that environment variable to be able to run my program.

silviubogan
  • 3,343
  • 3
  • 31
  • 57
  • Try putting -lclang after -lGL. Sometimes weird linker issues are due to having things in the wrong order. Mesa uses LLVM for shaders so that might be the source of your problem – Spudd86 Jul 30 '13 at 19:45
  • This might be helpful http://llvm.org/bugs/show_bug.cgi?id=6801 – Spudd86 Jul 30 '13 at 19:51
  • @Spudd86 I tried `g++ -fPIE test.cpp -o test -I/usr/include/qt -I/usr/include/qt/QtWidgets -lGL -lQt5Widgets -lclang` and I get the same runtime error. – silviubogan Jul 31 '13 at 06:33
  • After reading that bug report, I tried to link against some .a files I have in the /usr/lib directory which I believe are the clang modules (as seen here: http://clang.llvm.org/doxygen/dirs.html , under clang/lib): libclangTooling.a, libclangAST.a, libclangFrontend.a etc. I was thinking that maybe if I link only to the clang modules I need, there won't be any conflicts. But none of these files had the `clang_createIndex` function so I got the `undefined reference to 'clang_createIndex'` error. – silviubogan Jul 31 '13 at 07:00
  • LIBGL_ALWAYS_INDIRECT=1 is not something you want to set anyway, you loose access to most of OpenGL post 1.4 because it's sending your GL commands to the X server and there is no protocol for less than ancient GL – Spudd86 Aug 27 '13 at 15:18
  • I don't know how to fix your link issues properly but indirect works because it's not actually loading a dri driver – Spudd86 Aug 27 '13 at 15:20
  • Try asking on the Mesa mailing lists http://lists.freedesktop.org/mailman/listinfo/mesa-users they might be able to tell you how to link it in a way that doesn't break – Spudd86 Aug 27 '13 at 15:30
  • Why are you using the C interface to clang in a C++ program? – Spudd86 Aug 27 '13 at 15:34

1 Answers1

2

I can answer the part of you question about what's going wrong, I don't know how to fix it.

First, removing the CXIndex index = clang_createIndex(0, 0); wouldn't fix things if you didn't have -Wl,--as-needed removing it only fixes it because the linker noticed you didn't actually call into libclang and so didn't actually link your program to it without the CXIndex index = clang_createIndex(0, 0); line.

The reason things a breaking is because whatever Mesa backend you are using (either ATI or NVIDIA) also links against clang. What seems to be happening is that when your program is first loaded and dynamic links resolved the linker goes and loads libclang and other LLVM stuff libclang links to and runs the constructors for global objects, which is how LLVM registers it's built in passes automatically. So at this point all of the built in LLVM passes are registered, then QT starts up and it creates an OpenGL context so Mesa loads the appropriate DRI backend and as it happens on your system that backend uses clang/LLVM, and for some reason it seems that all those constructors run again and LLVM notices that "two" passes (actually the same pass trying to register itself twice) share the same name and aborts your program.

Like I said I don't really know why the constructors are running twice and I don't know how to make it stop. Try asking on the mesa-users mailing list if you don't get an answer there try mesa-dev

Mesa mailing lists: http://mesa3d.org/lists.html

EDIT: You should make sure that your copy of Mesa is linked against the same version of LLVM that you are trying to use, if it's not fixing the pass registration thing will be the least of your problems.

Try doing ls /usr/lib64/llvm/libLLVM-?.?.so if you get two things back you have two versions of libLLVM which is not a problem on it's own, but if you're linking against one version and Mesa links against a different version that might explain things.

Spudd86
  • 2,986
  • 22
  • 20