为什么我不能用LD_LIBRARY_PATH覆盖动态库的搜索路径?

时间:2015-11-04 10:37:26

标签: linux ld dynamic-linking fftw

编辑:我解决了这个问题,解决方法如下。

我正在专用于科学计算的共享计算集群中构建代码,因此我只能控制主文件夹中的文件。虽然我使用fftw作为示例,但我想了解具体原因,为什么我尝试设置LD_LIBRARY_PATH不起作用。

我在我的主文件夹中构建了fftw和fftw_mpi库,如下所示

./configure --prefix=$HOME/install/fftw --enable-mpi --enable-shared
make install

它构建正常,但在install / fftw / lib中,我发现新构建的libfftw3_mpi.so链接到错误版本的fftw库。

$ ldd libfftw3_mpi.so |grep fftw
  libfftw3.so.3 => /usr/lib64/libfftw3.so.3 (0x00007f7df0979000)

如果我现在尝试将LD_LIBRARY_PATH设置为正确指向此目录,它仍然更喜欢错误的库:

$ export LD_LIBRARY_PATH=$HOME/install/fftw/lib
$ ldd libfftw3_mpi.so |grep fftw
    libfftw3.so.3 => /usr/lib64/libfftw3.so.3 (0x00007f32b4794000)

只有我明确使用LD_PRELOAD,我才能覆盖此行为。我不认为LD_PRELOAD是一个合适的解决方案。

$ export LD_PRELOAD=$HOME/install/fftw/lib/libfftw3.so.3 
$ ldd libfftw3_mpi.so |grep fftw
   $HOME/install/fftw/lib/libfftw3.so.3 (0x00007f5ca3d14000)

这是我期望的,在Ubuntu桌面上完成的一个小测试,我先将fftw安装到/ usr / lib,然后使用LD_LIBRARY_PATH覆盖此搜索路径。

$ export LD_LIBRARY_PATH=
$ ldd q0test_mpi |grep fftw3
    libfftw3.so.3 => /usr/lib/x86_64-linux-gnu/libfftw3.so.3
$ export LD_LIBRARY_PATH=$HOME/install/fftw-3.3.4/lib
$ ldd q0test_mpi |grep fftw3
    libfftw3.so.3 => $HOME/install/fftw-3.3.4/lib/libfftw3.so.3

简而言之:为什么libfft3_mpi库仍然找不到错误的动态fftw3库?此搜索路径在何处以这样的方式进行硬编码,使其优先于LD_LIBARY_PATH?为什么在另一台计算机上不是这种情况?

如果这很重要,我正在使用英特尔编译器13.1.2,mkl 11.0.4.183和openmpi 1.6.2。

编辑:感谢您的所有答案。在这些帮助下,我们能够将问题隔离到RPATH,从那里,集群支持能够找出问题所在。我接受了第一个答案,但两个答案都很好。

为什么这么难以弄清楚的原因是我们不知道编译器实际上是包装脚本,在编译器命令行中添加了东西。这是支持部门的回复的一部分:

  

[编译]通过我们的编译器包装器完成。我们做RPATH   默认情况下,它可以帮助大多数用户正确运行他们的工作   没有加载LD-LIBRARY_PATH等但是我们排除了某些   默认RPATH的库路径,包括/ lib,/ lib64 / proj   / home等。之前/ usr / lib64没有被错误排除   (大多)。现在我们在排除列表中添加了该路径。

2 个答案:

答案 0 :(得分:16)

来自http://man7.org/linux/man-pages/man8/ld.so.8.html

  

在解析共享对象依赖项时,首先是动态链接器          检查每个依赖关系字符串以查看它是否包含斜杠(this          如果包含斜杠的共享对象路径名是,则会发生          在链接时指定)。如果找到斜杠,那么依赖          string被解释为(相对或绝对)路径名,而          使用该路径名加载共享对象。

     

如果共享对象依赖项不包含斜杠,那么它是          按以下顺序搜索:

     

o(仅限ELF)使用DT_RPATH动态中指定的目录             二进制文件的section属性(如果存在)和DT_RUNPATH             属性不存在。不推荐使用DT_RPATH。

     

o使用环境变量LD_LIBRARY_PATH。除非是             可执行文件是set-user-ID / set-group-ID二进制文件,在这种情况下它是             被忽略了。

     

o(仅限ELF)使用DT_RUNPATH中指定的目录             二进制文件的动态部分属性(如果存在)。

     

o来自缓存文件/etc/ld.so.cache,其中包含已编译的文件             先前在扩充中找到的候选共享对象的列表             图书馆路径。但是,如果二进制文件与-z链接             nodeflib链接器选项,默认路径中的共享对象是             跳过。安装在硬件功能中的共享对象             目录(见下文)优先于其他共享对象。

     

o在默认路径/ lib中,然后在/ usr / lib中。 (在某些64位上             archiectures,64位共享对象的默认路径             / lib64,然后是/ usr / lib64。)如果二进制文件与之链接             -z nodeflib链接器选项,跳过此步骤。

  • 使用readelf readelf -d libfftw3_mpi.so,您可以检查您的lib是否在动态部分中包含此类属性。

  • 使用export LD_DEBUG=libs
  • 您可以调试用于查找库的搜索路径

  • chrpath -r<new_path> <executable>可以更改rpath

答案 1 :(得分:3)

我认为有两个可能的原因。

首先,libfftw3_mpi.so可能与/usr/lib64/ RPATH相关联。在这种情况下,提供LD_LIBRARY_PATH将不起作用。要检查是否属于您的情况,请运行readelf -d libfftw3_mpi.so | grep RPATH并查看它是否有/usr/lib64/作为库路径。如果是,请使用chrpath实用程序更改或删除它。

或者,您可能正在运行一个根本不支持LD_LIBRARY_PATH的系统(如HP-UX)。