链接共享库绝对与相对路径

Pro*_*ain 4 linker gcc cmake shared-libraries

我一直在尝试将共享库链接到我的程序中,我希望它的路径与我的 RPATH 相关。

但是,当我运行ldd时,我注意到共享库的绝对路径是链接的。任何想法为什么?

编辑:

/home/projects/my_files/winter_fresh.so
libgcc_s.so.1 => /home/tomo/anaconda3/lib/libgcc_s.so.1 (0x00007f0a3bf64000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0a3bd47000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0a3b97d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0a3e369000)
libstdc++.so.6 => /home/tomo/anaconda3/lib/libstdc++.so.6 (0x00007f0a3b643000)
Run Code Online (Sandbox Code Playgroud)

问题是第一个文件。我不希望 Winter_fresh 的库成为绝对路径,因为我有一个包含它的 RPATH。

Emp*_*ian 8

问题是第一个文件。我不希望 Winter_fresh 的库成为绝对路径

当您像这样链接到您的库时,通常会发生这种情况:

gcc ... /home/projects/my_files/winter_fresh.so ...
Run Code Online (Sandbox Code Playgroud)

并且您的库没有SONAME(您-soname在构建它时没有使用链接器选项)。

要解决此问题,请添加SONAMEwinter_fresh.so(一般来说是一个好习惯),或者像这样链接它:

gcc ... -L /home/projects/my_files -l:winter_fresh.so
Run Code Online (Sandbox Code Playgroud)

更好的方法可能是重命名winter_fresh.solibwinter_fresh.so,然后像这样链接它:

gcc ... -L /home/projects/my_files -lwinter_fresh
Run Code Online (Sandbox Code Playgroud)


Kam*_*Cuk 1

我的猜测是,您使用 Winter_fresh.so 作为源文件编译了程序,而不是通过链接它。
如果您将共享库/可执行文件的路径编码为/home/projects/my_files/winter_fresh.so,则可以将共享库放入 RPATH 目录中,如下所示:

 $ mkdir some_dir
 $ mkdir -p some_dir/home/projects/my_files
 $ cp /home/projects/my_files/winter_fresh.so some_dir/home/projects/my_files
 $ RPATH=$(pwd)/some_dir ./executable
Run Code Online (Sandbox Code Playgroud)

链接器搜索/home/projects/my_files/winter_fresh.soRPATH 下命名的库。

现在进行一个简单的测试:

// main.c
int main() {
  int external_function(void);
  return external_function();
}

// exlib.c
#include <stdio.h>
int external_function(void) {
  return printf("%s\n", __func__);
}
Run Code Online (Sandbox Code Playgroud)

现在,让我们创建使用共享库作为源的bad.out编译:exlib.so

$ gcc -shared -fPIC -o exlib.so exlib.c
$ gcc /tmp/exlib.so main.c -o bad.out
$ ldd bad.out
linux-vdso.so.1 (0x00007ffd921db000)
/tmp/exlib.so (0x00007fe4470f7000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fe446d3b000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fe4474fb000)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,该字符串/tmp/exlib.so指向共享库。我可以运行该程序,使用 RPATH 将链接器指向 exlib.so 位置。我需要/tmp/exlib.so在 RPATH 内创建子树,如下所示:

$ mkdir -p lib/tmp
$ mv exlib.so lib/tmp
$ RPATH=$(pwd)/lib ./bad.out
external_function
Run Code Online (Sandbox Code Playgroud)

/tmp/exlib.so运行 bad.out 时,链接器会搜索名为inside的文件RPATHLinux 使用命名共享库
的约定。现在让我们链接到 good.out:

$ gcc -shared -fPIC -o libexlib.so exlib.c
$ gcc -I /tmp -lexlib main.c -o good.out
$ ldd good.out 
linux-vdso.so.1 (0x00007ffcb01bf000)
libexlib.so => not found
libc.so.6 => /usr/lib/libc.so.6 (0x00007fc1230ef000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fc1236ad000)
Run Code Online (Sandbox Code Playgroud)

现在您看到它good.out与 相关联libexlib.so。链接时, gcc 在 /tmp 目录中搜索名为lib exlib .so的库。我可以通过将 LD_LIBRARY_PATH 指定为 libexlib.so 所在的路径来运行 good.out:

 $ LD_LIBRARY_PATH=/tmp ldd ./good.out
 external_function
Run Code Online (Sandbox Code Playgroud)