4

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

# SHARED=1 make install

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

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

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

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

4

2 回答 2

3

背景概念

共享库用于两点:

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

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

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

    您可能能够摆脱/usr/local/lib为用户编译的库而设计的并且应该在/usr/lib.

    但是这样做会破坏任何使用 other 的东西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搜索路径中。

    这是最好的选择,迟早要完成,否则会造成无尽的混乱……发送拉取请求!

    在同一个拉取请求中,还将默认安装目录更改为/usr/local/lib而不是/usr/lib. 这就是默认情况下正常用户编译的库必须去的地方,正是为了避免覆盖分发提供的库。

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

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

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

  3. 在 Makefile 中找到一个选项来更改安装库 + 头文件的目录,然后使用完全自定义的东西(~/usr/lib, ~usr/include),并将其添加到您的动态加载程序搜索路径如何指定库路径的首选项?+ 包括搜索路径。有关GNU 方法,请参见make 的 DESTDIR 和 PREFIX 。

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

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

于 2013-11-02T07:57:00.030 回答
1

有几种方法:

  • 默认安装的库听起来好像你也可以使用它。想过吗?

  • 也许您确实可以重命名“其他” json 库,并将其安装到/usr/local/lib.

  • 也许你可以学习在 Arch Linux 上构建一个(pacman?)包。我不知道,但应该不会太难。至少,它不适用于基于 RPM 的系统,所以我认为它也不在 Arch 上。

  • 您可以采用介于两者之间的方式:

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

于 2013-11-02T08:50:47.917 回答