前几天做在做开发的时候,遇到一个编译报错问题,弄到半夜3点才解决。
具体错误是:/usr/bin/ld: cannot find -lLLVM-13-rust-1.58.0-nightly, 也就是gcc编译的时候缺少lLLVM-13-rust-1.58.0-nightly的第三方库,但是这个库的存放位置已经被写入zshrc的配置文件中的LD_LIBRARY_PATH位置,所以百思不得其解,最终查看各种资料才发现LIBRARY_PATH和LD_LIBRARY_PATH的区别。
1. LIBRARY_PATH
-
用途:
-
用于 编译阶段,告诉编译器(如
gcc或clang)在哪里查找静态库 (.a) 和动态库 (.so或.dylib)。 -
编译器在链接时使用这个路径来找到依赖的库文件。
-
-
常见场景:
- 当你编译程序并需要链接某些库(例如
gcc main.c -o main -lfoo),如果foo不在默认的库搜索路径下,你可以通过设置LIBRARY_PATH来告诉编译器去哪里找。
- 当你编译程序并需要链接某些库(例如
-
影响工具:
- 主要被编译器(如
gcc、clang)使用。
- 主要被编译器(如
-
示例:
export LIBRARY_PATH=/custom/lib/path:$LIBRARY_PATH gcc main.c -o main
2. LD_LIBRARY_PATH
-
用途:
-
用于 运行阶段,告诉动态链接器(
ld.so或ld-linux.so)在加载动态库时,优先从哪里查找.so文件。 -
这是运行时的动态库搜索路径。
-
-
常见场景:
- 当运行的程序依赖的动态库不在默认的搜索路径(如
/usr/lib、/lib)中时,可以通过设置LD_LIBRARY_PATH告诉系统去哪里找动态库。
- 当运行的程序依赖的动态库不在默认的搜索路径(如
-
影响工具:
- 主要被动态链接器(
ld.so)使用。
- 主要被动态链接器(
-
示例:
export LD_LIBRARY_PATH=/custom/lib/path:$LD_LIBRARY_PATH ./main
主要区别
| 属性 | LIBRARY_PATH | LD_LIBRARY_PATH |
| ------------ | ------------------------------ | --------------------------------------- |
| 作用阶段 | 编译阶段 | 运行阶段 |
| 使用场景 | 查找静态库和动态库以供链接 | 加载动态库以供程序运行 |
| 使用工具 | 编译器(如 gcc、clang) | 动态链接器(如 ld.so、ld-linux.so) |
| 作用对象 | 静态库 (.a) 和动态库 (.so) | 动态库 (.so) |
如何同时使用
如果你在开发时需要编译和运行程序,并且库文件不在系统默认路径中,你可能需要同时设置这两个变量。
export LIBRARY_PATH=/custom/lib/path:$LIBRARY_PATH
export LD_LIBRARY_PATH=/custom/lib/path:$LD_LIBRARY_PATH
gcc main.c -o main
./main
这样,编译器和动态链接器都能正确找到所需的库文件。
注意事项
-
安全性问题:
-
滥用
LD_LIBRARY_PATH可能引入安全风险,特别是在多用户系统中,攻击者可以通过伪造动态库进行攻击。 -
如果可能,优先使用
rpath或RUNPATH来指定运行时库路径,而不是依赖LD_LIBRARY_PATH。
-
-
调试问题:
- 设置过多的路径可能导致链接器行为复杂化,建议仅在必要时设置,并注意路径的优先级。
-
持久化配置:
- 如果需要长时间使用这些变量,可以将它们添加到
~/.bashrc或~/.zshrc中。
- 如果需要长时间使用这些变量,可以将它们添加到
总结
-
编译时找不到库 → 设置
LIBRARY_PATH。 -
运行时找不到库 → 设置
LD_LIBRARY_PATH。 -
它们的功能不同,不是同一个东西。