如何重命名共享库以避免同名冲突?

时间:2013-11-02 07:23:51

标签: linux linker shared-libraries dynamic-linking file-rename

我找到了一个库libjson,我试图将其构建为共享库并在项目中使用。建筑很简单;修复Makefile错误后

# SHARED=1 make install

将在.so中编译并安装/usr/lib。问题是我的系统(Arch Linux)已经有一个名为libjson的库,Makefile不经意地覆盖了我! Arch的库作为依赖项安装,因此无法替换。据推测,如果其他发行版有一个名为libjson的库。

,则会遇到类似的问题

我该怎么办?我可以重命名库(libjson-mine或其他东西),但动态链接距离魔法只有几步之遥,所以我不知道这是否会破坏某些东西。 如何重命名库?

另一种选择是将库的源代码放到我当前项目的源代码树中,让构建器创建一个静态库。 (显然这会使我的代码存储库有点混乱,因此不可取。)如果我走这条路,我需要让链接器更喜欢我的libjson.a,而不是搜索/usr/lib的“合适” (读:错)库。 如何让链接器更喜欢我的版本?

或者,是否有第三种选择我不知道?

2 个答案:

答案 0 :(得分:3)

背景概念

共享库在两点使用:

  • 链接器编译(ld
  • 由动态加载程序执行
  1. 如果使用-llibjson在gcc中编译,则基本名称将存储在可执行文件中

    在执行时,将搜索标准路径以查找该基本名称。

    在链接时,链接器必须能够在其搜索路径上找到您的库。 prepend 到搜索路径并不容易:

    您可能可以使用/usr/local/lib,这是用于用户编译的库,应该在/usr/lib之前。

    但这样做会破坏使用其他libjson的任何内容,所以你可能不希望这样。

  2. 如果使用-l:/full/path/to/libjson.so在gcc中编译,则完整路径将存储在可执行文件中。

    执行时,不需要路径搜索,因为我们已经有完整路径。

  3. 您可以使用以下命令检查可执行文件中存储的内容:

    readelf -d a.out | grep 'Shared library'
    

    可能的解决方案

    我没有看到任何不需要编辑项目的Makefile的好解决方案,因此细节是项目特定的。但总的来说,你可以:

    1. 编辑库的Makefile或类似文件,并将基本名称重命名为libjson_mine.so

      使用以下代码编译需要该库的程序:-ljson_mine。这将有效,因为我们知道/usr/lib位于.so搜索路径中。

      这是最好的选择,必须迟早要做,否则会成为无休止的困惑的根源......发送拉动请求!

      在同一个pull请求中,还要将默认安装目录更改为/usr/local/lib而不是/usr/lib。这是理所当然的用户编译库必须默认使用的地方,完全是为了避免覆盖分发提供的库。

    2. 如果所有者不想重命名库,请在Makefile中找到一个选项来更改生成的库的基本名称。

      如果此选项不存在,请提取请求。如果所有者不想接受,请分叉项目; - )

      然后您和您的发行版可以在编译时使用该选项。

    3. 在Makefile中查找更改库+标头安装目录的选项,然后使用完全自定义的内容(~/usr/lib~usr/include),并将其添加到动态加载程序搜索路径How to specify preference of library path? +包括搜索路径。有关GNU方法,请参阅DESTDIR and PREFIX of make

      然后在编译/执行时,更改包含/动态加载程序搜索路径。

      不理想,但可能适用于一次性。

答案 1 :(得分:1)

有几种方法:

  • 默认安装的库听起来好像也可以使用它。想到这个?
  • 也许您确实可以重命名“其他”json库,并将其安装到/usr/local/lib
  • 也许你可以学习在Arch Linux上构建一个(pacman?)软件包。我不知道它,但它不应该太难。至少,它不适用于基于RPM的系统,所以我认为它不在Arch上。
  • 你可以选择介于你的之间:

    从其他项目构建静态库,并将其包含在您自己的项目中。这样你就不会搞乱已安装的库,尽管如此你仍然可以清理你的代码树。