Domanda

Nel mio progetto c'è una dipendenza da una libreria statica (appena chiamato libsomething d'ora in poi) da un 3rd party. Recentemente, libsomething è diventato disponibile in un'altra versione. Il mio compito è quello di fornire il mio software con il supporto per la vecchia e la nuova versione. viene utilizzata solo una versione di libsomething a run-time in un dato momento, ma quale versione si tratta dovrebbe essere configurabile tra programma viene eseguito.

Sto usando MSVC2005 su WinXP, un obiettivo secondario è quello di diventare pronti a passare a Linux e GCC.

Dal momento che entrambe le versioni di libsomething stanno usando gli stessi simboli, che collega tutti e due nella mia eseguibile è fuori discussione, come i simboli di entrambe le versioni stanno andando a scontrarsi in tutto al link-tempo.

Mentre ho potuto creare due file eseguibili (uno che collegano contro la vecchia versione, l'altra con la nuova versione), non posso implementare una decisione su quale eseguibile per chiamare in ambiente di distribuzione finale (motivi di eredità).

mi è venuta l'idea di creare un wrapper libreria dinamica per ogni versione di libsomething e il loro collegamento in fase di esecuzione in base su alcuni file di configurazione. Con MSCV, questo significherebbe andare giù per la strada di usare LoadLibrary(), GetProcAddress(), ecc, mentre su Linux avrei dovuto all'uso dlopen() e dlsym().

capisco che usando libtool (vale a dire, libtldl) è avvolgente questa piattaforma dipendenza per l'utilizzo di librerie condivise. Si tratta di un percorso appropriato da seguire? ci sono meglio (o, almeno, diversi modi)? Fare alternative per libtldl esistiamo come open-source?

È stato utile?

Soluzione

E 'stato alcuni anni, ma mi piacerebbe parlare di un'altra soluzione per completezza. Invece di dlopen manuale e dlsym si potrebbe generare stub semplici per tutte le funzioni necessarie e in prima convocazione (o all'avvio del programma) decidere quale versione della libreria è necessario, caricarlo e risolvere gli indirizzi.

Si potrebbe scrivere uno script specificamente pensati per il vostro progetto o utilizzare Implib.so strumento:

# 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 è solo Linux atm ma dovrebbe essere facilmente adattabile a Windows.

Altri suggerimenti

So che hai detto che non è possibile utilizzare due file eseguibili a causa della decisione di cui si desidera eseguire, ma non si potrebbe exec avanti e indietro tra gli eseguibili a seconda di quale viene selezionata la versione a configurazione?

In Linux sarebbe più facile per voi di link alla biblioteca e uso comune collegamenti simbolici alla versione corretta -. IMO è molto più facile che usare dlopen() + dlsym()

librerie modo si creerebbe in comune per le vecchie e nuove versioni della libreria:

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

e

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

Crea i link simbolici:

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

Costruisci la tua applicazione, che lo collega alla vecchia versione della libreria. Suppongo che entrambe le versioni sono compatibili a livello binario (ABI non rotto), ma il nuovo si potrebbe avere alcuni nuovi simboli.

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

Dal SONAME della libreria condivisa è libshared.so.1 l'applicazione dipenderà su di esso e cercherà libshared.so.1 nei percorsi da /etc/ld.so.conf o LD_LIBRARY_PATH

Prima di eseguire l'applicazione è possibile impostare il collegamento simbolico libshared.so.1 al punto da libshared.so.1.2 o libshared.so.1.1.


Poco informazioni sulle opzioni di linker usato qui:

  

- intero archivio
             Per ogni archivio menzionato sulla riga di comando dopo l'opzione --whole-archivio, includere ogni file oggetto nell'archivio nella              collegamento, piuttosto che cercare l'archivio per i file oggetto necessari. Questo è normalmente usato per trasformare un file di archivio in una condivisa              biblioteca, costringendo ogni oggetto da inserire nella libreria condivisa risultante. Questa opzione può essere utilizzata più di una volta.   
             Due note quando si utilizza questa opzione dal gcc: In primo luogo, GCC non sapere di questa opzione, quindi bisogna usare -Wl, -Tutto-archivio.              In secondo luogo, non dimenticare di usare -Wl, -no-tutta-archivio dopo l'elenco degli archivi, perché gcc aggiungerà una propria lista degli archivi al vostro              link e potrebbe non voler questo flag di influenzare quelli pure.

     

-soname = nome
             Quando si crea un oggetto ELF condivise, impostare il campo DT_SONAME interna al nome specificato. Quando un file eseguibile è collegato con una              oggetto condiviso cui campo DT_SONAME, allora quando l'eseguibile viene eseguito il linker dinamico tenterà di caricare l'oggetto condiviso              specificato dal campo DT_SONAME piuttosto che il nome del file utilizzando il dato al linker.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top