【问题标题】:Trying to build C++ exe that uses .so that uses other .so files尝试构建使用 .so 的 C++ exe 使用其他 .so 文件
【发布时间】:2021-10-29 15:02:17
【问题描述】:

我正在尝试构建一个与共享库 libA.so 链接的 C++ 可执行文件。 libA.so 被构建并与另一个共享库 libB.so 链接。 libB.so 是使用 -rpath 构建的,用于在我的主目录 (liblapack.so) 中查找系统库的自定义构建。如果我在 libB.so 上执行“readelf -d”,我会将 liblapack.so 视为“NEEDED”,并且还会看到“RPATH”下列出的自定义构建路径。如果我对 libA.so 执行“readelf -d”,我只会看到 libB.so 列为“NEEDED”;没有 RPATH 条目。然后,当我尝试使用 libA.so 构建我的 exe 时,它​​没有在 libB.so 中指定的自定义路径中查找;它正在拾取系统位置中的一个,该位置没有正确的功能,因此链接失败。有谁知道实现我想要在这里做的事情的方法?有没有办法让 libB 的 RPATH 条目传播到 libA?

我在 RHEL 7 上使用 GCC 9。

提前致谢。

ETA:应用程序、libA 和 libB 都是独立的包,所以我更愿意让它们的构建过程和不寻常的 rpath 信息只有他们自己知道。我可以更改每个黑匣子的链接标志。它们也是已建立的软件包,因此我无法更改为 autoconf 或类似的东西。

ETA2:重申一下,当我构建 libA 并与 libB 链接时,它确实将 libA 标记为需要 libB,这很棒。然后应用程序可以与 libA 链接并隐式获取 libA 需要运行的 libB。但是为什么将 libB 与 libA 链接会丢弃 libB 的 rpath 信息?或者,当应用程序链接时,为什么它看不到,因为 libA 需要 libB,与 libB 链接并保留 libB 的 rpath 规范?最重要的是,libB 的 rpath 规范正在某个地方丢失,而且看起来不应该这样。 (顺便说一句:这对我来说是新事物,所以我不怀疑我认为它应该工作的方式存在问题。但从逻辑上讲,这听起来对我来说是正确的。)

【问题讨论】:

  • 您是否尝试指定构建libA 时所需的-rpath 条目?
  • 我在构建 libA 时没有尝试指定 -rpath,但我假设它会起作用。它们是单独的包,所以我想尽可能避免它。也许必须这样做。
  • 有些工具可以自动处理类似的技术细节。像 autmake 和 libtool 这样的工具负责管理这些包间的依赖关系。
  • 考虑到这些软件包很难。也许不是这样,但是链接器不能只携带 libB 的 RPATH 条目吗?这样就可以解决问题,而且看起来很明智。
  • 除非与问题相关的所有相关信息都包含在问题本身中,否则任何人都不太可能帮助回答问题。否则,任何提供的建议都可能导致这种“但由于我现在第一次提到的 而这不起作用”的响应,并浪费大家的时间。

标签: c++ linux shared-libraries


【解决方案1】:

链接时使用-rpath-link 并指定您的自定义库位置。

gcc -o app source.o -lA -Wl,-rpath-link=$HOME

这将导致链接器在$HOME 中查找其他共享库引用的共享库。但仅在链接时。在运行时,当动态链接完成时,rpath-link 选项无效,使用正常的 RPATH、LD_LIBRARY_PATH 等搜索顺序。

已搜索共享库中的 DT_RPATHDT_RUNPATH。但它们并不是搜索顺序中的第一位。您的替代版本的 libB 必须位于首先出现的路径中,因此可以找到它而不是您想要的。尝试重命名它,看看会发生什么,或者检查您的 LD_LIBRARY_PATHLD_RUN_PATH 变量。

没有办法改变顺序,但-rpath-link是第一位的,所以这可以解决问题。

要使 libB 独立,请使用 pkgconfig 文件之类的文件,其中包含使用库所需的选项。这也适用于查找头文件或静态库。

您还可以将 libA 重命名为 libMyA 以避免与同时安装的备用版本发生名称冲突。

或者,使用--allow-shlib-undefined 链接器选项可以避免链接失败,而无需真正解决问题。那么它是否找到错误的版本应该没有关系,因为丢失的符号不会是错误。

【讨论】:

  • 我确实尝试过,它确实有效。但正如我稍后在评论中提到的,应用程序、libA 和 libB 都是不相关的包,因此最好将它们作为彼此相关的黑盒子。我了解这可能无法按照工具当前的工作方式进行。谢谢。
  • 看起来你要做的是“构建 C++ exe”,但我猜你想在不添加编译器标志的情况下这样做。不知道有什么方法可以让 ld 或 gold 做到这一点。我认为假设是您应该在系统搜索路径中安装系统共享库,可以通过多种方式进行控制。如果库暂时位于不寻常的位置,例如在安装之前运行,则您正在构建它们并且可以设置链接器标志以反映该位置。如果库需要使用标志,则使用 pkgconfig 之类的东西来获取它们。
  • 我应该在问题中明确提到我不希望 app(或 libA)知道 libB 奇怪的 rpath 设置。对不起;我编辑了这个问题。我通常可以将编译器/链接器标志添加到任何单独的部分。在这种情况下,简单的答案似乎是“它不像那样工作”。话虽如此,我很好奇为什么它没有。这似乎是明智的。
  • 这里真正的问题是ld 使用的搜索顺序与ld.so 使用的搜索顺序不同。后者找到你想要的库,而前者没有。我不知道用库本身而不是链接器选项来改变它的方法。我认为顺序不同的原因是它更适合在一个位置构建软件然后在另一个位置安装的更正常情况。
  • 除非我在构建 app 或 libA 时使用 -rpath-link 或 -rpath(就像您在上面所做的那样),否则我无法构建 app 可执行文件。它抱怨仅在我的主目录(而不是系统目录)中的 lapack 构建中定义的一些函数未定义。所以我不确定 ld.so 是否参与?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多