当我尝试在Qt应用程序中使用libclang时,我遇到了一个奇怪的错误。
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命令和输出:
$ 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
如果我在不使用qmake的情况下手动运行g ++,我会收到同样的错误:
$ 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();
行程序,即使它在没有显示窗口的情况下进入主循环,程序也会编译并运行。CXIndex index = clang_createIndex(0, 0);
和Q_UNUSED(index)
行,程序将编译并运行。它进入主循环,窗口可见。我正在使用Qt 5.1和ArchLinux,我安装了clang
软件包(版本3.3),其中包含libclang头文件和文件/usr/lib/libclang.so和/usr/lib/libclang.a
该程序无效的原因是什么?如何解决?
更新:我找到了this page。
运行LIBGL_ALWAYS_INDIRECT=1 ./test
运行良好,但我想要更多。我不应该设置该环境变量才能运行我的程序。
答案 0 :(得分:2)
我可以回答你关于出了什么问题的问题,我不知道如何修复它。
首先,删除CXIndex index = clang_createIndex(0, 0);
不会解决问题,如果你没有-Wl,--as-needed
删除它只修复它,因为链接器注意到你实际上没有调用libclang,所以没有实际上,在没有CXIndex index = clang_createIndex(0, 0);
行的情况下将您的程序链接到它。
之所以破坏是因为您正在使用的Mesa后端(ATI或NVIDIA)也会链接到clang。似乎正在发生的事情是,当您的程序首次加载并且动态链接已解析时,链接器将加载libclang和其他LLVM内容libclang链接并运行全局对象的构造函数,这就是LLVM如何自动注册内置传递的方式。因此,此时所有内置的LLVM传递都已注册,然后QT启动并创建一个OpenGL上下文,因此Mesa加载适当的DRI后端,并且在系统上发生后端使用clang / LLVM,并且由于某种原因似乎所有这些构造函数再次运行,LLVM注意到“两个”传递(实际上是尝试自己注册两次的同一传递)共享相同的名称并中止您的程序。
就像我说的那样,我真的不知道为什么构造函数会运行两次而且我不知道如何让它停止。如果您没有得到答案,请尝试询问mesa-users
邮件列表,然后尝试mesa-dev
梅萨邮件列表:http://mesa3d.org/lists.html
编辑:您应该确保您的Mesa副本与您尝试使用的相同版本的LLVM相关联,如果它没有修复通行证注册事项将是您遇到的最少问题。
尝试执行ls /usr/lib64/llvm/libLLVM-?.?.so
如果你得到两件事你有两个版本的libLLVM,这本身就不是问题,但如果你是针对一个版本链接而Mesa链接针对可能解释的不同版本的东西。