Я столкнулся со странной ошибкой, когда пытался использовать libclang в приложении Qt.
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
Если я вручную запускаю g ++ без использования qmake, я получаю ту же ошибку:
$ 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 программа компилируется и запускается, даже если она входит в основной цикл без показанного окна.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.
По какой причине эта программа не работает и как я могу это исправить?
Обновить: я обнаружил эта страница.
Бег LIBGL_ALWAYS_INDIRECT=1 ./test
работает хорошо, но я хочу больше, чем это. Мне не нужно было устанавливать эту переменную окружения, чтобы иметь возможность запускать мою программу.
Я могу ответить на ваш вопрос о том, что идет не так, я не знаю, как это исправить.
Во-первых, удаление CXIndex index = clang_createIndex(0, 0);
не исправить вещи, если бы у вас не было -Wl,--as-needed
его удаление исправляет только потому, что компоновщик заметил, что вы на самом деле не вызывали libclang, и поэтому не связывали вашу программу с ним без CXIndex index = clang_createIndex(0, 0);
линия.
Причина этого заключается в том, что любой используемый в Mesa бэкэнд (ATI или NVIDIA) также связывается с клангом. Кажется, что происходит то, что когда ваша программа загружается впервые и динамические ссылки разрешаются, компоновщик запускает и загружает 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 ссылается на другую версию, которая может что-то объяснить.
Других решений пока нет …