我找到了一个库libjson
,我试图将其构建为共享库并在项目中使用。建筑很简单;修复Makefile错误后
# SHARED=1 make install
将在.so
中编译并安装/usr/lib
。问题是我的系统(Arch Linux)已经有一个名为libjson
的库,Makefile不经意地覆盖了我! Arch的库作为依赖项安装,因此无法替换。据推测,如果其他发行版有一个名为libjson
的库。
我该怎么办?我可以重命名库(libjson-mine
或其他东西),但动态链接距离魔法只有几步之遥,所以我不知道这是否会破坏某些东西。 如何重命名库?
另一种选择是将库的源代码放到我当前项目的源代码树中,让构建器创建一个静态库。 (显然这会使我的代码存储库有点混乱,因此不可取。)如果我走这条路,我需要让链接器更喜欢我的libjson.a
,而不是搜索/usr/lib
的“合适” (读:错)库。 如何让链接器更喜欢我的版本?
或者,是否有第三种选择我不知道?
答案 0 :(得分:3)
背景概念
共享库在两点使用:
ld
)如果使用-llibjson
在gcc中编译,则基本名称将存储在可执行文件中
在执行时,将搜索标准路径以查找该基本名称。
在链接时,链接器必须能够在其搜索路径上找到您的库。 prepend 到搜索路径并不容易:
您可能可以使用/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? +包括搜索路径。有关GNU方法,请参阅DESTDIR and PREFIX of make。
然后在编译/执行时,更改包含/动态加载程序搜索路径。
不理想,但可能适用于一次性。
答案 1 :(得分:1)
有几种方法:
/usr/local/lib
。你可以选择介于你的之间:
从其他项目构建静态库,并将其包含在您自己的项目中。这样你就不会搞乱已安装的库,尽管如此你仍然可以清理你的代码树。