【问题标题】:Linking shared library absolute vs. relative path链接共享库绝对路径与相对路径
【发布时间】:2018-11-06 11:06:55
【问题描述】:

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

【问题讨论】:

  • 你能发布 ldd 输出吗?库首先在 rpath 中搜索。 ldd 调用链接器获取程序依赖关系,它总是会打印到库的绝对路径。
  • @KamilCuk 完成。
  • 您是否使用 CMake 构建项目?不然你为什么要用cmake标签?

标签: gcc cmake linker shared-libraries


【解决方案1】:

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

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

gcc ... /home/projects/my_files/winter_fresh.so ...

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

要解决此问题,请将SONAME 添加到winter_fresh.so(一般来说是一个很好的做法),或者像这样链接它:

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

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

gcc ... -L /home/projects/my_files -lwinter_fresh

【讨论】:

    【解决方案2】:

    我的猜测是,您使用 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
    

    链接器在 RPATH 下搜索名为 /home/projects/my_files/winter_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__);
    }
    

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

    $ 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)
    

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

    $ mkdir -p lib/tmp
    $ mv exlib.so lib/tmp
    $ RPATH=$(pwd)/lib ./bad.out
    external_function
    

    运行 bad.out 时,链接器在 RPATH 内搜索名为 /tmp/exlib.so 的文件。
    Linux 使用命名shared libraries 的约定。现在让我们链接到 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.outlibexlib.so 相关联。链接时 gcc 在 /tmp 目录中搜索名为 libexlib.so 的库。我可以通过将 LD_LIBRARY_PATH 指定到 libexlib.so 所在的路径来运行 good.out:

     $ LD_LIBRARY_PATH=/tmp ldd ./good.out
     external_function
    

    【讨论】:

    • 我发现问题是创建共享库时缺少“-soname”。
    猜你喜欢
    • 2021-12-14
    • 2012-01-11
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-09
    相关资源
    最近更新 更多