不能在Qt中使用libclang

sil*_*gan 6 c++ qt clang libclang

当我尝试在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();
}
Run Code Online (Sandbox Code Playgroud)

test.pro

QT += core widgets

TARGET = test
TEMPLATE = app

SOURCES += test.cpp

LIBS += -lclang
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

如果我在不使用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
Run Code Online (Sandbox Code Playgroud)
  • 如果我对该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/libclang.so和/usr/lib/libclang.a.

这个程序不起作用的原因是什么,我该如何解决?


更新:我找到了这个页面.跑步LIBGL_ALWAYS_INDIRECT=1 ./test效果很好,但我想要更多.我不应该设置该环境变量才能运行我的程序.

Spu*_*d86 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 链接到另一个版本,这可能会解释问题。