linux下的Qt打包常见原因分析和雷区,获取一键式打包脚本(能避免各种问题)

news2024/12/24 2:06:55

 目录

一. 大致如下常见问题:

(1)找不到程序所依赖的Qt库 version `Qt_5' not found (required by

(2)Could not Load the Qt platform plugin "xcb" in "" even though it was found

(3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentation fault,或者Illegal instruction (core dumped) 非法指令

(4)ldd 应用程序或者库,查看运行所依赖的库时,直接报段错误

二. 问题逐个分析,得出解决方法:

(1)找不到程序所依赖的Qt库 version `Qt_5' not found (required by

解决方案有如下几种

(2)Could not Load the Qt platform plugin "xcb" in "" even though it was found

 (3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentation fault,或者Illegal instruction (core dumped) 非法指令

 (4)这个问题,在上面已经解决了

最后:

用网上的命令打包QT程序运行时常遇到程序无法运行的提示:

一. 大致如下常见问题:

(1)找不到程序所依赖的Qt库 version `Qt_5' not found (required by

/usr/lib/x86_64-linux-gnu/libQt5Gui.so.5: version `Qt_5' not found (required by ./运行程序名)

(2)Could not Load the Qt platform plugin "xcb" in "" even though it was found

qt.qpa.plugin: Could not Load the Qt platform plugin "xcb" in "" even though it was found.

This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

在命令下执行:export QT_DEBUG_PLUGINS=1 ,让程序输出更多信息,再次运行

 提示platforms文件下的libqxcb.so库缺少依赖库libQt5XcbQpa.so.5

(3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentation fault,或者Illegal instruction (core dumped) 非法指令

(4)ldd 应用程序或者库,查看运行所依赖的库时,直接报段错误

二. 问题逐个分析,得出解决方法:

(1)找不到程序所依赖的Qt库 version `Qt_5' not found (required by

        /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5: version `Qt_5' not found (required by ./运行程序名)

这个是找不到程序依赖库了,在没有安装Qt的裸机下,如果程序没有指定依赖库路径的话,默认是去 /etc/ld.so.conf 文件中指定的搜索路径寻找

如果在有开发环境的机子上运行上的话,无论你把程序拿到哪个地方,都能运行,因为运行时会去Qt库里面找,如下所示

 去新机子上运行,是没有Qt库的,所以需要打包指定程序运行时库依赖的位置

问题分析完了,解决方案也就出来了

解决方案有如下几种

        1.在程序编译时,先在.pro文件下指定程序运行时的库依赖路径(推荐)

        2.在/etc/ld.so.conf 文件添加程序依赖路径,如下所示,不要将第一个默认的删掉或者改了,否者系统将出大问题,基本什么东西都运行不了(不推荐)

 3.指定临时运行路径,只在当前窗口下有用,这个也是网上常用的方法,然后在运行程序

export LD_LIBRARY_PATH='你的库路径':$LD_LIBRARY_PATH

我比较喜欢用第一种方法,简单明了

(2)Could not Load the Qt platform plugin "xcb" in "" even though it was found

        执行:export QT_DEBUG_PLUGINS=1 , 在运行,提示找不到platforms文件下的libqxcb.so库缺少依赖库libQt5XcbQpa.so.5,如果没有这个库就链接下

        如果我们已经有这个库了,但还是提示的话,说明能找的地方都找了(指定的库位置,/etc/ld.so.conf 文件中指定的位置,临时指定的库位置等等),还是找不到。这个时候就得看一下platforms文件下的libqxcb.so库所运行时所依赖的Qt库路径在哪里

readelf -d 库名称

readelf -d 库名/程序名  可以查看默认依赖/运行库路径:Runpath

         可以看到,libqxcb.so库的运行依赖路径是在库所在目录的上级的上级的lib目录下目录:Library runpath: [$ORIGIN/../../lib]

         在Qt中,因为这个库libqxcb.so是Qt自带的,已经开发好的,指定的库依赖位置就是[$ORIGIN/../../lib],所以我们也能看到,在QT下安装目录下,Qt库目录lib目录就是在库libqxcb.so的上级目录的上级目录的位置

         所以只要把QT库放在libqxcb.so库所在目录的上级的上级的lib目录下就可以了,也就是platforms文件夹的上一级目录的lib目录下。打包的一般目录结构都是bin目录相同目录下放lib库目录,bin目录下放程序文件,这也是很多软件发布时的标准配置。

 这样子就没问题啦 

 (3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentation fault,或者Illegal instruction (core dumped) 非法指令

        如我将ubantu16.04下Qt打包的程序,在裸机的ubantu16.04或者18.04下运行没有,没有问题,但放到ubantu22.04下,直接报Illegal instruction (core dumped) 非法指令,

或者其他linux系统下,如deepin(深度系统)下,提示段错误

这个错误我搞了半天,ldd程序,程序所有的依赖库都有,为啥还报错呢,搞不懂

想去lib目录下看下库信息,输入ls -l,结果直接报错,很多常用的linux命令在这里都报这个错

         思考原因,对比了一下其他能正常运行的程序,发现lib目录下很多其他的库文件,我把那些多余的文件都删除了,结果可以输linux命令了,而且程序也能运行了,然后我在我的尝试下,发现就是这些文件搞的鬼,libbc.so.6和libpthread.so.0

 然后就去查了这些库是干嘛的,一查,所有迷雾都揭开了,如下

libc.so.6是glibc的软链接

        #glibc是GNU发布的libc库,即c运行库。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。glibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。由于 glibc 囊括了几乎所有的 UNIX 通行的标准,可以想见其内容包罗万象。而就像其他的 UNIX 系统一样,其内含的档案群分散于系统的树状目录结构中,像一个支架一般撑起整个操作系统。在 GNU/Linux 系统中,其C函式库发展史点出了GNU/Linux 演进的几个重要里程碑,用 glibc 作为系统的C函式库,是GNU/Linux演进的一个重要里程碑。--百度百科

所以这个软链接很重要!!

        不同的linux系统下,这个libc.so.6库是不一样的,相同的系统下,也可能因为系统的升级,libc.so.6库也就行了的升级,如ubantu16.04和ubantu 22.04的libc.so.6库是不一样的。

        这也就解释了为什么在从ubantu16.04打包过来的库,在ubantu 22.04或者其他linux系统下,在这个库目录执行linux的常用命令,直接报这个Illegal instruction (core dumped) 非法指令的信息,因为本就不是这个系统的。无法识别!

        libc 和 libpthread是linux非常重要的基础库。所以在所在目录下执行命令,最先寻找的就是当前目录下的库和文件。本系统的直接跳过了,不报错误才怪!

所以把他们删掉就可以了

 (4)这个问题,在上面已经解决了

        既然会出现上面这些问题,那不能避免吗,毕竟我们打包的程序,不可能只在相同版本的系统上运行,可能会拿到低或者高版本的系统,甚至其他linux系统下运行,大概率会踩雷

        要解决这个问题,就要知道出现问题的根源所在,根源就是,库的问题。库从哪里来呢?都是网上执行这个命令后打包拷过去的。所以我们先理解这个打包命令的含义:

第四行那个,拷贝的命令

ldd $exe | awk '{if (match($3,"/")){ printf("%s "),$3 } }' 

        这个命令:ldd $exe 就是获取程序所依赖的库,然后通过管道|输入给awk命令处理,获取字符串中匹配有/的字符串,然后通过空格隔开,获取第三列,也就是程序所依赖库的路径

         然后将所有的库全部拷贝过去,其实很多库都不需要用到,有的/lib/...开头的路径的库是不需要的,这个是linux系统自带的,全部拷过去,会拷个雷库(如libc.so.6)过去,需要拷贝的只有Qt目录下的库文件而已,所以        要对这个拷贝命令就行优化

        所依赖的QT库有一个共同点,都有Qt这两个子眼,所以在那个基础上在过滤一下就行啦

#赋值路径,准备拷贝
copyPathList=$(ldd $exe | awk  -F " " \
'
{
    if ($3 ~ "/Qt")
    { 
		 printf("%s\n"),$3
    }
}
')

最后:

写这篇博客,花了很多时间,都花这个份上了,我就把所有的打包的原创脚本代码都写出来了,想要的自己拿吧,脚本式打包,链接啥的,都给弄好了,贴心,注释都写好了,不会改的,在评论区留言吧,或者评论区交流下。对你有用的点个赞在走吧

一键打包代码,拿走

#!/bin/sh
exe="RFIDReaderTest" #要打包的程序名 *
#获取当前路径
currentPath=$(cd `dirname $0`; pwd)

#打包的Qt库位置 *
packDes="$currentPath/../lib" 
#程序依赖库所在位置,用于打包依赖库需要的Qt库,没有留空即可,即myLibPath=""  *
myLibPath="$currentPath/myLib"
#删除原有文件夹,新建新文件夹,存储Qt库
rm -r $packDes
mkdir $packDes

#----------获取程序所依赖的‘Qt库’路径--------------
echo "------------正在获取程序所依赖的‘Qt库’--------------"
#输出程序所依赖的Qt库
ldd $exe | awk  -F " " \
'
{
    if ($3 ~ "/Qt")
    { 
		 printf("%s\n"),$3
    }
}
'
#赋值路径,准备拷贝
copyPathList=$(ldd $exe | awk  -F " " \
'
{
    if ($3 ~ "/Qt")
    { 
		 printf("%s\n"),$3
    }
}
')

#拷贝‘Qt库’文件到打包文件夹路径中
cp $copyPathList $packDes

echo "---正在打包libQt5XcbQpa.so.*.0和libQt5DBus.so.*.0库......"

#获取依赖库中第一个库完整的路径
libPath=$(echo $copyPathList | awk -F " " '{printf("%s\n"),$1}')
#获取Qt版本号
sonPath1=$(echo $libPath | awk -F "/lib" '{printf("%s\n"),$1}')
sonPath2=$(echo $sonPath1 | awk -F "/" '{printf("%s\n"),$NF}')
sonPath3=$(echo $sonPath1 | awk -F "/$sonPath2" '{printf("%s\n"),$1}')
QtVersion=$(echo $sonPath3 | awk -F "/" '{printf("%s\n"),$NF}')
echo "当前Qt版本号为:"$QtVersion


cd $currentPath

#打包Qt插件platforms文件夹
echo "---打包Qt插件platforms文件夹......"
#分解拼接插件platforms路径
platformsPath=$(echo $libPath | awk -F "/lib/" '{printf("%s\n"),$1}')"/plugins/platforms"
echo "---platformsPath路径:"$platformsPath
#将platforms文件拷贝到程序所在路径
cp -r $platformsPath $currentPath

#分解拼接指定库路径
Qt5XcbCopyPath=$(echo $libPath | awk -F "/lib/" '{printf("%s\n"),$1}')"/lib/libQt5XcbQpa.so.$QtVersion"
Qt5DBusCopyPath=$(echo $libPath | awk -F "/lib/" '{printf("%s\n"),$1}')"/lib/libQt5DBus.so.$QtVersion"

echo "Qt5XcbCopyPath:"$Qt5XcbCopyPath
echo "Qt5DBusCopyPath:"$Qt5DBusCopyPath

#拷贝libQt5XcbQpa.so.$QtVersion和libQt5DBus.so.$QtVersion库
cp $Qt5XcbCopyPath $packDes
cp $Qt5DBusCopyPath $packDes

#软链接
echo "------- 软链接正在打包libQt5XcbQpa.so.*和libQt5DBus.so.*  --------"
cd $packDes

Qt5XcblnPath=$(echo libQt5XcbQpa.so.*.0)
Qt5DBuslnPath=$(echo libQt5DBus.so.*.0)

libName1=$(echo $QtVersion | awk -F "." '{printf("%s\n"),$1}')
libName2=$(echo $QtVersion | awk -F "." '{printf("%s\n"),$2}')

ln -s $Qt5XcblnPath  $packDes/libQt5XcbQpa.so
ln -s $Qt5XcblnPath  $packDes/libQt5XcbQpa.so.$libName1
ln -s $Qt5XcblnPath  $packDes/libQt5XcbQpa.so.$libName1.$libName2

ln -s $Qt5DBuslnPath $packDes/libQt5DBus.so
ln -s $Qt5DBuslnPath $packDes/libQt5DBus.so.$libName1
ln -s $Qt5DBuslnPath $packDes/libQt5DBus.so.$libName1.$libName2

#打包自己的库所依赖的QT库
if [ ! -d "$myLibPath" ]; then
    echo "$myLibPath no exist"
    echo "-----------'$exe'所依赖的Qt库打包完成!-----------"
    exit 1 #没有依赖自己写的库,直接结束
fi


echo "------------正在获取自己写的库所依赖的QT库--------------"
for filePath in $myLibPath/*.so
do

	echo "myLib:"$filePath
	#赋值路径,准备拷贝	
	copyPathList=$(ldd $filePath | awk -F " " \
	'
	{
	    if ($3 ~ "/Qt")
	    { 
		printf("%s\n"),$3
	    }
	}
	')
	for file in $copyPathList
	do
	    name=$(echo $file | awk -F "/lib/" '{ print $2}')
	    if [ ! -f "$packDes/$name" ];then
		echo "copy file:"$file
		#拷贝‘Qt库’文件到打包文件夹路径中
		cp $file $packDes
	    fi		    	    
	done
done 

echo "-----------所依赖的Qt库全部打包完成!-----------"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/508661.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

64/32位Linux系统的地址空间布局对比分析

Ubuntu从17.10开始不再官方支持32位(i386)架构(严格的说是从18.04开始的,因为17.10不支持32位的PC版,但是支持32位的SERVER版,但是偶数稳定版确实是从18.04开始的),只支持64位(amd64)架构,这是因为随着时间…

为什么ChatGPT用强化学习而非监督学习?

为什么ChatGPT非得用强化学习,而不直接用监督学习?原因不是那么显而易见。在上周发布的《John Schulman:通往TruthGPT之路》一文中,OpenAI联合创始人、ChatGPT主要负责人John Schulman分享了OpenAI在人类反馈的强化学习&#xff0…

去阿里面试,面试前20分钟突然要求候选人展示过去的工作方案,候选人拒绝后,竟被取消面试!...

离职时,你会把自己的工作成果拷贝下来留档吗? 一位网友说: 面试阿里,面试前20分钟,面试官突然要求他展示过去的工作成果,因为之前是用公司电脑,离职时把电脑交上去了,没有任何留档&a…

AE(自动编码器)与VAE(变分自动编码器)的区别和联系?

他们各自的概念看以下链接就可以了:https://blog.csdn.net/weixin_43135178/category_11543123.html 这里主要谈一下他们的区别? 先说结论: VAE是AE的升级版,VAE也可以被看作是一种特殊的AEAE主要用于数据的压缩与还原&#xff0…

redisson中的分布式锁解读

概述 Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅 提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue,…

【电机应用控制】——FOC基础理论针对无刷电机360°无死角磁场矢量控制

目录 前言 一、FOC简介 1、概述 2、框图详解 二、FOC控制核心—坐标变换 1、CLARKE变换 2、PARK变换&反变换 三、FOC闭环回路 四、SVPWM解析 总结 前言 声明:学习笔记来自正点原子B站教程,根据自己理解进行精简总结,仅供学习…

『python爬虫』16. 多线程与多进程(保姆级图文)

目录 多线程1. 什么是多线程?2. 串行模式3. 多线程3.1 多线程方法写法3.2 多线程方法带参数3.3 多线程类写法 多进程1. 什么是多进程 欢迎关注 『python爬虫』 专栏,持续更新中 欢迎关注 『python爬虫』 专栏,持续更新中 多线程 1. 什么是多…

优化Docker Compose日志输出,加速容器化应用的轻松部署

摘要: 在使用 Docker Compose 部署容器化应用程序时,优化日志输出对于提升效率和管理便利性至关重要。本文将介绍如何优化 Docker Compose 日志输出,以加速容器化应用的轻松部署过程。 优化操作 当我们使用 Docker Compose 部署容器化应用程…

【Queue新技法】用双数组实现一个队列 C++

目录 1 常规的队列构建2 加入一些限制2-1形式化说明 附录0 双数组或双链表实现队列1 单链表与循环缓冲区实现队列3 参考资料 1 常规的队列构建 到火车站办理退票,排队的人构成队列。注意到有两个关键动作: 入队,即自觉站到队伍的末尾。出队&…

一篇文章搞定《ViewPage2离屏加载》

------《ViewPage2离屏加载》 前言离屏加载是什么OffscreenPageLimit设置OffscreenPageLimit表现OffscreenPageLimit值为1OffscreenPageLimit值为3 OffscreenPageLimit值取多大比较合适 前言 这里就不讲ViewPage了,买新不买旧,用新不用旧。 但是会将Vie…

Power BI: 表格显示切片器选中时间之前的数据

例如下面的例子,Year List表和Caleadar表是1对多的关联关系。 Caleadar表: Caleadar VAR StartYear YEAR(NOW())-5 VAR EndYear YEAR(NOW())5 RETURN ADDCOLUMNS (CALENDAR (DATE(StartYear,1,1), DATE(EndYear,12,31)),"Year", YEAR ([…

【设计模式】| 修炼内功 | 23种设计模式——工厂方法模式(含抽象)

设计模式如同织锦之艺术,精心构筑,展示优美。 学习设计模式,犹如追逐清晨的曙光,扉页掀开了人生的新篇章。当你学会设计模式的奥秘,就如同走进了灯火通明的城市,丰富多彩的建筑,让你大开眼界&am…

30个最常用的空间SQL用例

在开始使用空间 SQL 时,至少对我而言,最大的挑战之一是拥有一个快速简便的参考,以将你当前的 GIS 工作流转换为 SQL。 有许多令人惊叹的资源可以扩展这方面的知识,但本指南旨在成为一本真正简单的食谱,以开始将你当前的…

从零开始的强化学习入门学习路线

强化学习是机器学习领域中的一个分支,它是指智能体通过与环境的交互来学习如何采取最佳行动以最大化奖励信号的过程。强化学习在许多领域都有广泛的应用,如游戏、自动驾驶和机器人控制等。如果你对强化学习感兴趣,下面是一个入门强化学习的学…

SequoiaDB分布式数据库2023.4月刊

本月看点速览 赋能产业升级,荣获新睿之星 聚焦金融,进一步探索非结构化数据价值释放 再获肯定,入选2023年中国最佳信创厂商入围名单 青杉计划2023已开启,一起攀登更高的“杉” 赋能产业升级,荣获新睿之星 4月18日…

PyTorch典型函数之gather

PyTorch典型函数之gather 作用描述函数详解典型应用场景(1) 深度强化学习中计算损失函数 参考链接 作用描述 如上图所示,假如我们有一个Tensor A(图左),要从A中提取一部分元素组成Tensor B(图右)&#xff0…

7.外观模式C++用法示例

外观模式 一.外观模式1.原理2.特点3.外观模式与装饰器模式的异同4.应用场景C程序示例 一.外观模式 外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个简单的接口,隐藏了一个或多个复杂的子系统的复杂性,并使…

图嵌入表示学习—Node Embeddings随机游走

Random Walk Approaches for Node Embeddings 一、随机游走基本概念 想象一个醉汉在图中随机的行走,其中走过的节点路径就是一个随机游走序列。 随机行走可以采取不同的策略,如行走的方向、每次行走的长度等。 二、图机器学习与NLP的关系 从图与NLP的…

posix线程的优先级测试

如果创建的线程不够多&#xff0c;有些问题是体现不出来的。 优先级打印&#xff1a; 测试目的&#xff1a;输出三种调度模式下的最大优先级和最小优先级 #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <fcntl.h> #…

Kubernetes_容器网络_01_Docker网络原理(二)

文章目录 一、前言二、被隔离的Docker容器三、网桥Bridge四、VethPair网络对五、统一宿主机上的两个Container容器通信六、宿主机访问其上的容器七、宿主机上的容器访问另一个宿主机八、尾声 一、前言 二、被隔离的Docker容器 Linux 网络&#xff0c;就包括&#xff1a;网卡&…