编译后更改Linux共享库(.so文件)版本

jpo*_*o38 17 c++ linux versioning g++ shared-libraries

我正在编译Linux库(对于Android,使用NDK的g ++,但我敢打赌我的问题对任何Linux系统都有意义).在将这些库提供给合作伙伴时,我需要使用版本号标记它们.我还必须能够以编程方式访问版本号(例如,在"关于"对话框或GetVersion函数中显示它).

我首先使用unversioned标志(版本0.0)编译库,并且在我将测试发送给合作伙伴之前完成测试时需要将此版本更改为真实版本.我知道修改源代码并重新编译会更容易,但我们不想这样做(因为如果我们重新编译代码,我们应该再次测试所有内容,我们觉得它不会出错,请看这个注释post和最后因为我们的开发环境以这种方式工作:我们为Windows二进制文件执行此过程:我们设置0.0资源版本字符串(.rc),然后我们使用verpatch更改它...我们想要使用相同的类型运送Linux二进制文件时的进程).

这里最好的策略是什么?总而言之,要求是:

  1. 用"未设置"版本(0.0或其他任何东西)编译二进制文件
  2. 能够将此"未设置"版本修改为特定版本而无需重新编译二进制文件(理想情况下,运行第三方工具命令,就像在Windows下使用verpatch一样)
  3. 能够让库代码在运行时检索它的版本信息

如果您的答案是"重命名.so",那么请提供3的解决方案:如何在运行时检索版本名称(即:文件名).

我在考虑一些解决方案,但不知道它们是否可以工作以及如何实现它们.

  • 在代码中有一个版本变量(一个string或三个int),并有办法在以后的二进制文件中更改它?使用二进制sed ......?
  • 在资源中有一个版本变量,并有办法在以后的二进制文件中更改它?(正如我们为win32/win64所做的那样)
  • 使用专用于此的.so(如SONAME)字段,并有一个允许更改它的工具......并使其可以从C++代码访问.
  • 重命名lib +更改SONAME(没有找到如何实现)...并找到一种从C++代码中检索它的方法.
  • ...

请注意,我们使用QtCreator来编译Android .so文件,但它们可能不依赖于Qt.因此使用Qt资源并不是一个理想的解决方案.

jpo*_*o38 2

与 Slava 的讨论让我意识到任何内容const char*实际上在二进制文件中都是可见的,并且可以轻松地修补到其他任何内容。

所以这是解决我自己的问题的好方法:

  1. 创建一个库:
    • 的定义const char version[] = "VERSIONSTRING:00000.00000.00000.00000";(我们需要它足够长的时间,因为我们稍后可以安全地修改二进制文件内容但不能扩展它......)
    • 一个GetVersion可以清理version上面变量的函数(removeVERSIONSTRING:和unused 0)。它将返回:
      • 0.0如果versionVERSIONSTRING:00000.00000.00000.00000
      • 2.3如果versionVERSIONSTRING:00002.00003.00000.00000
      • 2.3.40如果versionVERSIONSTRING:00002.00003.00040.00000
      • ...
  2. 编译库,我们命名它mylib.so
  3. 从程序加载它,询问它的版本(调用GetVersion),它返回0.0,毫不奇怪
  4. 创建一个小程序(用 C++ 完成,但也可以用 Python 或任何其他语言完成),它将:
    • 将整个二进制文件内容加载到内存中(使用std::fstreamwith std::ios_base::binary
    • VERSIONSTRING:00000.00000.00000.00000在里面找到
    • 确认它只出现一次(以确保我们不会修改我们无意的内容,这就是为什么我在字符串前面加上VERSIONSTRING, 使其更加独特......)
    • VERSIONSTRING:00002.00003.00040.00000如果预期的二进制数是,则将其修补为2.3.40
    • 将修补后的内容保存回二进制文件
  5. mylib.so使用上述工具打补丁(2.3例如请求版本)
  6. 运行与步骤 3 相同的程序,它现在报告2.3

无需重新编译或链接,您修补了二进制版本!