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

我find了一个库, libjson ,我试图build立一个共享库并在一个项目中使用。 build筑很简单, 修复了一个Makefile错误之后,

 # SHARED=1 make install 

将在/usr/lib编译和安装.so 。 问题是我的系统(Arch Linux)已经有一个名为libjson的库,Makefile为我覆盖了这个库! Arch的库被安装为一个依赖项,所以它不能被replace。 据推测,其他发行版也会有类似的问题,如果他们有一个名为libjson的库。

我能做些什么呢? 我可以重命名这个库( libjson-mine或者其他的东西),但是dynamic链接离魔术只有几步之遥,所以我不知道这是否会破坏某些东西。 我怎样才能重命名图书馆?

另一个select是将库的源代码放到我当前项目的源代码树中,然后让构build器创build一个静态库。 (显然这使得我的代码存储库变得有点混乱,因此不合要求)。如果我走了这条路线,我需要让链接器更喜欢我的libjson.a而不是search/usr/lib “适合”(阅读:错误)库。 如何让链接器更喜欢我的版本?

或者,还有第三个选项我不知道?

背景概念

共享库有两点使用:

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

    在执行时,标准路径将被搜索该基名。

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

    • GCC如何在默认的链接器默认搜索路径之前添加? LIBRARY_PATH不起作用
    • 如何阻止gcc将标准库路径传递给链接器

    您可能能够脱离/usr/local/lib目的是为用户编译的库,应该在/usr/lib之前。

    但这样做会打破使用其他libjson任何东西,所以你可能不希望这样做。

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

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

您可以用以下方式检查可执行文件中存储的内容:

 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中找到一个选项来更改生成的库的基本名称。

    如果这个选项不存在,请求pull。 如果业主不想接受,分叉项目;-)

    然后你和你的发行版在编译时可以使用这个选项。

  3. 在Makefile中找到一个选项,用来改变库+头文件的安装目录,然后使用一些完全自定义的( ~/usr/lib~usr/include ),并将其添加到动态加载程序搜索路径中。 图书馆路径? +包含搜索路径。 见GNU方法make的DESTDIR和PREFIX 。

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

    不理想,但可能为一次性工作。

有几种方法:

  • 默认情况下安装的库听起来好像你也可以使用这些东西。 想过那个?
  • 也许你确实可以重命名“其他”json库,并将其安装到/usr/local/lib
  • 也许你可以学习在Arch Linux上构建一个(pacman?)包。 我不知道,但不应该太难。 至少,这不是基于RPM的系统,所以我不在Arch上。
  • 你可以用一种方式在你的之间:

    从另一个项目构建一个静态库,并将其包含在您自己的项目中。 这样你就不会搞乱安装的库,而且你的代码树也是干净的。