如何在静态库(file.a)中存储版本号,然后在Linux中检查其版本?
PS我需要任何时候检查文件版本的可能性,没有任何特殊的可执行文件只使用shell实用程序。
也许你可以用这样的版本创建一个字符串:
char* library_version = { "Version: 1.3.6" };
并能够从shell中检查它只是使用:
strings library.a | grep Version | cut -d " " -f 2
除了提供一个由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
的结构体。 你可以通过在库中创建函数并从调用应用程序访问这些函数来进行进一步验证。
根据您的编辑创建一个新的答案…只是为了避免混淆:)
如果你正在寻找一个非代码的方式来解决这个问题,你可以试试这个。 它(又一次)是Puppe定义的strings
方法的替代方案。
也许你可以触摸一个名为version_1.2.3
的文件并将其添加到存档中。 然后,您可以使用ar命令查找版本文件来确定版本:
ar t libmylib.a | grep 'version_' | sed -e 's/^version_//'
我不确定这是否会得到您所需要的内容,但没有将这样的元数据嵌入到档案中的标准方法。 也许你会发现你想存储在这个“图元文件”的档案的其他信息。
几次man 1 ident
已被提及,所以这里是关于使用该方法的细节。
ident
是RCS(修订版本控制系统)附带的命令,但如果您使用CVS(并行版本系统)或Subversion,也可能可用。
你会像这样使用它(从手册页克隆):
#include <stdio.h> static char const rcsid[] = "$Id: fc,v 5.4 1993/11/09 17:40:15 eggert Exp $"; int main() { return printf("%s\n", rcsid) == EOF; }
而fc被编译成fo,然后是命令
ident fc fo
会输出
fc: $Id: fc,v 5.4 1993/11/09 17:40:15 eggert Exp $ fo: $Id: fc,v 5.4 1993/11/09 17:40:15 eggert Exp $
如果你的fo
被添加到一个静态库fa
然后ident fa
应该显示一个类似的输出。 如果你在你的az.a
有几个类似构建的[az].o
,你应该在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; }
而fc被编译成fo,然后是命令
what fc fo
会输出
fc: @(#) EXP v 5.4 1993/11/09 17:40:15 eggert fo: @(#) EXP v 5.4 1993/11/09 17:40:15 eggert
PS:既有ident
也有特定集中式源代码管理系统的命令。 如果你使用分布式源代码控制系统(比如git),那么整个概念可能就没有意义了。 对于使用git
一些想法看到这个线程: 从CVS转移到git:$ Id:$ equivalent? 尽管哈希与版本号不一样。 🙂
如果您使用的是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
完全忽略它(这也将省略编译对象的编译器版本注释)