为什么LD_LIBRARY_PATH是BAD以及加载动态库的正确方法

所以,我有一个运行OpenBlas的程序,我想编译它。 链接过程如下所示:

gcc -o prog prog.o -O3 -I/opt/OpenBLAS/include -L/opt/OpenBLAS/lib -lopenblas 

到现在为止还挺好。 如果我删除-L选项,我在链接过程中出错

 /usr/bin/ld: cannot find -lopenblas 

使用-L所有链接都没有错误。 但是,当我尝试运行它时,我收到以下错误:

 ./prog: error while loading shared libraries: libopenblas.so.0: cannot open shared object file: No such file or directory 

如果我将env变量LD_LIBRARY_PATH设置为/opt/OpenBlas/lib我可以运行该程序,但很多来源如http://xahlee.info/UnixResource_dir/_/ldpath.html认为这是一个不好的做法,我可以理解几乎所有的推理。 文章中提到的另一种方法(修改ld配置)也被认为是一种不好的做法。 最后,您可以在/usr/lib向库中添加符号链接。 最后两种方法的一个大问题是您需要sudo访问权限。

所以我的问题是如何在不使用LD_LIBRARY_PATH和sudo访问的情况下编译和运行链接到不在默认路径( /usr/lib )中的共享库的程序。 在文章中他们说你可以在二进制文件中“写”寻找共享库,但我不知道如何做( -L标志似乎没有这样做)。 我很感激,如果有人能解释这个问题,因为我一直在寻找各处,我很困惑(一些参考文献似乎表明标志’-L’应该这样做,但我不适合我)。 先感谢您。

将路径添加到运行时库搜索路径。

 gcc -Wl,-rpath=/opt/OpenBlas/lib ... 

-L选项在链接时执行的操作, -rpath选项在运行时执行。

在linux上,也可以在rpath中使用$ ORIGIN来表示应用程序的目录路径,并从那里构建相对rpath。 然后,您可以将库移动到二进制文件的已知相对路径。

 gcc -o prog prog.o -O3 -I/opt/OpenBLAS/include -Wl,-rpath=\$ORIGIN/lib -L/opt/OpenBLAS/lib -lopenblas 

您还可以使用库的完整路径,它将链接到:

 gcc -o prog prog.o -O3 -I/opt/OpenBLAS/include /opt/OpenBLAS/lib/libopenblas.so 

如果在可执行文件上运行“ldd”,则应该看到编码的完整路径。