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

# SHARED=1 make install

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

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

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


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

解决方法:

背景概念

共享库有两点使用:

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

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

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

GCC how to add before the default linker search path by default? LIBRARY\_PATH not working
How to stop gcc from passing -L with standard library paths to the linker

您可以使用/usr/local/lib来获取用户编译库,并且应该在/usr/lib之前.

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

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

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

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

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

可能的解决方案

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

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

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

这是最好的选择,必须迟早要做,否则它将成为无休止混淆的源头……发送拉动请求!

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

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

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

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

在Makefile中找到一个选项,用于更改安装库头的目录,然后使用完全自定义的东西(〜/usr/lib,~usr / include),并将其添加到动态加载器搜索路径How to specify preference of library path? include search path .有关GNU方法,请参阅DESTDIR and PREFIX of make.

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

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

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

相关文章推荐

添加新评论,含*的栏目为必填