一般情况下qt打包目录结构如下:
bin目录为可执行文件
lib目录为qt依赖的一大堆库

1、报错问题
运行可执行文件报错,缺少libcrypto++.so.6,但如下图所示,库已经是存在的:
error while loading shared libraries: libcrypto++.so.6: cannot open shared object file: No such file or directory

2、分析:
qt.conf 是 Qt 框架专用 的配置文件。它主要用来告诉 Qt 应用程序去哪里寻找 Qt 插件(Plugins) 、QML 组件 或者 Qt 自身的动态库(如 libQt5Core.so)。
然而,libcrypto++.so.6 是一个标准的 C++ 开源加密库(Crypto++),它不是 Qt 的一部分。
-
当程序启动时,首先由操作系统的系统动态链接器 (而不是 Qt 框架)去寻找
libcrypto++.so.6。 -
在系统链接器去找这个库的时候,Qt 的环境还没初始化,它根本不会去读取
qt.conf
方法 1:临时测试 ------ 使用 LD_LIBRARY_PATH
这是最快验证问题的方法。在终端中直接把上一级目录加到系统的动态库搜索路径中:
bash
export LD_LIBRARY_PATH=/opt/client/lib:$LD_LIBRARY_PATH
./client
注意:这种方法只在当前终端窗口有效,关闭窗口后就失效了。
方法 2:永久解决(推荐) ------ 编译时指定 rpath
如果你有这个程序的源码并负责编译它,最好的做法是在编译时(例如在 Qt 的 .pro 文件中)指定 rpath(运行路径)。
在你的 .pro 文件 中加入以下代码:
bash
# 让程序在运行时自动去程序所在目录的 "../lib" 目录找库
QMAKE_LFLAGS += -Wl,-rpath,\'\$\$ORIGIN/../lib\'
方法3:bash脚本启动可执行文件,而不是直接启动
bash
#!/bin/bash
# 获取当前脚本所在的绝对路径
SH_DIR=$(cd "$(dirname "$0")"; pwd)
# 把上一级 lib 目录临时加入系统搜索路径
export LD_LIBRARY_PATH=$SH_DIR/../lib:$LD_LIBRARY_PATH
# 启动真正的程序
exec $SH_DIR/client "$@"
方法4:复制库到lib目录
这是解决"找不到库"最直接、最粗暴的方法。 当系统在自己的默认"地盘"找不到这个库时,你直接把库丢到它的地盘里,最适合存放第三方库的系统文件夹是 /usr/lib/ 或 /usr/local/lib/。
具体操作步骤
请在终端中执行以下命令(需要管理员权限):
第一步:复制文件到系统目录
将你打包好的库文件复制到 /usr/lib/ 目录下Bash
bash
sudo cp /opt/client/lib/libcrypto++.so.6 /usr/lib/
第二步:刷新系统动态库缓存(至关重要!)
注意: Linux 系统为了提高找库的效率,并不是每次运行程序都去遍历一遍文件夹,而是读取一个叫 ld.so.cache 的缓存文件。所以复制进去后,你必须让系统刷新一下缓存:
sudo ldconfig
第三步:验证与运行
现在你可以回到你的 bin 目录下,直接运行你的程序了:
bash
cd /opt/client/bin
./client
⚠️ 这样做有什么隐患吗?(老鸟的温馨提示)
虽然这个方法能立马解决你当下的问题,但在实际生产或软件发布中,一般不推荐这么做,原因有两点:
-
污染系统环境 :如果每个闭源软件都往
/usr/lib里扔自己的库,时间久了系统文件夹会变得非常混乱。 -
版本冲突(覆盖风险) :假设以后你通过系统自带的软件源安装了另一个也依赖
libcrypto++的官方软件,系统可能会下载一个官方的libcrypto++.so.6并直接覆盖掉你刚才复制进去的这个文件。如果两个版本不兼容,你的软件或者系统的软件就会有一个死掉。 -
不利于移植 :如果这套软件要部署到客户的 100 台电脑上,你就必须在 100 台电脑上都执行一次复制和
ldconfig命令,无法做到"解压即用"。