无法将libclang与Qt一起使用

Cannot use libclang with Qt

本文关键字:一起 Qt libclang      更新时间:2023-10-16

当我尝试在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

外壳命令和输出:

$ 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)行进行注释,程序就会编译并运行。它进入主循环,窗口可见
  • 我也用clang编译了这个,得到了同样的错误消息
  • 我在网上搜索了一下,只发现了这个带有类似错误消息的结果,但我不知道它是否以及如何帮助我:http://comments.gmane.org/gmane.comp.compilers.llvm.devel/34647

我使用的是Qt 5.1和ArchLinux,我安装了clang包(3.3版),其中包括libclang头文件和/usr/lib/libcrang.so和/usr/lib-libcrang.a文件。

这个程序不起作用的原因是什么?我该如何修复它?


更新:我找到了这个页面。运行LIBGL_ALWAYS_INDIRECT=1 ./test效果很好,但我想要的不止这些。我不应该为了运行我的程序而设置那个环境变量。

我可以回答你关于出了什么问题的部分,我不知道如何解决它。

首先,如果没有-Wl,--as-needed,删除CXIndex index = clang_createIndex(0, 0);并不能解决问题。删除它只是修复它,因为链接器注意到你实际上没有调用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

Mesa邮件列表:http://mesa3d.org/lists.html

编辑:你应该确保你的Mesa副本链接到你试图使用的LLVM的同一版本,如果它不能解决通行证注册问题,那将是你最小的问题。

试着做ls /usr/lib64/llvm/libLLVM-?.?.so,如果你得到了两个东西——你有两个版本的libLLVM,这本身不是问题,但如果你链接到一个版本,而Mesa链接到另一个版本——这可能会解释问题。