我制作了一个使用两个共享库(已编译)的程序,并将其放置如下:
/home_directory_where_I_compile_and_run_everything
-->/lib/libjson_linux-gcc-4.4.6_libmt.so
-->/lib/libre2.so.0
当我编译程序时,我将这些库的相对位置传递给链接器,如下所示:
g++ ...... stuff ........ my_program.cc lib/libjson_linux-gcc-4.4.6_libmt.so lib/libre2.so.0
而且它可以正常编译,但是在运行程序时找不到libre2.so,如果我使用ldd进行检查,则会发生以下情况:
....
lib/libjson_linux-gcc-4.4.6_libmt.so (0x00007f62906bc000)
libre2.so.0 => not found
....
显然,它确实确认libjson上的路径是相对路径,但在libre2.so.0上却不这样做(它修剪所有路径,只留下libre2.so.0)。
有人可以告诉我为什么会这样吗?
另外,有没有一种方法可以通过g++参数修改它?
最好。
*更新* 哇,快来看看!
我已经将libre2.so.0的名称更改为stuff.so,然后尝试像这样基本上编译:
g++ ...... stuff ........ my_program.cc lib/libjson_linux-gcc-4.4.6_libmt.so lib/stuff.so
反正它失败了;它不仅失败,而且因为找不到“libre2.so.0”而失败。
怎么了
*更新#2 *
readelf -d the_program.o
的输出0x0000000000000001 (NEEDED) Shared library: [lib/libjson_linux-gcc-4.4.6_libmt.so]
0x0000000000000001 (NEEDED) Shared library: [libre2.so.0]
现在,如果我可以将[libre2.so.0]设置为[lib/libre2.so.0],那就可以了。
*更新#3 *
正如@troubadour发现的那样:
这就是为什么它可用于libjson ..... so而不可用于libre2.so.0。 (libjson .....因此没有SONAME的条目)。
我终于找到了我要寻找的确切问题:
是否有任何方法可以告诉gcc链接程序忽略共享库文件上的SONAME条目,而是链接到特定的文件路径?
最佳答案
我将首先回答您问题的第二部分,即为什么重命名libre2.so.0并没有达到您的期望。
运行可执行文件时,传递给链接器的文件名无关紧要(除非在构建库时未能提供-soname
-请参见下面的第二个编辑)。依赖关系取自所谓的“soname”。如果在库上运行readelf
命令,则可以确定其soname,例如。
readelf -d libre2.so.0 | grep SONAME
重命名文件并不重要。上面命令的结果仍然会给您相同的名称,因此该程序仍无法找到“libre2.so.0”的原因。
对于您问题的原始部分,所有内容都取决于库中是否内置了
RPATH
或RUNPATH
,和/或LD_LIBRARY_PATH
环境变量的内容是什么。这些是运行时链接程序(ld.so)用于查找共享库的东西。尝试man ld.so
欲获得更多信息。
由于您自己构建了库,因此您将知道在最后的链接阶段它们是否使用了
-rpath
或-runpath
选项。或者,再次使用readelf
例如。readelf -d libre2.so.0 | grep RPATH
readelf -d libre2.so.0 | grep RUNPATH
我怀疑以上两个命令不会返回任何内容。
我的猜测是,您的
LD_LIBRARY_PATH
中有当前目录,这将允许运行时链接程序查找lib/libjson_linux-gcc-4.4.6_libmt.so,但不能找到libre2.so.0。我注意到您已回复我对问题的评论,说LD_LIBRARY_PATH
为空。真奇怪也许您以某种方式在libjson的soname上获得了前缀“lib/”?即是否为SONAME返回了
readelf
命令lib/libjson_linux-gcc-4.4.6_libmt.so
而不只是
libjson_linux-gcc-4.4.6_libmt.so
另外,通过运行以下命令检查程序在soname方面的需求
readelf -d my_progam | grep NEEDED
也许因为您将其传递给gcc的方式而使前缀“lib/”在其中。如果是这样,那么如果您使用@enobayram给出的gcc命令,它将平整公平竞争环境,即也将找不到libjson。
首先要确定的不是不是为什么找不到libre2.so.0,而是为什么要找到libjson。如果尝试从其他目录运行可执行文件,它仍然可以工作,或者现在对于libjson也失败了吗?或者,如果将libre2.so.0复制到可执行文件的旁边,这会改变吗?
编辑
posting on the Fedora Forum建议Fedora版本的ld.so将当前目录作为内置搜索路径。我还不能验证这一点,但是它可以解释为什么既然您的案例中没有ld.so使用的所有其他内容,那么为什么您要选择任何库。
编辑2
从我系统上的ld手册页
因此,您评论中的理论是正确的。如果在构建库时未明确指定
-soname
,则共享对象中不存在SONAME,并且可执行文件中的NEEDED字段仅具有指定给链接器的文件名,在您的情况下,该文件名包含前导“lib/”。