2009-10-28 19 views
7

Come posso memorizzare un numero di versione in una libreria statica (file.a) e successivamente verificare la sua versione in Linux?Come memorizzare un numero di versione in una libreria statica?

P.S. Ho bisogno della possibilità di controllare la versione del file in qualsiasi momento senza alcun eseguibile speciale usando solo le utilità della shell.

+0

Le soluzioni seguenti (due come scrivo) sono entrambe disponibili anche per le librerie condivise, ovviamente. –

+0

Appena aggiunta un'altra risposta in base alla modifica ... Spero che ti sia d'aiuto. – jheddings

risposta

8

Forse si potrebbe creare una stringa con la versione in questo modo:

char* library_version = { "Version: 1.3.6" }; 

e di essere in grado di controllare dalla shell basta usare:

strings library.a | grep Version | cut -d " " -f 2 
+0

Dovresti, ovviamente, eseguire 'const char library_version [] =" 1.3.6 ";' per salvare lo spazio per il puntatore. E dichiareresti la variabile nell'intestazione della libreria (o in un'intestazione distribuita con la libreria). –

+0

per favore ricontrolla la mia domanda - è stata aggiornata – Pirks

+1

Informazioni aggiunte per verificare la versione da una shell – Puppe

8

Oltre a fornire una stringa statica come accennato da Puppe, è prassi comune fornire una macro per recuperare la verifica della versione per la compatibilità. Ad esempio, si potrebbe avere le seguenti macro (dichiarati in un file di intestazione per essere utilizzato con la libreria):

#define MYLIB_MAJOR_VERSION 1 
#define MYLIB_MINOR_VERSION 2 
#define MYLIB_REVISION 3 
#define MYLIB_VERSION "1.2.3" 
#define MYLIB_VERSION_CHECK(maj, min) ((maj==MYLIB_MAJOR_VERSION) && (min<=MYLIB_MINOR_VERSION)) 

avviso con il MYLIB_CHECK_VERSION macro, sto supponendo che si desidera una specifica importante giro e un giro minore maggiore o uguale alla versione desiderata. Cambia come richiesto per la tua applicazione.

Quindi utilizzare da un'applicazione chiamata, qualcosa di simile a:

if (! MYLIB_VERSION_CHECK(1, 2)) { 
    fprintf(stderr, "ERROR: incompatible library version\n"); 
    exit(-1); 
} 

Questo approccio farà sì che le informazioni sulla versione di venire dal file di intestazione incluso. Inoltre, sarà ottimizzato in fase di compilazione per l'applicazione chiamante. Con un po 'di lavoro in più, puoi estrarlo dalla libreria stessa. Continua a leggere ...

È inoltre possibile utilizzare queste informazioni per creare una stringa statica memorizzata all'interno della libreria, come indicato da Puppe. Mettere qualcosa di simile all'interno della vostra libreria:

struct { 
    const char* string; 
    const unsigned major; 
    const unsigned minor; 
    const unsigned revision; 
} mylib_version = { 
    MYLIB_VERSION, MYLIB_MAJOR_VERSION, MYLIB_MINOR_VERSION, MYLIB_REVISION 
}; 

Questo creerà una struttura chiamata mylib_version nella libreria. È possibile utilizzare questo per fare ulteriori verifiche con la creazione di funzioni all'interno della vostra biblioteca e l'accesso a coloro che da un'applicazione chiamata, ecc

+1

L'unico problema con MYLIB_VERSION_CHECK che vedo è che viene valutato in fase di compilazione, e un buon ottimizzatore rimuoverà il controllo se tutto è OK, e chiamerà incondizionatamente printf() - volevi dire fprintf (stderr, ...), non è vero? - ed esce(). Penso che sarebbe meglio chiamare una funzione che incorpori la logica piuttosto che usare un'espressione costante. –

+0

Sì, buoni punti qui ... In seguito ho modificato il mio post per includere l'incorporazione delle informazioni nella libreria per questo motivo. Grazie per il chiarimento. – jheddings

+0

si prega di ricontrollare la mia domanda - è stato aggiornato – Pirks

3

Creazione di una nuova risposta, sulla base di edit ... Proprio per evitare confusione :)

