如何强制 .so 依赖项与库位于同一目录中
How to force .so dependency to be in same directory as library
我有一个 libA.so 依赖于 libB.so,即使它在同一目录中也找不到它。
ldd libA.so
linux-vdso.so.1 (0x00007fff50bdb000)
libB.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4aeb902000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4aebadb000)
我想知道是否有办法让 libA.so 始终在同一目录中查找 libB.so,因为我的应用程序就是这种情况?我知道更新 LD_LIBRARY_PATH
也是一个选项,但我想减少所需的工作量。
来自'man 8 ld.so':
If a shared object dependency does not contain a slash, then it
is searched for in the following order:
o Using the directories specified in the DT_RPATH dynamic
section attribute of the binary if present and DT_RUNPATH
attribute does not exist. Use of DT_RPATH is deprecated.
o Using the environment variable LD_LIBRARY_PATH, unless the
executable is being run in secure-execution mode (see below),
in which case this variable is ignored.
o Using the directories specified in the DT_RUNPATH dynamic
section attribute of the binary if present. Such directories
are searched only to find those objects required by DT_NEEDED
(direct dependencies) entries and do not apply to those
objects' children, which must themselves have their own
DT_RUNPATH entries. This is unlike DT_RPATH, which is applied
to searches for all children in the dependency tree.
o From the cache file /etc/ld.so.cache, which contains a
compiled list of candidate shared objects previously found in
the augmented library path. If, however, the binary was
linked with the -z nodeflib linker option, shared objects in
the default paths are skipped. Shared objects installed in
hardware capability directories (see below) are preferred to
other shared objects.
o In the default path /lib, and then /usr/lib. (On some 64-bit
architectures, the default paths for 64-bit shared objects are
/lib64, and then /usr/lib64.) If the binary was linked with
the -z nodeflib linker option, this step is skipped.
这里的关键是使用 DT_RUNPATH,它可以嵌入到您正在创建的二进制文件中。您可以 link 它指向同一目录,如您所愿。
查看此post了解如何执行此操作:
ELF 文件的 .dynamic
部分(Linux 上的 .so
库使用 ELF 格式)包含帮助库找到其依赖项的信息。 .dynamic
类型为 DT_NEEDED
的条目包含供动态 link 用户查找的其他 .so
文件的名称,但它们不包含有关在哪里可以找到这些文件的任何信息。为此,正如您提到的,您可以使用 LD_LIBRARY_PATH
,但 ELF 格式还提供了一种在文件本身中指定它的方法。
类型为 DT_RUNPATH
的 .dynamic
条目为动态 linker 提供了动态 linker 应该查找 DT_NEEDED
的目录路径文件。 DT_RUNPATH
允许一个特殊变量,$ORIGIN
,它指的是文件的当前目录。这允许您使用相对路径,而不需要用户从特定工作目录调用可执行文件。
您使用 -rpath
linker 标志来指定 DT_RUNPATH
条目。但是,为了传递文字字符串 $ORIGIN
,您必须将其用单引号括起来,以防止您的 shell 将其解释为环境变量。
假设您使用的是 gcc
,您应该将此参数添加到 link 步骤:
-Wl,-rpath,'$ORIGIN'
我有一个 libA.so 依赖于 libB.so,即使它在同一目录中也找不到它。
ldd libA.so
linux-vdso.so.1 (0x00007fff50bdb000)
libB.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4aeb902000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4aebadb000)
我想知道是否有办法让 libA.so 始终在同一目录中查找 libB.so,因为我的应用程序就是这种情况?我知道更新 LD_LIBRARY_PATH
也是一个选项,但我想减少所需的工作量。
来自'man 8 ld.so':
If a shared object dependency does not contain a slash, then it
is searched for in the following order:
o Using the directories specified in the DT_RPATH dynamic
section attribute of the binary if present and DT_RUNPATH
attribute does not exist. Use of DT_RPATH is deprecated.
o Using the environment variable LD_LIBRARY_PATH, unless the
executable is being run in secure-execution mode (see below),
in which case this variable is ignored.
o Using the directories specified in the DT_RUNPATH dynamic
section attribute of the binary if present. Such directories
are searched only to find those objects required by DT_NEEDED
(direct dependencies) entries and do not apply to those
objects' children, which must themselves have their own
DT_RUNPATH entries. This is unlike DT_RPATH, which is applied
to searches for all children in the dependency tree.
o From the cache file /etc/ld.so.cache, which contains a
compiled list of candidate shared objects previously found in
the augmented library path. If, however, the binary was
linked with the -z nodeflib linker option, shared objects in
the default paths are skipped. Shared objects installed in
hardware capability directories (see below) are preferred to
other shared objects.
o In the default path /lib, and then /usr/lib. (On some 64-bit
architectures, the default paths for 64-bit shared objects are
/lib64, and then /usr/lib64.) If the binary was linked with
the -z nodeflib linker option, this step is skipped.
这里的关键是使用 DT_RUNPATH,它可以嵌入到您正在创建的二进制文件中。您可以 link 它指向同一目录,如您所愿。
查看此post了解如何执行此操作:
ELF 文件的 .dynamic
部分(Linux 上的 .so
库使用 ELF 格式)包含帮助库找到其依赖项的信息。 .dynamic
类型为 DT_NEEDED
的条目包含供动态 link 用户查找的其他 .so
文件的名称,但它们不包含有关在哪里可以找到这些文件的任何信息。为此,正如您提到的,您可以使用 LD_LIBRARY_PATH
,但 ELF 格式还提供了一种在文件本身中指定它的方法。
类型为 DT_RUNPATH
的 .dynamic
条目为动态 linker 提供了动态 linker 应该查找 DT_NEEDED
的目录路径文件。 DT_RUNPATH
允许一个特殊变量,$ORIGIN
,它指的是文件的当前目录。这允许您使用相对路径,而不需要用户从特定工作目录调用可执行文件。
您使用 -rpath
linker 标志来指定 DT_RUNPATH
条目。但是,为了传递文字字符串 $ORIGIN
,您必须将其用单引号括起来,以防止您的 shell 将其解释为环境变量。
假设您使用的是 gcc
,您应该将此参数添加到 link 步骤:
-Wl,-rpath,'$ORIGIN'