1. 找不到动态库的解决方法
Linux 动态库的默认搜索路径是 /lib
和 /usr/lib
,可使用以下方法来指定搜索路径
- 添加环境变量或移动动态库文件
1 | // 添加当前用户当前终端的环境变量(临时) |
- 添加 ldconfig 寻找路径
1 | vim /etc/ld.so.conf 直接添加路径 |
- 编译目标代码时指定程序的动态库搜索路径
1 | gcc xxx.c -Lxxx -lxxx -Wl,-rpath=xxx -o main |
使用 -Wl,-rpath=<link_path>
参数,<link_path>
就是链接库的路径
2. 动态库查找顺序
- 编译目标代码时指定的动态库搜索路径; //-L、-rpath和-rpath-link
- 环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
- 配置文件/etc/ld.so.conf中指定的动态库搜索路径;
- 默认的动态库搜索路径/lib;
- 默认的动态库搜索路径/usr/lib。
在上述1、2、3指定动态库搜索路径时,都可指定多个动态库搜索路径,其搜索的先后顺序是按指定路径的先后顺序搜索的。
3. 动态库路径(链接时和运行时)
现代链接器在处理动态库时将链接时路径(Link-time path)
和运行时路径(Run-time path)
分开。用户可以
- 通过
-L
指定编译链接时库的路径 - 通过
-R
或-rpath
指定程序运行时库的路径
链接器 ld 的选项有 -L
、-rpath
、-rpath-link
。区别如下
-L
:链接时去找的目录,也就是所有的-lxxx
选项里的库,都会先从-L
指定的目录去找,然后是其他默认地方。-L
只是指定了程序编译链接时库的路径,并不影响程序运行时库的路径-rpath
和-rpath-link
都可以在链接时指定库的路径。但是运行可执行文件时,-rpath-link
指定的路径就不再有效(链接器没有将库的路径包含到可执行文件中)-rpath
指定的路径有效(因为链接器已经将库的路径包含在可执行文件中了)
LIBRARY_PATH
和 LD_LIBRARY_PATH
环境变量的区别:
LIBRARY_PATH
环境变量用在程序编译期间查找动态链接库时指定查找库的路径LD_LIBRARY_PATH
环境变量用于在程序加载期间查找动态链接库时指定除了系统默认路径之外的其他路径
4. 其他命令
- 查看程序依赖的 so 库
1 | // 使用 ldd 查看可执行程序需要用到哪些动态库以及是否能找到 |
- 查看 so 库的信息
1 | // 查看 so 库的信息 |
5. 链接动/静态库
1 | # 第一种方式 |
当一个库文件既有 .a 又有 .so 时,gcc 会优先链接 .so 文件。如果强制链接 .a 库文件,如下即可
1 | gcc -Lxxx -l:libxxx.a -o main |
6. 静态库说明
创建静态库:将代码文件编译成目标文件(.o
),然后通过 ar
工具将目标文件打包成 .a
静态库文件
1 | gcc -c xxx.c -o xxx.o |
7. nm 命令
nm 命令可以打印出库中的涉及到的所有符号。库既可以是静态的,也可以是动态的。nm 列出的符号有很多,常见的有三种
- 一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用 U 表示
- 一种是库中定义的函数,用 T 表示,比较常见
- 一种的所谓的弱态符号,他们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用 W 表示