2014-12-02 7 views
5

Problem: Ich baue ein externes Projekt in CMake. Das Projekt verfügt über ein Makefile, das letztendlich ein gemeinsames Objekt erzeugt. Ich möchte dieses Objekt in meinem Superprojekt verlinken und installieren, als wäre es eine der Bibliotheken im Projekt. Das Problem besteht darin, dass die ExternalProject-Bibliothek in meinen Anwendungen und Bibliotheken mit einem relativen Pfad verknüpft wird, nicht mit einem absoluten Pfad, der Probleme verursacht, wenn ich von einem beliebigen Verzeichnis aus neben dem Ort ausführe, an dem CMake es absetzt.CMake: Verknüpftes C++ - Objekt von ExternalProject erzeugt Binärdateien mit relativem Pfad, nicht absolut

Ich habe created a sample SSCCE example project, um meine gesamte Einrichtung zu demonstrieren. Fühlen Sie sich frei zu lesen und zu kompilieren, wenn nötig (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).

Immer, wenn ich ldd auf die ausführbare Datei und Libs laufen, bekomme ich folgende Ausgabe:

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) 

ich alle möglichen Dinge versucht haben, mit RPATHS zu tun, aber nicht die extlib bekommen Recht zu verknüpfen. Die lib, die lokal für das Projekt ist (libTestLib.so) Links gut.

Ich habe auch versucht, die LD_LIBRARY_PATH den relativen Pfad zu überschreiben, wenn ich die App ausführen, aber selbst wenn ich das tue, findet es immer noch nicht die Bibliothek. Ich nehme an, weil es relativ ist, folgt es nicht der normalen Verknüpfungsreihenfolge? Das Ergebnis ist, dass die Binärdatei nicht ausgeführt wird, wenn ich nicht in dem Verzeichnis bin, in dem sie sich befindet.

Ich habe das Gefühl, dass ich etwas wirklich Dummes mache, wenn ich Abhängigkeiten mit dem ExternalProject erzeuge, und das ist mein Problem, aber ich habe meinen Kopf drei Tage lang geschlagen und mir nichts einfallen lassen.

Systemeinrichtung: Debian Wheezy 64-Bit, CMake 3.0.2, g ++ - 4.9.2.

+0

Noch keine Treffer, nicht wahr? Whelp, ich habe das Problem vorübergehend "behoben", indem ich das externe Projekt auch eine statische lib erstellen lasse und diese anstelle der gemeinsamen lib verlinke. Keine langfristige Lösung, aber zumindest eine, die das richtig macht. Ich habe das Repo aktualisiert, um diese Option für andere zu haben, aber Sie müssen es manuell in ext/CMakeLists.txt ändern, um es zu aktivieren. – Caleb

+0

Entschuldigung, habe die Antwort nicht bemerkt – Slava

Antwort

1

Es dauerte eine Weile, aber ich bin endlich bei einer Antwort mit Hilfe des CMake Users Listserv angekommen, speziell @ brad-king.

Das Hauptproblem ist, dass ich mein freigegebenes Objekt nicht korrekt in meinem externen Projekt kompiliere. Brads Antwort auf meine Frage:

Danke für das komplette/einfache Beispiel. Das Problem ist, dass die libExtLib.so-Datei, die von dem externen Projekt erstellt wird, nicht über DT_SONAME verfügt, das von dem Linker festgelegt wird. Wenn ein Linker einen Pfad zu einer freigegebenen Bibliotheksdatei ohne Soname erhält, wird der Pfad in das DT_NEEDED Feld des Consumers kopiert, da kein Soname dafür verwendet werden kann.

Es gibt zwei Lösungen:

  1. Stellen Sie sicher, DT_SONAME wird durch das externe Build-System richtig eingestellt.

  2. CMake Sagen Sie, dass die importierte Bibliotheksdatei keine soname hat:

    set_property (TARGET extlib PROPERTY IMPORTED_NO_SONAME 1)

    CMake wird dann verbinden sie über -lExtLib und der Linker nicht speichern den Pfad zu die Datei in DT_NEEDED, aber nur den Dateinamen.

Eines dieser Probleme sollte das Problem beheben. Nummer 1 ist sauberer.

Da ich die Kontrolle über die Make-Dateien in der externen Bibliothek, ich für den Reiniger ersten Lösung entschieden durch das gemeinsame Objekt kompiliert wie folgt:

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

Ich habe mein ursprüngliches Beispiel überarbeitet und machte es viel einfacher: https://github.com/calebwherry/cmake-SO-question-main. Ich werde es als Referenz für jemanden zurücklassen, der zu einem späteren Zeitpunkt über diesen Posten stolpert.

P.S.

Es gibt einen anderen Fix, der suboptimal ist. Wenn ich nichts von dem oben genannten getan hätte, hätte ich target_link_library den vollständigen Pfad zu der Bibliothek geben können, mit der ich verlinkt habe, und nicht das importierte Bibliotheksziel verwendet. Ich habe dies in der CMake-Datei im Repo notiert und kommentiert. Keine gute Lösung, aber löst das Problem auf andere Weise.

Verwandte Themen