8

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

PS 我需要随时检查文件版本的可能性,而无需任何特殊的可执行文件,仅使用 shell 实用程序。

4

5 回答 5

10

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

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

并且能够从外壳检查它只需使用:

strings library.a | grep Version | cut -d " " -f 2
于 2009-10-28T16:06:37.710 回答
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在您的库中调用的结构。您可以通过在库中创建函数并从调用应用程序等访问这些函数来使用它来进行进一步的验证。

于 2009-10-28T16:19:37.823 回答
3

根据您的编辑创建一个新答案...只是为了避免混淆:)

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

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

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

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

于 2009-10-28T17:09:51.450 回答
1

如果你使用 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(这也将省略编译对象中的编译器版本注释)

于 2016-06-02T18:25:41.210 回答
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; }

而fc被编译成fo,那么命令

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].oaz.a你应该在az.a文件中找到它们的所有字符串。

警告:仅仅因为它们在 .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; }

而fc被编译成fo,那么命令

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请参阅此线程:从 CVS 迁移到 git:$Id:$ 等价物?尽管哈希与版本号不同。:)

于 2016-06-02T16:31:35.597 回答