无法打开共享对象文件

17

我正在尝试编译这里找到的一个项目:USB-I2C/SPI/GPIO接口适配器。

我下载了i2c_bridge-0.0.1-rc2.tgz包。我安装了libusb,没有遇到任何问题。我进入i2c_bridge-0.0.1-rc2/目录并执行make命令。那样编译了。我进入i2c_bridge-0.0.1-rc2/i2c文件夹并执行make命令。它编译了并给了我./i2c文件。然而,当我运行它时,它会显示错误信息:error while loading shared libraries: libi2cbrdg.so: cannot open shared object file: No such file or directory

i2c_bridge-0.0.1-rc2/i2c中的makefile将库目录设置为../libi2cbrdg.so在该目录下(i2c_bridge-0.0.1-rc2)。我还将该文件复制到/usr/local/lib。对i2c_bridge-0.0.1-rc2/目录执行命令ls

i2c        i2cbrdg.d  i2cbrdg.o  libi2cbrdg.a   Makefile  tests
i2cbrdg.c  i2cbrdg.h  INSTALL    libi2cbrdg.so  README    u2c4all.sh

(这里的i2c是一个目录)

即使我用sudo ./i2c执行,它仍然会出现问题。

我不得不在所有的makefile中去掉-Werror-noWdecrepated(拼写?)选项才能让它们编译通过,但这应该不会影响到这个问题,对吗?

还需要什么来找到.so文件呢?如果有人能帮我找出问题所在,我将不胜感激。如果需要更多信息,我可以发帖提供。


有时候,“无法打开共享对象文件”可以通过发出“sudo ldconfig”来解决,以刷新先前编译和安装的软件包的共享库缓存,使其准备好编译下游软件包。 - Scott Stensland
3个回答

41

你需要区分编译时和运行时找到so的区别。你在编译时提供的-L标志与在运行时本地化库无关。这可以通过一些变量和嵌入在库中的路径来完成。

对于这个问题,最好的热修复方法通常是将LD_LIBRARY_PATH设置为包含.so文件的目录,例如:

 $ LD_LIBRARY_PATH=.. ./i2c

如果想要一个长期的解决方案,你需要仔细查看整个LD系统的rpath和runpath,或者使用libtool(可以为您解决这些移植问题)。

将文件复制到/usr/local/lib通常不足以解决问题,因为ld缓存可用库,所以在将库复制到/usr/local/lib后,您需要重新运行ldconfig(作为root用户)。


LD_LIBRARY_PATH是否适用于我所有的库?那么,如果我运行该命令,它会影响其他事情,直到我将其改回来吗?我该如何查看现在设置为什么? - Sterling
2
这是一个环境变量。因此,您可以通过“echo $LD_LIBRARY_PATH”来检查它,并且在命令行中设置的方式仅适用于i2c进程及其子进程。 - thiton
1
不是我的问题,但感谢您的帮助解决了我确切的问题。 - Rich

25
如果你正在从源代码构建需要该库的代码,你可以在构建之前将库所在路径放入环境变量LD_RUN_PATH中,链接器会将这个路径保存到二进制文件中,这样在运行时自动查找正确的位置。
适用于Linux的方法:或者将库放置在/lib/usr/lib等某个路径下,该路径被引用于你的/etc/ld.so.conf或其导入的配置片段中,然后只需运行/sbin/ldconfig来刷新ld.so(动态链接器)对库的缓存。

尽管我在/etc/ld.so.conf.d/libc.conf中有/usr/local/lib,但是用sudo ldconfig进行动态链接库缓存刷新对我起了作用。 - Serge Stroobandt

5
这对于我的问题有用,希望能帮助其他人。
gcc test.c -Wl,-rpath /usr/local/lib -lfcgi -o test.fcg

-Wl,-rpath 选项是关键的技巧。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接