加载共享库时出错

加载共享库时出错

我的项目树看起来像这样:

src/
include/
Makefile
lib/
   lib/3rdparylib/

我没有编码3rdpartylib,但决定将其源代码嵌入到我的项目打包中。我通过执行以下步骤来编译该软件:

$ cd lib/3rdpartylib/
$ make
$ ln -s 3rdpartylib.so.0 3rdpartylib.so

然后我编译每个我的源文件如下:

$ gcc -c src/file.c -I include -o file.o -l 3rdparylib -L lib/3rdpartylib -I lib/3rdpartylib/include

然后我链接:

$ gcc file1.o file2.o -l3rdpartylib -L lib/3rdpartylib -o myapp

当我在我的主机上时,它工作得很好。今天我尝试在另一台机器上启动它。它编译和链接没有任何问题。但是,当我尝试启动该应用程序时,收到以下错误消息。

./myapp:加载共享库时出错:3rdpartylib.so.0:无法打开共享对象文件:没有这样的文件或目录

我尝试执行以下操作:

export LD_LIBRARY_PATH=/path/to/3rdpartylib.so

似乎有效。但我知道使用 LD_LIBRARY_PATH 是一种不好的做法。每次我想运行我的应用程序时都要设置这个变量,这让我很困扰。

我缺少什么?为什么它在我的主机上工作(LD_LIBRARY_PATH 未设置任何内容),而在另一台机器上不起作用?另一台机器是虚拟机有关系吗?

如果有帮助的话,我的主机器是 Debian 机器,我的“新”机器是 Sabayon (Gentoo),在 Virtualbox 中运行。

答案1

重要的是每台机器使用什么 Linux 发行版,因为它们处理库路径的方式不同。在 Gentoo (Sabayon) 机器上,如果您希望第三方库在整个系统范围内可用,您应该:

  • 在该文件下创建一个文件/etc/env.d/,其中将包含附加环境设置。这些文件使用该方案命名[0-9][0-9]somename- 两个初始数字决定它们的使用顺序。一个好的做法需要添加您的自定义设置(附近)最后的99只要有效,这就是一个正确的开始。进入正题:创建一个名为类似的文件

    /etc/env.d/99mythirdpartylib
    

    含有

    LDPATH=/path/to/your/library
    
  • 要使更改生效而无需重新启动,请以 root 身份运行:

    env-update && source /etc/profile
    

    (这将更新环境并运行ldconfig)。

参考,如果你想要的话。

答案2

如果您不想使用该方法为整个系统设置全局库搜索路径/etc/env.d,您可以:

只需LD_LIBRARY_PATH小路你的库的(你确实将其设置为库本身,这不起作用),与你使用-Lgcc 参数设置的相同,例如

export LD_LIBRARY_PATH="$PROJ/lib/3rdpartylib/:$LD_LIBRARY_PATH"

(最后一部分用于保留变量(如果已设置),但通常不应该这样)。 这仅适用于您当前的 shell,并且您每次都必须重新设置它。

或者您使用“静态”库搜索路径进行链接,如下所示:

gcc file1.o file2.o -L./lib/3rdpartylib -Wl,-rpath=./lib/3rdpartylib  -l3rdpartylib  -o myapp

-Wl指定不会由 gcc 处理而是传递给链接器的命令行参数。 由于库搜索路径将被写入二进制文件中,因此即使在不同的机器上也可以工作(只要库存在)

附:由于你只是谈论你正在开发一个项目的情况,我认为这种临时方式比将其放在系统范围的配置文件中更合适。

答案3

该行:

$ gcc file1.o file2.o -l3rdpartylib -L lib/3rdpartylib -o myapp

搜索在您的库路径中调用的文件lib3rdpartylib.so,该文件甚至不包括lib/3rdpartylib!如果您查看 gcc 手册页,它指出在指定库路径时,-L它必须位于-l标志之前,否则将不会被搜索。实际上,最简单的解决方案就是链接到库本身:

$ gcc file1.o file2.o lib/3rdpartylib/3rdpartylib.so -o myapp

这样,将在库路径中搜索该库并在myapp运行时动态加载。

如果您想检查它,只需strace -eopen ./myapp在安装后执行一次,然后查看它尝试从何处加载库。

答案4

您必须告诉您的系统在哪里寻找库。这项工作是由 完成的/etc/ld.so.cache。您可以在 中添加库或整个目录/etc/ld.so.conf

您可以通过执行以下操作来重建缓存:

# /sbin/ldconfig -v

相关内容