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

skd*_*skd 16 c c++ compiler-errors shared-libraries

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

gcc -o prog prog.o -O3 -I/opt/OpenBLAS/include -L/opt/OpenBLAS/lib -lopenblas
Run Code Online (Sandbox Code Playgroud)

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

/usr/bin/ld: cannot find -lopenblas
Run Code Online (Sandbox Code Playgroud)

随着-L一切链接没有错误.但是,当我尝试运行它时,我收到以下错误:

./prog: error while loading shared libraries: libopenblas.so.0: cannot open shared object file: No such file or directory
Run Code Online (Sandbox Code Playgroud)

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

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

Die*_*Epp 19

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

gcc -Wl,-rpath=/opt/OpenBlas/lib ...
Run Code Online (Sandbox Code Playgroud)

-L选项在链接时的作用是什么,该-rpath选项在运行时执行.

  • 这可能是OP正在寻找的答案,虽然它也很糟糕,因为它构建了可执行文件的路径,需要重新编译可执行文件以重新定位库.因此,您应该基本了解所有解决方案,为什么它们都是坏的,然后选择对您的用例最不利的解决方案.;) (3认同)
  • @DavidSchwartz:您可以重新定位库而无需重新编译,您只需将其重新定位到运行时搜索路径中的其他位置...如果您不使用“-rpath”,这与您的选择相同。如果你确实想将库移到其他地方,你可以随时使用“LD_LIBRARY_PATH”。抱歉,我没有看到缺点,除了如果将二进制文件复制到另一个系统,`-rpath` 可能会有点“吵闹”。 (2认同)
  • "-Wl"是在创建exectuable时将rpath选项传递给链接器"ld". (2认同)

Jua*_*uan 6

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

gcc -o prog prog.o -O3 -I/opt/OpenBLAS/include -Wl,-rpath=\$ORIGIN/lib -L/opt/OpenBLAS/lib -lopenblas
Run Code Online (Sandbox Code Playgroud)

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

gcc -o prog prog.o -O3 -I/opt/OpenBLAS/include /opt/OpenBLAS/lib/libopenblas.so
Run Code Online (Sandbox Code Playgroud)

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