我的项目树看起来像这样:
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
将小路你的库的(你确实将其设置为库本身,这不起作用),与你使用-L
gcc 参数设置的相同,例如
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