【问题标题】:GCC / Linux: adding a static library to a .so?GCC / Linux:将静态库添加到 .so?
【发布时间】:2009-08-17 23:58:29
【问题描述】:

我有一个程序,它通过从某个 plugin_name.so 动态加载一个函数来实现一个插件系统(像往常一样)。

但反过来,我有一个静态“帮助器”库(我们称之为 helper.a),它的功能既可用于主程序,也可用于插件中的主要功能。它们不必以任何方式进行互操作,它们只是文本操作等的辅助函数。

这个程序一旦启动,就无法重新加载或重新启动,这就是为什么我希望插件拥有新的“帮助”功能,而不是主程序。

所以我的问题是.. 是否可以强制 .so 中的这个“插件功能代码”使用(静态链接?)与主程序不同的(可能是更新的)“助手”版本?

如何做到这一点?也许通过静态链接或以其他方式将 helper.a 添加到 plugin_name.so?

【问题讨论】:

  • 我想补充一点,我不想或期望使用主程序中的新助手库。我只想将每个新插件与更新/更好的助手链接图书馆。
  • 辅助函数不能使用动态链接有什么原因吗?
  • 一旦启动,主程序无法停止执行,甚至重新加载更新的 helper.so.. 程序只需要非常基本的帮助功能,因为它只是插件的占位符。所以如果我有一个新的/改进的或扩展的帮助程序库,我更愿意再次编译整个插件。我认为分发一个 .so(插件)比分发两个 .so(插件和插件使用的最新助手)更实用
  • 所以您需要能够更新插件或插件使用的库代码,而无需重新启动主进程?
  • 这是正确的,增加了复杂性,可能有几十个插件作为线程并发运行,每个插件都有自己版本的帮助库(插件越新,库可能越新) - 并且 - 主程序还内置了一些非常简单的操作的帮助程序库,在其编译时可用的最新版本(我真的不关心在它工作正常时更新它)。也可能有其他库 - 使用 helper 中的功能 - 可以链接到每个插件..也许一些插件也会共享这些库..

标签: c++ linux gcc linker


【解决方案1】:

Nick Meyer 的答案在 Windows 和 AIX 上是正确的,但在默认情况下不太可能在所有其他 UNIX 平台上都是正确的。

在大多数 UNIX 平台上,运行时加载程序为所有符号维护一个单个名称空间,因此如果您在 a.outplugin.so 中定义 foo_helper,然后调用 @ 987654324@ 来自任何一个,默认情况下,对运行时加载程序可见的第一个定义(通常来自a.out)用于两个调用。

此外,由于foo_helper 可能无法从a.out 导出(因此可能对运行时加载程序不可见),情况变得复杂,除非您使用-rdynamic 标志或其他一些 共享库引用它。换句话说,事情可能看起来像 Nick 描述的那样工作,然后你将一个共享库添加到 a.out 链接行,它们就不再那样工作了。

在 ELF 平台(例如 Linux)上,您可以很好地控制符号的可见性和绑定。请参阅 GCC 手册页中对 -fvisibility=hidden-rdynamic 的描述,以及链接器手册页中的 -Bsymbolic

大多数其他 UNIX 平台也有一些方法来控制符号绑定,但这必然是特定于平台的。

【讨论】:

    【解决方案2】:

    如果您的主程序和动态库都静态链接到 helper.a,那么您不必担心混用 helper.a 的版本(只要您不做诸如传递在 helper.a 中分配的指针之类的事情。 a 在 .exe 和 .so 边界之间)。

    helper.a 所需的代码在您链接时插入到实际的二进制文件中。因此,当您从 .exe 调用 helper.a 时,您将从可执行映像的代码段执行代码,而当您从 .so 调用 helper.a 时,您将从加载 .so 的地址空间。即使您在 helper.a 中调用相同的函数,您也会调用该函数的两个不同“实例”,具体取决于调用是从 .exe 还是 .so 进行的。

    【讨论】:

    • 我明白了。但是如何在编译时将 libhelper.a 中的代码添加到 plugin.so 中?我应该在编译plugin.so时指定类似“gcc -lhelper.a -static”的东西吗?
    • 如果你的库是libhelper.a,则在编译plugin.so时将-Ldir -lhelper传递给gcc,其中dir为路径到 libhelper.a。无需指定 -static,在创建静态库时使用。
    • 此答案仅在未说明的有限条件下是正确的。
    【解决方案3】:

    我认为这个问题和你的一样。 How to force symbols from a static library to be included in a shared library build?

    --whole-archive 链接器选项应该这样做。您可以将其用作例如

    gcc -o libmyshared.so foo.o -lanothersharedlib -Wl,--whole-archive -lmystaticlib

    它对我有用。

    【讨论】:

      猜你喜欢
      • 2020-02-01
      • 1970-01-01
      • 2013-10-29
      • 2011-09-12
      • 1970-01-01
      • 2017-08-05
      • 1970-01-01
      • 1970-01-01
      • 2019-09-15
      相关资源
      最近更新 更多