共享库搜索路径

Posted by DEVIN on Sun, Jun 18, 2023

基本原理

-L编译选项是编译期间使用

LD_LIBRARY_PATH环境变量是运行期间使用,可以用来指定so的加载路径,并且优先级高于系统默认的。

RPATHRUNPATH是ELF格式里面的一个数据,rpath编译选项实际上是在可执行文件中加入了RUNPATH或者RPATH

小结一下一个ELF文件自身加载so的情况(不可信,仅供参考):

其实这三者的关系概括起来没有几点:

  1. LD_LIBRARY_PATH是个环境变量,优先级高于系统默认的。
  2. RPATH是ELF格式里面的一个数据,他的优先级比LD_LIBRARY_PATH还要高
  3. RUNPATH很特殊,如果他出现了RPATH就躲起来了,LD_LIBRARY_PATH 又成了首选??
ELF 中 RPATH ELF 中 RUNPATH LD_LIBRARY_PATH 变量 尝试加载目录的顺序
未设置 未设置 未设置 /lib => /usr/lib
未设置 未设置 设置 ${LD_LIBRARY_PATH} => /lib => /usr/lib
设置 未设置 未设置 ${RPATH} => /lib => /usr/lib
设置 未设置 设置 ${RPATH} => ${LD_LIBRARY_PATH} => /lib => /usr/lib
设置 或 未设置 设置 设置 ${LD_LIBRARY_PATH} => ${RUN_PATH} => /lib => /usr/lib
设置 或 未设置 设置 未设置 ${RUN_PATH} => /lib => /usr/lib

LD_LIBRARY_PATH 例子

 1// a.c
 2#include <stdio.h>
 3
 4extern void test_b();
 5void test_a()
 6{
 7    test_b();
 8}
 9
10int main()
11{
12    test_a();
13    return 0;
14}
15
16// b.c
17#include <stdio.h>
18
19void test_b()
20{
21}
 1root@ubuntu:/usr1/tmp/2# gcc b.c -shared -fPIC -o lib/libmyb.so
 2root@ubuntu:/usr1/tmp/2# gcc -o a a.c -Llib -lmyb
 3root@ubuntu:/usr1/tmp/2# 
 4root@ubuntu:/usr1/tmp/2# ./a
 5./a: error while loading shared libraries: libmyb.so: cannot open shared object file: No such file or directory
 6root@ubuntu:/usr1/tmp/2# 
 7root@ubuntu:/usr1/tmp/2# export LD_LIBRARY_PATH=lib
 8root@ubuntu:/usr1/tmp/2# ./a
 9root@ubuntu:/usr1/tmp/2# 
10root@ubuntu:/usr1/tmp/2# tree

RPATH和RUNPATH 例子

 1// a.c
 2#include <stdio.h>
 3
 4extern void test_b();
 5void test_a()
 6{
 7    test_b();
 8}
 9
10int main()
11{
12    test_a();
13    return 0;
14}
15
16// b1.c, b2.c
17#include <stdio.h>
18
19void test_b()
20{
21    printf("test_b in: %s\n", __FILE__);
22}
 1unset LD_LIBRARY_PATH
 2gcc b1.c -shared -fPIC -o lib1/libmyb.so
 3gcc b2.c -shared -fPIC -o lib2/libmyb.so
 4gcc -o a a.c -Llib1 -lmyb -Wl,-rpath=lib2
 5tree
 6
 7ldd ./a
 8readelf -d ./a | grep PATH
 9
10export LD_LIBRARY_PATH=lib1
11ldd ./a
12readelf -d ./a | grep PATH

参考文档

RPATH和RUNPATH区别 - 简书 (jianshu.com)

RPATH RUNPATH 和 LD_LIBRARY_PATH_pkpkpk的专栏-CSDN博客