使用绝对路径链接共享库

问题描述 投票:0回答:1

我一直生活在幻想中,认为与

-L/some/path/ -lfoo
链接和与
/some/path/libfoo.so
链接是 100% 相同的事情(但到目前为止我从未使用过后者)。根据我最新的实验,情况似乎并非如此,我并不真正了解起作用的基本机制。

这里有一些有趣的信息:

使用绝对路径指定库的 GCC 行为是什么

还有那里

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

但这似乎并不能完全解释我在这个简单的例子中所看到的:

foo.c

int foo_func(int i)
{
    return i+1;
}

bar.c

#include <stdio.h>

extern int foo_func(int i);

int main(int argc, char *argv[])
{
    fprintf(stdout, "%d\n", foo_func(argc));
    return 0;
}

Makefile

clean:
    mkdir -p install
    rm -f ./install/*

########################

foo_simple: clean
    gcc foo.c -shared -fPIC -o ./install/libfoo.so

foo_soname: clean
    gcc foo.c -shared -fPIC -o ./install/libfoo.so -Wl,-soname=libfoo.so  

######################## Traditional way with lib-dirs (-L)

bar_libdir_%: %
    gcc bar.c -L`pwd`/install -lfoo -o ./install/bar

######################## Without lib-dir but absolute paths instead

bar_abspath_%: %
    gcc bar.c `pwd`/install/libfoo.so -o ./install/bar

bar_abspath_no_undefined_%: %
    gcc bar.c `pwd`/install/libfoo.so -o ./install/bar -Wl,-no-undefined

######################## sims

sim1_%: %
    cd install ; ./bar

sim2_%: %
    ./install/bar

test1:  sim1_bar_libdir_foo_simple                 # Works
test2:  sim1_bar_libdir_foo_soname                 # Works
test3:  sim2_bar_libdir_foo_simple                 # Fails - Error while loading shared libraries
test4:  sim2_bar_libdir_foo_soname                 # Fails - Error while loading shared libraries

test5:  sim1_bar_abspath_foo_simple                # Works
test6:  sim1_bar_abspath_foo_soname                # Fails - Error while loading shared libraries
test7:  sim2_bar_abspath_foo_simple                # Works
test8:  sim2_bar_abspath_foo_soname                # Fails - Error while loading shared libraries

test9:  sim1_bar_abspath_no_undefined_foo_simple   # Works
test10: sim1_bar_abspath_no_undefined_foo_soname   # Works
test11: sim2_bar_abspath_no_undefined_foo_simple   # Works
test12: sim2_bar_abspath_no_undefined_foo_soname   # Fails - Error while loading shared libraries

首先要做的事情:任何人都可以重现我 12 次测试的结果吗?

为了完整起见,makefile 有一个详尽的组合列表,有/没有绝对路径,并且还可能使用

soname
和/或
--no-undefined
。 所有组合并非都同样有趣,但我无法理解一些关键方面:

  1. -L/some/path/ -lfoo
    链接和与
    /some/path/libfoo.so
    链接显然不一样,如(test2和test6)或(test3和test7)的不同结果所示

  2. 使用显式

    soname
    构建共享库(按照此处的建议)似乎会导致比它解决的问题更多的问题,如(test5和test6)或(test7和test8)的不同结果所示

  3. --no_undefined
    链接不仅会影响链接时行为,还会影响运行时行为,如(test6 和 test10)

    的不同结果所示

有人可以解释一下发生了什么事吗?

c linker shared-libraries ld
1个回答
0
投票

您可以使用“man ld.so”获取完整详细信息 - 下面是简短版本。

答案假设您已将环境变量 LD_LIBRARY_PATH 设置为“.” (或类似的),基于您的测试结果 - 特别是 test1。

在我的测试中,我得到了与你相同的结果 - 除了 test5,f

当您提供共享对象的名称时,链接会将提供的名称(libfoo.so 或 /path/to/libfoo.so)存储到可执行文件中。

当您尝试运行可执行文件时,动态链接加载器 (ld.so) 将尝试使用以下规则查找引用的共享库:

  • 如果名称以“/”开头,则假定为绝对路径名。这涵盖了带有abspath的测试用例(test5、test7、test9、test11)。所有这些情况都使用共享对象的完整路径。

  • 如果名称包含“/”(但不以 1 开头),则假定它是当前路径的相对路径名。您没有任何测试用例。它将是“gcc bar.c install/libfoo.so -o install/bar ; install/bar)

  • 如果名称不包含“/”(例如 libfoo.so、-lfoo 或 soname=libfoo.so),则搜索路径(使用 LD_LIBRARY_PATH env var,以及可能已设置到二进制文件中的 DT_RPATH 属性,以及系统提供的库:“/lib64”、“/usr/lib64”等)。由于没有明确的搜索路径,它将仅使用当前文件夹。这适用于从“安装”文件夹(test1、test2、test8、test10)执行代码的情况。

所有其他情况都会失败。这基本上涵盖了代码使用不带“.”的路径的情况(soname、-lfoo 或 libfoo.so),并且程序从不包含 libfoo.so 的文件夹中执行。测试3,测试4,测试6,测试12。

如果从环境中删除 LD_LIBRARY_PATH(取消设置 LD_LIBRARY_PATH),搜索路径将不包括当前文件夹,并且测试用例 test1、test2、test8、test10)将失败。

总结-工作:

  • 使用abspath(无soname)并从任何文件夹运行
  • 不带路径(-lfoo, libfoo.so soname=libfoo.so),并使用LD_LIBRARY_PATH到相对/绝对路径列表,并在当前文件夹可以通过路径找到共享对象时执行程序。
  • 否则失败。
© www.soinside.com 2019 - 2024. All rights reserved.