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
w.show();
line the program compiles and runs even if it enters the main loop without the window shown.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 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With