Se stai cercando un modo non di codice per risolvere il problema, potresti provare questo. È (ancora una volta) un'alternativa all'approccio strings definito da Puppe.

Forse potresti semplicemente toccare un file chiamato version_1.2.3 e aggiungerlo all'archivio. Quindi, si potrebbe determinare la versione, cercando per il file versione utilizzando il comando ar:

ar t libmylib.a | grep 'version_' | sed -e 's/^version_//' 

Non sono sicuro se questo ti porterà quello che ti serve, ma non esiste un metodo standard per incorporare i metadati come questo in un archivio. Forse troverai altre informazioni che vuoi memorizzare in questo "metafile" per l'archivio.

+0

Che ne dici di ** 'man 1 ident' **? –

+0

Questo metodo non è adatto per il controllo della versione. –

+0

@ vitaly.v.ch Non disponibile su tutto tranne linyux. – MarcusJ

0

È stato menzionato più volte man 1 ident, quindi ecco i dettagli sull'utilizzo di tale metodo.

ident è un comando fornito con RCS (Revision Control System), ma potrebbe anche essere disponibile se si utilizza CVS (Concurrent Versions System) o Subversion.

Si potrebbe usare in questo modo (clonato dalla pagina man):

#include <stdio.h> 
static char const rcsid[] = 
    "$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $"; 
int main() { return printf("%s\n", rcsid) == EOF; } 

e FC è compilato in fo, quindi il comando

ident f.c f.o 

uscita volontà

f.c: 
     $Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $ 
    f.o: 
     $Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $ 

Se il tuo f.o è stato aggiunto a una libreria statica f.a quindi ident f.a dovrebbe mostrare un output simile. Se nel tuo az.a si sono creati diversi modelli simili [a-z].o, è necessario trovare tutte le loro stringhe nel file az.a.

CAVEAT: Solo perché sono nel file .a non significa che saranno inclusi nel file di programma. A meno che il programma non li faccia riferimento, il linker non vede la necessità di includerli. Quindi di solito devi avere un metodo in ogni modulo per restituire la stringa, e l'app deve chiamare quel metodo. Ci sono modi per convincere la maggior parte dei linker che si tratta di un simbolo richiesto senza effettivamente farvi riferimento, ma dipende dal linker ed è oltre lo scopo di questa risposta.

Se invece si ha familiarità con il CSSC (Fonte Control System Code) allora si sarebbe usare man 1 what invece, e sarebbe simile a questa (fatto con le macro per mostrare la flessibilità disponibile):

#include <stdio.h> 
#define VERSION_STR "5.4" 
#define CONFIG "EXP" 
#define AUTHOR "eggert" 
static char const sccsid[] = 
    "@(#) " CONFIG " v " VERSION_STR " " __DATE__ " " __TIME__ " " AUTHOR; 
int main() { return printf("%s\n", sccsid) == EOF; } 

e fc è compilato in fo, allora il comando

what f.c f.o 

stamperà

f.c: 
     @(#) EXP v 5.4 1993/11/09 17:40:15 eggert 
    f.o: 
     @(#) EXP v 5.4 1993/11/09 17:40:15 eggert 

PS: sia ident che what sono comandi forniti con specifici sistemi di controllo centralizzato della sorgente. Se si utilizza un sistema di controllo del codice sorgente distribuito (come git), l'intero concetto potrebbe non avere senso. Per alcune idee che utilizzano git vedi questa discussione: Moving from CVS to git: $Id:$ equivalent? sebbene l'hash non sia lo stesso di un numero di versione. :)

0

Se si utilizza gcc, è possibile utilizzare la direttiva #ident

#ident "Foo Version 1.2.3.4" 
void foo(void){ /* foo code here */ } 

Per ottenere la versione basta usare uno dei seguenti:

strings -a foo.o | grep "Foo Version" 
strings -a foo.a | grep "Foo Version" 
strings -a foo.so | grep "Foo Version" 

Questo vi permetterà di compilare la versione nella libreria con la possibilità di estrarla in seguito utilizzando strip -R .comment your_file o ometterla completamente passando -fno-ident (Ciò ometterà anche i commenti della versione del compilatore dagli oggetti compilati)

Problemi correlati