Frage

In meinem Projekt gibt es eine Abhängigkeit von einer statischen Bibliothek (nur genannt libsomething von jetzt an) von einer dritten Partei. Vor kurzem libsomething hat in einer anderen Version verfügbar ist. Meine Aufgabe ist es, meine Software mit Unterstützung für die alte und die neue Version zur Verfügung zu stellen. Nur eine Version von libsomething wird zur Laufzeit zu einem bestimmten Zeitpunkt verwendet, aber welche Version sollte dies zwischen Programm läuft sein konfigurierbar ist.

Ich bin mit MSVC2005 auf WinXP, ein sekundäres Ziel ist vorbereitet zu werden, um Linux und GCC zu wechseln.

Da beide Versionen von libsomething sind die gleichen Symbole verwendet, welches sie verbinden beide in meine ausführbaren Datei ist nicht in Frage, da die Symbole beiden Versionen werden alle auf Link-Zeit über kollidieren.

Während ich zwei ausführbare Dateien erstellen könnte (eine Verknüpfung mit der alten Version, die andere die neue Version verwendet wird), kann ich keine Entscheidung implementieren, auf dem ausführbaren Datei in der letzten Implementierungsumgebung zu nennen (legacy Gründe).

kam ich auf die Idee, eine dynamische Bibliothek Wrapper für jede Version von libsomething zu schaffen und deren Verknüpfung zur Laufzeit abhängig von einigen Konfigurationsdatei. Mit MSCV, würde dies bedeuten, die Straße hinunter ging der Verwendung LoadLibrary(), GetProcAddress() usw., während auf Linux ich Gebrauch dlopen() und dlsym() hat.

Ich verstehe, dass libtool mit (das heißt libtldl) wickelt diese Plattform-Abhängigkeit für gemeinsam genutzte Bibliotheken. Ist dies ein geeigneter Weg zu folgen? Gibt es bessere (oder zumindest verschiedene) Arten? Haben Alternativen für libtldl exist als Open-Source?

War es hilfreich?

Lösung

Es ist nun einige Jahre her, aber ich möchte eine andere Lösung für Vollständigkeit erwähnen. Anstelle des manuellen dlopen und dlsym könnten Sie einfache Stubs für alle notwendigen Funktionen erzeugen und auf den ersten Anruf (oder beim Programmstart) entscheiden, welche Version der Bibliothek benötigt wird, wird sie und die Adressen auflösen.

Sie können ein Skript speziell für Ihr Projekt zugeschnitten schreiben oder verwenden Sie Implib.so -Tool:

# This will generate mylib.so.init.c and mylib.so.tramp.S
# which implement stubs. These need to be linked to your
# executable.
$ implib-gen.py mylib.so

Implib.so ist Linux-only atm sollte aber auf Windows leicht anpassbar sein.

Andere Tipps

Ich weiß, Sie sagen, Sie nicht zwei ausführbare Dateien aufgrund der Entscheidung, welche ausführen verwenden konnten, konnten aber nicht Sie exec hin und her zwischen ausführbaren Dateien je nachdem, welcher Version bei der Konfiguration ausgewählt wird?

Unter Linux wäre es einfacher für Sie, um eine Verknüpfung zu gemeinsam genutzten Bibliothek und Verwendung Symlinks auf korrekte Version -. IMO ist es viel einfacher als die Verwendung von dlopen() + dlsym()

So würden Sie die alten und neuen Versionen Ihrer Bibliothek gemeinsam genutzten Bibliotheken für erstellen:

g++ -shared -o libshared.so.1.1 -Wl,-soname=libshared.so.1 -L. -Wl,--whole-archive libstatic.a.old -Wl,-no-whole-archive

und

g++ -shared -o libshared.so.1.2 -Wl,-soname=libshared.so.1 -L. -Wl,--whole-archive libstatic.a.new -Wl,-no-whole-archive

Erstellen

die Symlinks:

ln -s libshared.so.1.1 libshared.so.1
ln -s libshared.so.1 libshared.so

Erstellen Sie Ihre Anwendung, um es in der alten Version der Bibliothek zu verknüpfen. Ich nehme beide Versionen sind binärkompatibel (ABI nicht gebrochen), aber die neue man konnte einige neue Symbole haben.

g++ -o myapp myapp.cpp -L. -lshared

Da die gemeinsame Bibliothek SONAME ist libshared.so.1 Ihre Anwendung auf sie abhängen und libshared.so.1 in Pfaden von /etc/ld.so.conf oder LD_LIBRARY_PATH

suchen

Bevor Sie Ihre Anwendung ausführen können Sie den libshared.so.1 Symlink Punkt auf libshared.so.1.2 oder libshared.so.1.1 gesetzt.


Wenig Informationen über die Linker-Optionen verwendeten hier:

  

- Ganz Archiv
             Für jedes Archiv in der Befehlszeile nach der --whole-Archiv Option erwähnt, umfasst jede Objektdatei im Archiv in der              Link, anstatt das Archiv für die erforderlichen Objektdateien zu suchen. Dies wird normalerweise verwendet, um eine Archivdatei in einen gemeinsam genutzten drehen              Bibliothek und zwingt jedes Objekt werden in der resultierenden gemeinsam genutzten Bibliothek enthalten. Diese Option kann mehrfach verwendet werden.   
             Zwei Anmerkungen, wenn Sie diese Option aus gcc: Erstens, gcc weiß nicht, über diese Option, so dass Sie verwenden müssen -Wl, -ganz-Archiv.              Zweitens, nicht vergessen -Wl zu verwenden, -NO-ganze-Archiv nach der Liste der Archive, weil gcc seine eigene Liste von Archiven hinzufügen, wird Ihre              Link und Sie können nicht wollen, dass diese Flagge diese ebenfalls beeinflussen.

     

-soname = name
             Beim Erstellen eines ELF Objekt geteilt wird, setzen die interne DT_SONAME Feld zu dem angegebenen Namen. Wenn eine ausführbare Datei mit einem verknüpften              gemeinsames Objekt, das eine DT_SONAME Feld hat, dann, wenn die ausführbare betrieben, um den dynamischen Linker versuchen wird, das gemeinsame Objekt zu laden,              durch das DT_SONAME Feld angegeben, anstatt der Verwendung des Dateinamens an den Linker gegeben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top