2013-07-30 12 views
6

Ho incontrato uno strano bug quando ho provato a usare libclang in un'applicazione Qt.Impossibile usare libclang con 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 

comandi Shell e uscita:

$ 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 

Se corro manualmente g ++ senza utilizzare qmake, I ottenere lo stesso errore:

  • Se io commento la linea w.show(); il programma viene compilato ed eseguito anche se si entra nel ciclo principale, senza la finestra mostrata.
  • Se commento le righe CXIndex index = clang_createIndex(0, 0); e Q_UNUSED(index), il programma viene compilato ed eseguito. Entra nel ciclo principale con la finestra visibile.
  • Ho anche compilato questo con clang e ottengo lo stesso messaggio di errore.
  • Ho cercato sul Web e ho trovato solo questo risultato con un messaggio di errore simile ma non so se e come può aiutarmi: http://comments.gmane.org/gmane.comp.compilers.llvm.devel/34647.

Sto usando Qt 5.1 e ArchLinux, ho il pacchetto clang (versione 3.3) installato che comprende le intestazioni libclang ei file /usr/lib/libclang.so e /usr/lib/libclang.a.

Qual è il motivo per cui questo programma non funziona e come posso risolverlo?


Update: ho trovato this page. In esecuzione LIBGL_ALWAYS_INDIRECT=1 ./test funziona bene, ma voglio più di questo. Non avrei dovuto impostare quella variabile d'ambiente per poter eseguire il mio programma.

+0

Prova a inserire -lclang dopo -lGL. A volte problemi di linker strani sono dovuti ad avere le cose nell'ordine sbagliato. Mesa usa LLVM per gli shader in modo che questa possa essere la fonte del tuo problema – Spudd86

+0

Questo potrebbe essere utile http://llvm.org/bugs/show_bug.cgi?id=6801 – Spudd86

+0

@ Spudd86 Ho provato 'g ++ -fPIE test.cpp -o test -I/usr/include/qt -I/usr/include/qt/QtWidgets -lGL -lQt5Widgets -lclang' e ottengo lo stesso errore di runtime. – silviubogan

risposta

2

Posso rispondere alla parte di voi su cosa sta andando male, non so come risolverlo.

In primo luogo, la rimozione dello CXIndex index = clang_createIndex(0, 0); non risolveva le cose se non si avesse -Wl,--as-needed rimuovendolo si risolve solo perché il linker ha notato che in realtà non si chiama in libclang e quindi non ha effettivamente collegato il programma ad esso senza la linea CXIndex index = clang_createIndex(0, 0);.

La ragione per cui le cose si rompono è perché qualsiasi backend Mesa che si sta utilizzando (ATI o NVIDIA) si collega anche a clang. Quello che sembra accadere è che quando il tuo programma viene caricato per la prima volta e risolti i link dinamici, il linker va e carica libclang e altri LLVM roba collegamenti libclang a ed esegue i costruttori per gli oggetti globali, che è il modo in cui LLVM registra automaticamente i passaggi incorporati. Quindi a questo punto vengono registrati tutti i passaggi LLVM incorporati, quindi viene avviato QT e viene creato un contesto OpenGL in modo che Mesa carichi il backend DRI appropriato e come accade sul sistema che backend utilizza clang/LLVM e per qualche motivo lo fa Sembra che tutti quei costruttori funzionino di nuovo e LLVM nota che "due" passaggi (in realtà la stessa passata che tenta di registrarsi due volte) condividono lo stesso nome e interrompono il programma.

Come ho detto, non so davvero perché i costruttori sono in esecuzione due volte e non so come farlo smettere. Prova a chiedere sulla mesa-users mailing list, se non si ottiene una risposta ci prova mesa-dev

Mesa mailing list:

EDIT: Si dovrebbe fare in modo che la copia di Mesa è legata contro la stessa versione di LLVM che stai cercando di usare, se non sta risolvendo il problema di registrazione del pass sarà l'ultimo dei tuoi problemi.

Provare a fare ls /usr/lib64/llvm/libLLVM-?.?.so se si ottengono due cose indietro si hanno due versioni di libLLVM che non è un problema per conto proprio, ma se si sta collegando una versione e collegamenti Mesa con una versione diversa che potrebbe spiegare le cose.