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

Gcc 链接共享库绝对路径与相对路径,gcc,cmake,linker,shared-libraries,Gcc,Cmake,Linker,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/libpth

我一直在尝试将一个共享库链接到我的程序中,我希望它的路径与我的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)

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

我的猜测是,您使用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
$ mkdir -p lib/tmp
$ mv exlib.so lib/tmp
$ RPATH=$(pwd)/lib ./bad.out
external_function
链接器在RPATH下搜索名为
/home/projects/my\u files/winter\u fresh.so的库

下面是一个简单的测试:

// 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__);
}
正如您看到的字符串
/tmp/exlib.so
指向共享库。我可以运行该程序,使用RPATH将链接器指向exlib.so位置。我需要在RPATH中创建子树
/tmp/exlib.so
,如下所示:

 $ 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
$ mkdir -p lib/tmp
$ mv exlib.so lib/tmp
$ RPATH=$(pwd)/lib ./bad.out
external_function
运行bad.out时,链接器在
RPATH
中搜索名为
/tmp/exlib.so
的文件
Linux使用命名约定。现在让我们链接到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)
现在您看到,
good.out
链接到
libexlib.so
。gcc在链接时在/tmp目录中搜索名为libexlib.so的alibrary。通过指定LD_LIBRARY_路径到libexlib.so路径,我可以运行good.out:

 $ LD_LIBRARY_PATH=/tmp ldd ./good.out
 external_function
问题是第一个文件。我不希望冬季图书馆成为一条绝对的道路

这通常发生在您链接库时,如下所示:

gcc ... /home/projects/my_files/winter_fresh.so ...
而且您的库没有
SONAME
(您在构建它时没有使用
-SONAME
链接器选项)

要解决此问题,请将
SONAME
添加到
winter\u fresh.so
(通常这是一个很好的做法),或者将其链接如下:

gcc ... -L /home/projects/my_files -l:winter_fresh.so
gcc ... -L /home/projects/my_files -lwinter_fresh
更好的方法可能是将
winter\u fresh.so
重命名为
libwinter\u fresh.so
,然后像这样链接:

gcc ... -L /home/projects/my_files -l:winter_fresh.so
gcc ... -L /home/projects/my_files -lwinter_fresh

你能发布ldd输出吗?首先在rpath中搜索库。ldd调用链接器以获取程序依赖项,它将始终打印到库的绝对路径。@KamilCuk已完成。是否使用CMake构建项目?否则,为什么要使用
cmake
标记?我发现问题在于创建共享库时缺少“-soname”。