2009-10-28 7 views
7

Comment puis-je stocker un numéro de version dans une bibliothèque statique (fichier.a) et vérifier plus tard sa version sous Linux?Comment stocker un numéro de version dans une bibliothèque statique?

P.S. J'ai besoin de la possibilité de vérifier la version du fichier à tout moment sans aucun exécutable spécial en utilisant uniquement les utilitaires shell.

+0

Les solutions ci-dessous (deux que j'écris) sont également disponibles pour les bibliothèques partagées, bien sûr. –

+0

Juste ajouté une autre réponse en fonction de votre montage ... J'espère que cela aide. – jheddings

Répondre

8

Peut-être que vous pouvez créer une chaîne avec la version comme ceci:

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

et d'être en mesure de le vérifier à partir du shell utilisez simplement:

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

Vous feriez, bien sûr, que 'const char library_version [] =" 1.3.6 ";' pour sauvegarder l'espace pour le pointeur. Et vous déclareriez la variable dans l'en-tête de la bibliothèque (ou dans un en-tête distribué avec la bibliothèque). –

+0

s'il vous plaît revérifier ma question - il a été mis à jour – Pirks

+1

Informations supplémentaires pour vérifier la version à partir d'un shell – Puppe

8

En plus de fournir une chaîne statique Comme mentionné par Puppe, il est de pratique courante de fournir une macro pour récupérer la compatibilité de la version. Par exemple, vous pouvez avoir les macros suivantes (déclarées dans un fichier d'en-tête à utiliser avec votre bibliothèque):

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

Avis avec le MYLIB_CHECK_VERSION macro, je suppose que vous voulez un rev majeur spécifique et un rev mineur supérieur ou égal à la version souhaitée. Changez comme requis pour votre application.

utiliser Ensuite, à partir d'une application qui appelle, quelque chose comme:

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

Cette approche entraînera les informations de version à venir du fichier d'en-tête inclus. De plus, il sera optimisé au moment de la compilation pour l'application appelante. Avec un peu plus de travail, vous pouvez l'extraire de la bibliothèque elle-même. Lire la suite ...

Vous pouvez également utiliser cette information pour créer une chaîne statique stockée dans votre bibliothèque, comme mentionné par Puppe. Placez quelque chose comme ça dans votre bibliothèque:

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

Cela va créer un struct appelé mylib_version dans votre bibliothèque. Vous pouvez l'utiliser pour faire des vérifications supplémentaires en créant des fonctions à l'intérieur de votre bibliothèque et l'accès à ceux d'une application appelant, etc.

+1

Le seul problème avec le MYLIB_VERSION_CHECK que je vois est qu'il est évalué au moment de la compilation, et un bon optimiseur supprimera la vérification si tout est OK, et appellera inconditionnellement printf() - vous vouliez dire fprintf (stderr, ...), n'est-ce pas? - et exit(). Je pense qu'il serait préférable d'appeler une fonction qui intègre la logique plutôt que d'utiliser une expression constante. –

+0

Ouais, de bons points ici ... J'ai plus tard édité mon message pour inclure l'intégration de l'information dans la bibliothèque pour cette raison. Merci pour la clarification. – jheddings

+0

s'il vous plaît revérifier ma question - il a été mis à jour – Pirks

3

Création d'une nouvelle réponse en fonction de votre édition ... Juste pour éviter toute confusion :)

Si vous cherchez un moyen non-code pour résoudre le problème, vous pouvez essayer cela. C'est (encore une fois) une alternative à l'approche strings définie par Puppe.

Peut-être que vous pourriez simplement toucher un fichier appelé version_1.2.3 et l'ajouter à l'archive. Ensuite, vous pouvez déterminer la version en recherchant le fichier de version en utilisant la commande ar:

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

Je ne suis pas sûr que vous obtiendrez ce dont vous avez besoin, mais il n'y a pas de méthode standard pour l'incorporation des métadonnées comme celui-ci dans une archive. Peut-être trouverez-vous d'autres informations que vous souhaitez stocker dans ce "métafichier" pour l'archive.

+0

Que diriez-vous de ** 'man 1 ident' **? –

+0

Cette méthode n'est pas bonne pour le contrôle de version. –

+0

@ vitaly.v.ch Non disponible sur autre chose que linyux. – MarcusJ

0

Plusieurs fois, man 1 ident a été mentionné, donc voici des détails sur l'utilisation de cette méthode.

ident est une commande fournie avec RCS (Revision Control System), mais peut également être disponible si vous utilisez CVS (Concurrent Versions System) ou Subversion.

Vous l'utiliser comme ceci (cloné à partir de la page de manuel):

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

et fc est compilé dans fo, la commande

ident f.c f.o 

volonté sortie

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 votre f.o a été ajouté à une bibliothèque statique f.a puis ident f.a devrait afficher une sortie similaire. Si vous avez plusieurs [a-z].o de construction similaire dans votre az.a vous devriez trouver toutes leurs chaînes dans le fichier az.a. CAVEAT: Ce n'est pas parce qu'ils se trouvent dans le fichier .a qu'ils seront inclus dans votre fichier de programme. À moins que le programme ne les référence, l'éditeur de liens ne voit aucun besoin de les inclure. Vous devez donc généralement avoir une méthode dans chaque module pour renvoyer la chaîne, et l'application doit appeler cette méthode. Il existe des moyens de convaincre la plupart des linkers qu'il s'agit d'un symbole requis sans le référencer, mais cela dépend de l'éditeur de liens et dépasse la portée de cette réponse.

Si au contraire, vous êtes familier avec le CSSC (code source du système de contrôle) alors vous utilisez man 1 what à la place, et il ressemblerait à ceci (fait avec des macros pour montrer la flexibilité 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; } 

et fc est compilé dans fo, la commande

what f.c f.o 

volonté sortie

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: les deux ident et what sont des commandes fournies avec des systèmes de contrôle de source centralisés spécifiques. Si vous utilisez un système de contrôle de source distribué (comme git), le concept entier peut ne pas avoir de sens. Pour certaines idées en utilisant git voir ce fil: Moving from CVS to git: $Id:$ equivalent? si le hachage n'est pas le même que le numéro de version. :)

0

Si vous utilisez gcc, vous pouvez utiliser la directive #ident

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

Pour obtenir la version il suffit d'utiliser une des options suivantes:

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

Cela vous permettra de compiler la version dans la bibliothèque avec la possibilité de l'enlever plus tard en utilisant strip -R .comment your_file ou complètement l'omettre en passant -fno-ident (Cela omettra également les commentaires de la version du compilateur des objets compilés)

Questions connexes