如何在静态库中存储版本号?

时间:2009-10-28 15:57:53

标签: c linux static-libraries

如何在静态库(file.a)中存储版本号,然后在Linux中检查其版本?

P.S。我需要随时使用shell实用程序检查文件版本而无需任何特殊可执行文件。

5 个答案:

答案 0 :(得分:10)

除了提供Puppe提到的静态字符串之外,通常的做法是提供一个宏来检索版本检查的兼容性。例如,您可以使用以下宏(在头文件中声明以与库一起使用):

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

注意MYLIB_CHECK_VERSION宏,我假设你想要一个特定的主要转速和一个小于或等于你想要的版本的小转速。根据您的申请需要进行更改。

然后在调用应用程序中使用它,例如:

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

此方法将导致版本信息来自包含的头文件。此外,它将在编译时针对调用应用程序进行优化。通过更多工作,您可以从库本身中提取它。请继续阅读...

如Puppe所述,您还可以使用此信息创建存储在库中的静态字符串。在你的图书馆里放置这样的东西:

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

这将在您的库中创建一个名为mylib_version的结构。您可以通过在库中创建函数并从调用应用程序等访问这些函数来使用它来进行进一步的验证。

答案 1 :(得分:9)

也许你可以用这样的版本创建一个字符串:

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

并且能够从shell中检查它只需使用:

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

答案 2 :(得分:3)

根据您的编辑创建新答案...为避免混淆:)

如果您正在寻找解决问题的非代码方式,您可以试试这个。它(又一次)是Puppe定义的strings方法的替代方案。

也许您只需触摸一个名为version_1.2.3的文件并将其添加到存档中即可。然后,您可以使用ar命令查找版本文件来确定版本:

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

我不确定这是否能满足您的需求,但是没有标准方法可以在存档中嵌入这样的元数据。也许你会在这个档案的“元文件”中找到你想要存储的其他信息。

答案 3 :(得分:0)

已多次提到man 1 ident,因此这里有关于使用该方法的详细信息。

ident是RCS(修订控制系统)附带的命令,但如果您使用的是CVS(并发版本系统)或Subversion,则可能也可用。

您可以像这样使用它(从手册页克隆):

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

和f.c被编译成f.o,然后是命令

ident f.c f.o

将输出

   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 $

如果您的f.o已添加到静态库f.a,则ident f.a应显示类似的输出。如果您的[a-z].o中有几个类似构建的az.a,则应在az.a文件中找到所有字符串。

CAVEAT:仅仅因为它们在.a文件中并不意味着它们将包含在您的程序文件中。除非程序引用它们,否则链接器不需要包含它们。因此,您通常必须在每个模块中都有一个方法来返回字符串,并且应用程序需要调用该方法。有一些方法可以说服大多数链接器它是一个必需的符号而没有实际引用它,但它取决于链接器,超出了这个答案的范围。

如果您熟悉SCCS(源代码控制系统),那么您将使用man 1 what代替它,它看起来像这样(用宏来完成以显示可用的灵活性):

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

和f.c被编译成f.o,然后是命令

what f.c f.o

将输出

   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:identwhat都是特定集中式源控制系统附带的命令。如果您使用的是分布式源代码控制系统(如git),整个概念可能没有意义。对于使用git的一些想法,请参阅此主题:Moving from CVS to git: $Id:$ equivalent?尽管散列与版本号不同。 :)

答案 4 :(得分:0)

如果您使用的是gcc,则可以使用#ident指令

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

要获取该版本,请使用以下其中一项:

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

这将允许您将版本编译到库中,以后可以使用strip -R .comment your_file将其删除,或者通过传递-fno-ident完全省略它(这也将省略编译器版本注释编译对象)