2009-10-28 10 views
7

¿Cómo puedo almacenar un número de versión en una biblioteca estática (archivo.a) y luego verificar su versión en Linux?¿Cómo almacenar un número de versión en una biblioteca estática?

P.S. Necesito la posibilidad de verificar la versión del archivo en cualquier momento sin ningún archivo ejecutable especial utilizando solo utilidades de shell.

+0

Las soluciones a continuación (dos mientras escribo) están disponibles para bibliotecas compartidas también, por supuesto. –

+0

Acabo de agregar otra respuesta en función de su edición ... Espero que ayude. – jheddings

Respuesta

8

Tal vez usted podría crear una cadena con la versión de la siguiente manera:

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

y para poder comprobar desde el shell sólo tiene que utilizar:

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

Usted, por supuesto, haría que 'const char library_version [] =" 1.3.6 ";' para guardar el espacio para el puntero. Y declararía la variable en el encabezado de la biblioteca (o en un encabezado distribuido con la biblioteca). –

+0

vuelva a verificar mi pregunta - se actualizó – Pirks

+1

Se agregó información para verificar la versión de un shell – Puppe

8

Además de proporcionar una cadena estática como lo menciona Puppe, es una práctica común proporcionar una macro para recuperar la versión de verificación de compatibilidad. Por ejemplo, usted podría tener las siguientes macros (declaradas en un archivo de cabecera para ser usado con su biblioteca):

#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)) 

de aviso con el MYLIB_CHECK_VERSION macro, estoy asumiendo que usted quiere un rev importante específico y un rev menor mayor o igual a su versión deseada. Cambie según sea necesario para su aplicación.

Entonces usarlo desde una aplicación que llama, algo así como:

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

Este enfoque hará que la información de la versión para venir desde el archivo de cabecera incluida. Además, se optimizará en tiempo de compilación para la aplicación de llamada. Con un poco más de trabajo, puede extraerlo de la biblioteca. Siga leyendo ...

También puede usar esta información para crear una cadena estática almacenada dentro de su biblioteca, como lo menciona Puppe. Colocar algo como esto dentro de su biblioteca:

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 
}; 

Esto creará una estructura llamada mylib_version en su biblioteca. Usted puede usar esto para hacer comprobaciones adicionales mediante la creación de funciones dentro de su biblioteca y acceder a los de una aplicación de llamada, etc.

+1

El único problema con MYLIB_VERSION_CHECK que veo es que se evalúa en tiempo de compilación, y un buen optimizador eliminará la comprobación si todo está bien, y llamará incondicionalmente a printf() - quiso decir fprintf (stderr, ...), ¿verdad? - y salir(). Creo que sería mejor llamar a una función que incorpore la lógica en lugar de usar una expresión constante. –

+0

Sí, buenos puntos aquí ... Más tarde edité mi publicación para incluir la incrustación de la información en la biblioteca por este motivo. Gracias por la aclaración. – jheddings

+0

vuelva a verificar mi pregunta - se ha actualizado – Pirks

3

Creación de una nueva respuesta en función de su edición ... Sólo para evitar confusiones :)

Si Si está buscando una forma que no sea de código para resolver el problema, puede intentarlo. Es (una vez más) una alternativa al enfoque strings definido por Puppe.

Quizás podría simplemente tocar un archivo llamado version_1.2.3 y agregarlo al archivo. A continuación, se puede determinar la versión de buscar el archivo de la versión con el comando ar:

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

No estoy seguro de si eso va a conseguir lo que necesita, pero no existe un método estándar para incrustar metadatos como esto en un archivo. Quizás encuentre otra información que desee almacenar en este "metarchivo" para el archivo.

+0

¿Qué tal ** 'man 1 ident' **? –

+0

Este método no es bueno para el control de versiones. –

+0

@ vitaly.v.ch No disponible en cualquier cosa que no sea linyux. – MarcusJ

0

Se ha mencionado varias veces man 1 ident, así que aquí hay detalles sobre el uso de ese método.

ident es un comando que viene con el RCS (Sistema de control de revisiones), pero también podría estar disponible si está utilizando CVS (sistema de versiones simultáneas) o Subversion.

Se podría utilizar de esta manera (clonado a partir de la página del manual):

#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; } 

y FC se compila en fo, entonces el comando

ident f.c f.o 

es la salida

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 $ 

Si su f.o se agregaron a una biblioteca estática f.a entonces ident f.a debe mostrar un resultado similar. Si tiene varios [a-z].o construidos de forma similar en su az.a, debe encontrar todas sus cadenas en el archivo az.a.

CAVEAT: El hecho de que estén en el archivo .a no significa que se incluirán en el archivo de programa. A menos que el programa los haga referencia, el vinculador no necesita incluirlos. Por lo tanto, generalmente debe tener un método en cada módulo para devolver la cadena, y la aplicación debe llamar a ese método. Hay formas de convencer a la mayoría de los vinculadores de que se trata de un símbolo obligatorio sin hacer referencia a él, pero depende del vinculador y está fuera del alcance de esta respuesta.

En cambio, si está familiarizado con el (sistema de control de código fuente) CCSC, entonces sería utilizar man 1 what su lugar, y que sería el siguiente (hecho con macros para mostrar la flexibilidad disponible):

#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; } 

y fc se compila en fo, entonces el comando

what f.c f.o 

es la salida

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: ambos ident y what son comandos que vienen con sistemas de control de fuente centralizados específicos. Si está utilizando un sistema de control de fuente distribuida (como git), el concepto completo puede no tener sentido. Para algunas ideas usando git, vea este hilo: Moving from CVS to git: $Id:$ equivalent? aunque el hash no es lo mismo que un número de versión. :)

0

Si está utilizando gcc, se puede utilizar la directiva #ident

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

Para obtener la versión sólo tiene que utilizar uno de los siguientes:

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

Esto le permitirá compilar la versión en la biblioteca con la capacidad de eliminarla posteriormente usando strip -R .comment your_file o omitirla por completo pasando -fno-ident (Esto también omitirá los comentarios de la versión del compilador de los objetos compilados)

Cuestiones relacionadas