Pregunta

¿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?

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

¿Fue útil?

Solución

Tal vez podría crear una cadena con la versión como esta:

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

y para poder verificarlo desde el shell simplemente use:

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

Otros consejos

Además de proporcionar una cadena estática como mencionó Puppe, es una práctica común proporcionar una macro para recuperar la verificación de la versión para verificar la compatibilidad. Por ejemplo, podría tener las siguientes macros (declaradas en un archivo de encabezado para usar 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))

Observe con la macro MYLIB_CHECK_VERSION , supongo que desea una rev mayor específica y una rev menor menor o mayor que la versión deseada. Cambie según sea necesario para su aplicación.

Luego utilícelo desde una aplicación de llamada, algo 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 provenga del archivo de encabezado incluido. Además, se optimizará en tiempo de compilación para la aplicación que realiza la llamada. Con un poco más de trabajo, puede extraerlo de la biblioteca misma. Sigue leyendo ...

También puede usar esta información para crear una cadena estática almacenada dentro de su biblioteca, como lo menciona Puppe. Coloque 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. Puede usar esto para realizar verificaciones adicionales creando funciones dentro de su biblioteca y accediendo a ellas desde una aplicación de llamada, etc.

Creando una nueva respuesta basada en tu edición ... solo para evitar confusiones :)

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

Tal vez podría tocar un archivo llamado versión_1.2.3 y agregarlo al archivo. Luego, puede determinar la versión buscando el archivo de versión con el comando ar:

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

No estoy seguro de si eso le dará lo que necesita, pero no existe un método estándar para insertar metadatos como este en un archivo. Quizás encuentre otra información que desee almacenar en este '' metarchivo '' para el archivo.

Varias veces se ha mencionado 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 revisión), pero también podría estar disponible si está utilizando CVS (Sistema de versiones concurrentes) o Subversion.

Lo usarías así (clonado desde la página de manual):

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

y f.c se compila en f.o, entonces el comando

   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 $

generará

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

Si su f.o se agregó a una biblioteca estática f.a , entonces ident f.a debería mostrar una salida similar. Si tiene varios [az] .o de construcción 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 su archivo de programa. A menos que el programa los haga referencia, el vinculador no ve la necesidad de 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 es un símbolo obligatorio sin hacer referencia a él, pero depende del vinculador y está más allá del alcance de esta respuesta.

Si, en cambio, está familiarizado con el SCCS (Sistema de control de código fuente), entonces usaría man 1 what , y se vería así (hecho con macros para mostrar la flexibilidad disponible):

what f.c f.o

y f.c se compila en f.o, entonces el comando

   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

generará

<*>

PS: tanto ident como what son comandos que vienen con sistemas de control de fuente centralizados específicos. Si está utilizando un sistema de control de fuente distribuido (como git), el concepto completo puede no tener sentido. Para algunas ideas usando git vea este hilo: Pasando de CVS a git: $ Id: $ equivalente? aunque el hash no es lo mismo que un número de versión. :)

Si está usando gcc, puede usar la directiva #ident

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

Para obtener la versión solo use 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 u omitirla completamente pasando -fno-ident (Esto también omitirá los comentarios de la versión del compilador de los objetos compilados)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top