【问题标题】:Load shared library only if dependencies are met仅在满足依赖关系时才加载共享库
【发布时间】:2019-03-04 13:58:23
【问题描述】:

我有一个链接到两个共享库的可执行文件,每个共享库都依赖于系统共享库。 (在这种情况下,这些是 OpenCL 和 CUDA 运行时库,但这不影响问题)

     +--> libA.so  --->  libOpenCL.so (on system)
Exe -|
     +--> libB.so  --->  libcudart.so (on system)

ExelibA.solibB.so 被分发给用户。用户可能没有在他们的系统上安装libOpenCL.so 和/或libcudart.so

目标是Exe 无论如何都应该能够启动,并在运行时检测到,例如libA.so 无法加载,因为它的依赖关系不满足。

一种可能性是让libA.so 在运行时使用dlopen() 加载,它会检测加载是否失败。

是否也可以将libA.so 正常链接到Exe,但是如果libA.so 无法加载,Exe 仍然可以启动?这在 Linux 和/或 Windows 平台上可行吗?

【问题讨论】:

  • 您是自己构建 libAlibB 库还是外部库?
  • @yugr 是的 libAlibBExe 一起构建,具有相同的编译器/ABI。它们也可以是静态的,甚至是Exe 的一部分。它们是库,主要是为了对它们的依赖项进行分组(例如libB 需要多个 CUDA 库)

标签: c linux windows linker dynamic-linking


【解决方案1】:

如果你想这样做,你需要dlopen。在程序加载时,除了执行失败之外,没有用于错误报告的向量,也没有任何合理的选择来确定在缺少的库中要找到的符号如果缺少定义将解析为什么。

【讨论】:

  • 如果对可能丢失的 DLL 的显式依赖不是强制性的,可以使用延迟加载(有关详细信息,请参阅我的答案)。
  • 确实,您的回答可能适合OP。在回退路径中使用带有虚拟库的自定义库路径可能会实现类似的效果,但它似乎很脆弱。
【解决方案2】:

在 Windows 上,您可以将 libAlibB 链接到 delay-loaded mode 中可能丢失的 DLL。这将阻止运行时系统加载 DLL,直到您的程序实际调用其函数之一。

Linux 没有开箱即用的延迟加载功能,但您可以通过将libOpenCL.so(或libcudart.so)中的函数的虚拟包装器添加到libA(或libB)中来模仿它。 Wrappers 将 dlopen 在第一次调用时需要库并跳转到真正的函数实现。这样的包装器可以手工编写或通过Implib.so自动生成:

# This will generate libOpenCL.tramp.S and libOpenCL.init.c
# which need to be linked into libA.
$ implib-gen.py libOpenCL.so

因此,libA 将不再直接链接到 libOpenCL.so,除非您调用使用 OpenCL 的函数,否则您的程序将正常运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-22
    • 2011-01-20
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    相关资源
    最近更新 更多