我一直生活在幻想中,认为与
-L/some/path/ -lfoo
链接和与 /some/path/libfoo.so
链接是 100% 相同的事情(但到目前为止我从未使用过后者)。根据我最新的实验,情况似乎并非如此,我并不真正了解起作用的基本机制。
这里有一些有趣的信息:
还有那里
但这似乎并不能完全解释我在这个简单的例子中所看到的:
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
。
所有组合并非都同样有趣,但我无法理解一些关键方面:
与
-L/some/path/ -lfoo
链接和与/some/path/libfoo.so
链接显然不一样,如(test2和test6)或(test3和test7)的不同结果所示
使用显式
soname
构建共享库(按照此处的建议)似乎会导致比它解决的问题更多的问题,如(test5和test6)或(test7和test8)的不同结果所示
与
--no_undefined
链接不仅会影响链接时行为,还会影响运行时行为,如(test6 和 test10) 的不同结果所示
有人可以解释一下发生了什么事吗?
您可以使用“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)将失败。
总结-工作: