2014-12-02 7 views
5

Problema: sto creando un progetto esterno in CMake. Il progetto ha un Makefile che alla fine produce un oggetto condiviso. Voglio collegarmi e installare questo oggetto nel mio super progetto, proprio come se fosse una delle librerie del progetto. Il problema è che la libreria ExternalProject viene collegata alle mie applicazioni e alle mie librerie con un percorso relativo, non un percorso assoluto che causa problemi quando si esegue da una directory diversa da quella in cui si trova CMake.CMake: il collegamento di oggetti C++ condivisi da ExternalProject produce binari con percorso relativo, non assoluto

Ho created a sample SSCCE example project per dimostrare la mia configurazione generale. Sentiti libero di leggere e compilare se necessario (git clone https://github.com/calebwherry/cmake-SO-question-main --recursive && cd cmake-SO-question-main && mkdir build && cd build && cmake .. && make && cd src/app/testApp && ldd testApp).

Ogni volta che corro ldd sul file eseguibile e librerie, ottengo output come questo:

linux-vdso.so.1 => (0x00007fff8b5a2000) 
    libTestLib.so => /home/jwherry3/repos/cmake-superprj-main-test/build/src/lib/TestLib/libTestLib.so (0x00007f592da57000) 
    ../../lib/libExtLib.so (0x00007f592d855000) 
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f592d539000) 
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f592d2b7000) 
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f592d0a0000) 
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f592cd14000) 
    /lib64/ld-linux-x86-64.so.2 (0x00007f592dc5a000) 

Ho provato tutti i tipi di cose che si occupano di RPATHS ma non può ottenere l'EXTLIB di collegare destra. La lib locale al progetto (libTestLib.so) si collega bene.

Ho anche provato a impostare LD_LIBRARY_PATH per sovrascrivere il percorso relativo quando eseguo l'app, ma anche quando lo faccio, non trova ancora la libreria. Suppongo perché è relativo non segue il normale ordine di collegamento? Il risultato è che il file binario non verrà eseguito a meno che non sia nella directory in cui risiede.

Mi sento come se stessi facendo qualcosa di veramente stupido quando creo dipendenze con ExternalProject e questo è il mio problema, ma ho battuto la mia testa per 3 giorni e non ho inventato nulla.

Impostazioni di sistema: Debian Wheezy 64-bit, CMake 3.0.2, g ++ - 4.9.2.

+0

Ancora nessun colpo, eh? Comunque, ho temporaneamente risolto il problema facendo in modo che il progetto esterno costruisse una lib statica e collegasse quella invece della lib condivisa. Non è una soluzione a lungo termine, ma almeno che ottiene questo per funzionare correttamente. Ho aggiornato il repository per avere questa opzione per gli altri ma devi cambiarlo manualmente in ext/CMakeLists.txt per attivarlo. – Caleb

+0

scusa, non ho notato la risposta – Slava

risposta

1

Ci sono voluti un po 'ma alla fine sono arrivato a una risposta con l'aiuto degli utenti di CMake listserv, in particolare @ brad-king.

Il problema principale è che non sto compilando correttamente il mio oggetto condiviso nel mio progetto esterno. La risposta di Brad alla mia domanda:

Grazie per l'esempio completo/semplice. Il problema è che il file libExtLib.so creato dal progetto esterno non ha DT_SONAME impostato dal linker. Quando a un linker viene assegnato un percorso in un file di libreria condivisa privo di soname, il percorso viene copiato nel campo DT_NEEDED del consumer poiché esso non ha un soname da utilizzare per questo .

ci sono due soluzioni:

  1. Accertarsi DT_SONAME viene impostato in modo corretto il sistema di compilazione esterno.

  2. Dillo CMake che il file di libreria importata non ha soname:

    set_property (TARGET EXTLIB PROPRIETA IMPORTED_NO_SONAME 1)

    CMake sarà poi collegarlo tramite -lExtLib e il linker non negozio il percorso il file in DT_NEEDED ma solo il nome del file.

Uno di questi dovrebbe risolvere il problema. Il numero 1 è più pulito.

Dal momento che ho il controllo dei file effettuate nella libreria esterna, ho optato per la prima soluzione detergente compilando l'oggetto condiviso in questo modo:

$(SHARED_TARGET): $(OBJECTS) $(CXX) $(CXXFLAGS) $(OBJECTS) -o [email protected] $(LDFLAGS) -Wl,-soname,[email protected]

ho rivisto il mio esempio originale e reso molto più semplice: https://github.com/calebwherry/cmake-SO-question-main. Lo lascerò come riferimento per chiunque inciampi in questo post in un secondo momento.

P.S.

C'è un'altra correzione che non è ottimale. Se non avessi fatto nulla di quanto sopra, avrei potuto dare a target_link_library il percorso completo della libreria su cui stavo collegando e non ho usato la destinazione della libreria importata. Ho notato questo nel file CMake nel repository e l'ho commentato. Non è una grande soluzione, ma risolve il problema in un altro modo.

Problemi correlati