☰
麒麟ARM系统离线安装Qt环境实战:依赖分析与部署指南
2026/9/28 18:12:57 网站建设 项目流程

1. 为什么要在麒麟ARM系统上折腾离线Qt环境

如果你正在读这篇文章,大概率是遇到了这样一个场景:手头有一台搭载麒麟操作系统的ARM架构机器,可能是飞腾、鲲鹏或者麒麟芯片的终端,这台机器处在内网环境里,没有外网连接,但你需要在上面跑一个基于Qt的图形界面程序。这时候你会发现,平时在x86架构的Ubuntu上一条apt install qt5-default就能搞定的事情,到了这里完全行不通——没有网络,没有现成的ARM架构Qt二进制包,甚至连编译工具链都得自己想办法搬进去。

我自己第一次遇到这个需求的时候,是在一个国产化替代的项目现场。客户给了一台银河麒麟V10的ARM机器,要求在上面部署一套Qt开发的监控界面。当时我天真地以为,不就是装个Qt嘛,能有多难。结果从下午两点折腾到晚上十一点,中间踩了无数坑,才终于把环境跑通。这篇文章就是把我那天的经验完整地梳理出来,从依赖包的下载、传输、安装,到编译配置、环境变量设置,再到各种稀奇古怪的报错处理,全部讲清楚。

麒麟ARM系统离线安装Qt环境这件事,核心难点其实不在Qt本身,而在于三个字:依赖链。ARM架构的软件包生态远不如x86丰富,很多在x86上理所当然存在的库,在ARM上要么版本不对,要么根本没有预编译包。再加上麒麟系统基于国产化的需求做了一些定制,包管理器的源配置、系统库的路径都可能和标准Linux发行版有差异。所以整个安装过程更像是在做一道精密的外科手术,每一步都得小心翼翼。

这篇文章适合谁看?如果你是有一定Linux基础,需要在国产化平台上做Qt开发的工程师,那这篇内容可以直接拿来当操作手册用。如果你是对ARM架构交叉编译感兴趣的技术爱好者,里面关于依赖分析和工具链配置的思路同样有参考价值。即使你之前没接触过麒麟系统,只要跟着步骤走,也能把环境搭起来。

注意:本文所有操作均基于合法合规的软件开发场景,涉及的软件包均来自官方或开源渠道。请确保你的使用场景符合相关软件许可协议。

2. 动手之前:环境确认与整体方案设计

2.1 先搞清楚你的机器到底缺什么

在开始下载任何东西之前,有一件事必须先做:确认目标机器的系统版本、架构和已有的库。这一步看起来简单,但我见过太多人跳过这步,结果下载了一堆不匹配的包,白白浪费时间。

登录到麒麟系统上,打开终端,依次执行下面几条命令:

# 查看系统版本信息 cat /etc/os-release # 查看内核版本和架构 uname -a # 查看CPU架构详情 lscpu | grep -E "Architecture|Model name" # 查看已安装的Qt相关包 dpkg -l | grep -i qt # 查看系统已安装的图形库依赖 ldconfig -p | grep -E "libGL|libX11|libxcb"

以银河麒麟V10为例,典型的输出会显示aarch64架构,系统基于Debian体系,使用dpkg和apt作为包管理工具。这一点很关键,因为它决定了你后续下载依赖包时应该找.deb格式的文件,而不是.rpm。

我当时的机器上已经预装了一些Qt5的运行库,版本是5.12.8,但开发环境(头文件、qmake、编译工具)完全没有。这就意味着我需要额外安装qtbase5-dev、qt5-qmake、qtcreator等开发包。如果你的机器上连运行库都没有,那需要安装的包会更多。

2.2 离线安装的整体思路

离线安装Qt环境,本质上就是解决一个“搬运”问题:把原本需要从网络仓库下载的软件包,提前在另一台有网络的机器上下载好,然后通过U盘或内网传输到目标机器上安装。

整个流程可以拆成四个阶段:

第一阶段:依赖分析。在目标机器上确定需要哪些包,包括Qt的核心库、开发工具、编译器等。这一步的关键是搞清楚包与包之间的依赖关系,因为离线安装时apt无法自动解决依赖,缺一个包就会导致安装失败。

第二阶段:包下载。在一台有网络的、架构相同的机器上下载所有需要的.deb包。这里有个坑:下载机的架构必须和目标机一致,都是ARM64。如果你在x86机器上下载ARM的包,需要用apt-get download配合正确的源,或者直接用wget从镜像站拉取。

第三阶段:传输与安装。把下载好的包传到目标机器,用dpkg -i批量安装。安装顺序很重要,被依赖的包要先装。

第四阶段:环境配置与验证。设置PATH、LD_LIBRARY_PATH等环境变量,编译一个测试程序验证环境是否可用。

2.3 方案选型:为什么选择系统包而非源码编译

在离线环境下安装Qt,其实有两条路可走:一是下载系统包(.deb)安装,二是下载Qt源码在目标机器上编译。我两种方式都试过,最终推荐系统包方案,原因如下。

源码编译Qt在ARM机器上非常耗时。我试过在一台飞腾FT-2000/4的机器上编译Qt 5.15.2,完整编译花了将近四个小时,而且中间因为缺少各种开发库(比如libxcb-xinerama0-dev、libfontconfig1-dev)反复中断。更麻烦的是,编译过程中如果缺少某个可选依赖,Qt会自动跳过对应的模块,导致最终编译出来的Qt功能不全,比如缺少serialport模块或者sqlite驱动。

系统包方案的优势在于:包的依赖关系已经被维护者处理好了,你只需要按顺序安装即可;安装速度快,通常几分钟就能搞定;版本经过发行版测试,稳定性有保障。缺点是有时候系统源里的Qt版本比较老,比如麒麟V10默认源里是Qt 5.12.8,如果你需要Qt 5.15的新特性,可能得另想办法。

实操心得:如果你的项目对Qt版本没有硬性要求,优先用系统包。如果确实需要特定版本,可以考虑在x86机器上交叉编译Qt,然后把编译好的库和工具链整体搬到ARM机器上。交叉编译的环境配置我会在后面的章节详细讲。

3. 依赖包下载:在联网机器上把东西备齐

3.1 准备一台同架构的联网机器

下载ARM64的.deb包,最省事的办法是找一台同样运行麒麟系统的ARM机器,并且这台机器能连外网。如果手头没有这样的机器,退而求其次,可以用一台ARM架构的服务器装个Ubuntu,只要架构是aarch64就行,因为.deb包本身是架构相关的,但发行版之间的包通常可以通用(前提是glibc版本兼容)。

如果连ARM机器都没有,那就只能在一台x86机器上通过apt-get download配合--arch参数来下载ARM包。具体做法是修改/etc/apt/sources.list,添加ARM64的源,然后执行:

# 在x86机器上下载ARM64架构的包 apt-get download qtbase5-dev:arm64

不过这种方式有时候会因为依赖解析的问题失败,不如直接在ARM机器上操作来得稳妥。

3.2 用apt-rdepends分析完整依赖树

确定需要哪些包,最可靠的方法是使用apt-rdepends工具。这个工具可以递归地列出一个包的所有依赖。在联网的ARM机器上执行:

# 安装apt-rdepends工具 sudo apt install apt-rdepends # 分析qtbase5-dev的完整依赖树 apt-rdepends qtbase5-dev | grep -v "^ " | sort -u > qt_deps_list.txt

这样得到的qt_deps_list.txt文件里包含了所有需要的包名。但要注意,这里面有些包是系统已经预装的,不需要重复下载。你可以在目标麒麟机器上执行dpkg -l导出已安装包列表,然后做差集运算,筛选出真正需要下载的包。

我当时的做法更直接一些:先在目标机器上尝试安装,看apt报缺哪些包,然后把这些包名记下来,到联网机器上下载。虽然笨了点,但很有效。具体操作是在目标机器上执行:

# 模拟安装,查看缺失的依赖 sudo apt install --simulate qtbase5-dev qt5-qmake qtcreator

--simulate参数会让apt只做模拟,不实际安装,但会输出所有需要下载的包。把输出里的包名提取出来,就是你的下载清单。

3.3 批量下载deb包的脚本

手动一个个下载太慢,写个脚本批量处理。在联网的ARM机器上,把包名列表存到pkg_list.txt里,每行一个包名,然后执行:

#!/bin/bash # download_debs.sh # 批量下载deb包及其依赖 DOWNLOAD_DIR="./qt_offline_packages" mkdir -p "$DOWNLOAD_DIR" cd "$DOWNLOAD_DIR" while read -r pkg; do echo "正在下载: $pkg" apt-get download "$pkg" 2>&1 | tee -a download.log done < ../pkg_list.txt echo "下载完成,共下载 $(ls -1 *.deb | wc -l) 个包"

这个脚本会把所有.deb文件下载到qt_offline_packages目录下。下载完成后,把这个目录整体拷贝到U盘或者通过内网传到目标机器上。

注意:apt-get download只下载指定的包本身,不会自动下载依赖。所以你的pkg_list.txt必须包含所有依赖包。这就是为什么前面要用apt-rdepends或者--simulate来生成完整的包列表。

3.4 那些容易被遗漏的关键包

根据我的经验,下面这些包在离线安装Qt时最容易被漏掉,单独列出来提醒一下:

包名作用遗漏后果
libqt5core5aQt核心库所有Qt程序无法运行
libqt5gui5Qt GUI库图形界面无法显示
libqt5widgets5Qt Widgets模块窗口程序编译失败
libqt5serialport5串口模块串口通信功能不可用
qtbase5-devQt基础开发头文件无法编译Qt程序
qt5-qmakeqmake构建工具无法生成Makefile
libqt5sql5-sqliteSQLite数据库驱动数据库功能报错
libxcb-xinerama0XCB扩展库Qt程序启动时报xcb错误
libfontconfig1字体配置库界面字体显示异常
libgl1-mesa-devOpenGL开发库需要OpenGL的程序编译失败

特别是libxcb-xinerama0这个包,我在三个不同的项目现场都遇到过它缺失导致Qt程序无法启动的问题。报错信息通常是qt.qpa.plugin: Could not load the Qt platform plugin "xcb",看起来像是Qt插件的问题,实际上根源是系统缺少XCB的某个扩展库。

4. 离线安装实操:从dpkg到环境变量

4.1 批量安装deb包的正确姿势

把下载好的包传到目标机器后,进入包所在目录,执行批量安装。这里有个技巧:直接用dpkg -i *.deb可能会因为安装顺序问题报依赖错误,更好的做法是用dpkg的--force-depends参数先强制安装所有包,然后再用apt install -f修复依赖关系。

# 进入包目录 cd /path/to/qt_offline_packages # 批量安装所有deb包 sudo dpkg -i --force-depends *.deb # 修复可能的依赖问题 sudo apt install -f # 如果apt install -f因为离线无法工作,手动按依赖顺序重新安装 # 通常的顺序是:基础库 -> 核心库 -> 开发工具

如果apt install -f因为离线环境无法下载缺失的包而失败,那就需要手动处理。先用dpkg -l | grep -v "^ii"查看哪些包处于非正常安装状态,然后根据报错信息逐个安装缺失的依赖。

我自己的习惯是先把所有包按名称排序,然后分批安装:先装libqt5core5a、libqt5gui5这类基础库,再装qtbase5-dev这类开发包,最后装qtcreator这类工具。这样虽然麻烦一点,但成功率更高。

4.2 验证Qt是否安装成功

安装完成后,用几个简单的命令验证:

# 查看qmake版本 qmake --version # 查看Qt库文件位置 ls /usr/lib/aarch64-linux-gnu/libQt5Core.so* # 查看Qt插件目录 ls /usr/lib/aarch64-linux-gnu/qt5/plugins/ # 查看已安装的Qt模块 ls /usr/lib/aarch64-linux-gnu/qt5/mkspecs/modules/

如果qmake --version能正常输出版本信息,说明Qt的基本环境已经就绪。如果提示qmake: command not found,那可能是qt5-qmake包没有安装成功,或者qmake的可执行文件不在PATH里。可以用dpkg -L qt5-qmake | grep qmake找到它的实际位置。

4.3 环境变量配置:让Qt工具链随手可用

系统包安装的Qt,qmake通常位于/usr/bin/qmake或者/usr/lib/qt5/bin/qmake。如果不在PATH里,需要手动添加。编辑~/.bashrc或者/etc/profile,加入以下内容:

# Qt环境变量配置 export QT_DIR=/usr/lib/aarch64-linux-gnu/qt5 export PATH=$QT_DIR/bin:$PATH export LD_LIBRARY_PATH=$QT_DIR/lib:$LD_LIBRARY_PATH export QT_PLUGIN_PATH=$QT_DIR/plugins export QML2_IMPORT_PATH=$QT_DIR/qml

保存后执行source ~/.bashrc使配置生效。这里重点说一下LD_LIBRARY_PATH和QT_PLUGIN_PATH这两个变量。LD_LIBRARY_PATH告诉系统去哪里找Qt的动态库,如果设置不对,运行Qt程序时会报error while loading shared libraries: libQt5Core.so.5: cannot open shared object file。QT_PLUGIN_PATH告诉Qt去哪里找平台插件,如果设置不对,程序启动时会报This application failed to start because no Qt platform plugin could be initialized。

实操心得:有些麒麟系统上,/etc/ld.so.conf.d/目录下已经有Qt库的配置,这种情况下不需要额外设置LD_LIBRARY_PATH。可以用ldconfig -p | grep Qt5确认系统是否能找到Qt库。如果能找到,就不要重复设置,避免路径冲突。

4.4 编译一个测试程序验证环境

环境变量配好后,写一个最简单的Qt程序测试一下。创建一个test_qt.cpp文件:

#include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label("Qt on Kylin ARM works!"); label.show(); return app.exec(); }

然后创建一个test_qt.pro文件:

QT += widgets SOURCES += test_qt.cpp

执行编译:

qmake test_qt.pro make ./test_qt

如果弹出一个显示“Qt on Kylin ARM works!”的窗口,恭喜你,环境搭建成功。如果编译时报错,根据错误信息对照后面的问题排查章节处理。

5. 常见问题与排查技巧实录

5.1 Qt程序启动报xcb插件加载失败

这是离线安装Qt后最常见的问题,没有之一。报错信息通常是:

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.

这个问题的根源是系统缺少XCB相关的库。Qt的xcb平台插件依赖一系列XCB扩展库,包括libxcb-xinerama0、libxcb-icccm4、libxcb-image0、libxcb-keysyms1、libxcb-randr0、libxcb-render-util0、libxcb-shape0、libxcb-xkb1、libxkbcommon-x11-0等。在离线环境下,这些库可能没有随Qt一起安装。

排查方法是先用ldd查看xcb插件的依赖:

ldd /usr/lib/aarch64-linux-gnu/qt5/plugins/platforms/libqxcb.so | grep "not found"

输出中所有显示not found的库就是缺失的。把这些库名记下来,到联网机器上下载对应的.deb包,传到目标机器安装即可。

5.2 编译时报“Unknown module(s) in QT: serialport”

这个报错说明你的Qt环境里没有安装serialport模块。在离线环境下,serialport模块需要单独安装libqt5serialport5-dev包。这个包不在qtbase5-dev的依赖列表里,很容易被遗漏。

解决方法是在联网机器上下载libqt5serialport5-dev和libqt5serialport5两个包,传到目标机器安装。安装完成后,用ls /usr/lib/aarch64-linux-gnu/qt5/mkspecs/modules/ | grep serialport确认模块是否注册成功。

类似的模块缺失问题还可能出现在sql、multimedia、websockets等模块上。排查方法是一样的:在.pro文件里用到的QT += xxx,对应的模块必须有对应的-dev包安装。

5.3 qmake生成的Makefile里路径不对

有时候qmake生成的Makefile里引用的头文件路径或者库路径是错的,导致make时报“找不到头文件”或者“找不到库”。这种情况通常是因为系统里存在多个Qt版本,qmake指向了错误的那个。

用which qmake和qmake -query查看当前qmake的实际路径和配置信息。如果发现qmake指向的不是你期望的版本,可以通过修改PATH环境变量的顺序来切换,或者直接用绝对路径调用正确的qmake。

# 查看qmake的详细配置 qmake -query # 如果系统有多个qmake,用绝对路径指定 /usr/lib/aarch64-linux-gnu/qt5/bin/qmake test_qt.pro

5.4 常见问题速查表

问题现象可能原因解决方法
qmake: command not foundqt5-qmake未安装或不在PATH安装qt5-qmake,添加PATH
无法加载xcb插件缺少XCB扩展库安装libxcb-xinerama0等库
Unknown module serialport缺少serialport开发包安装libqt5serialport5-dev
找不到libQt5Core.so.5LD_LIBRARY_PATH未设置设置LD_LIBRARY_PATH或运行ldconfig
编译时找不到QApplication头文件qtbase5-dev未安装安装qtbase5-dev
程序运行字体显示为方块缺少中文字体安装fonts-wqy-zenhei等字体包
make报错“cannot find -lGL”缺少OpenGL开发库安装libgl1-mesa-dev
Qt Creator无法启动缺少依赖库用ldd检查并补齐依赖

5.5 几个容易踩的坑和独家技巧

第一个坑是包版本不匹配。麒麟V10的系统源里,Qt的版本是5.12.8,但如果你从Ubuntu的源里下载了5.15.2的包,安装后可能会出现库版本冲突。表现是程序能编译但运行时报symbol lookup error。解决方法是确保所有Qt相关的包都来自同一个源,版本号一致。

第二个坑是依赖包的依赖。你用apt-rdepends分析出来的依赖树,可能只覆盖了直接依赖和二级依赖,更深层的依赖可能被遗漏。我的做法是在目标机器上先装一遍,把所有报错信息收集起来,然后针对性地补充下载。虽然多花点时间,但能确保不漏包。

第三个技巧是用dpkg-deb -c查看包内容。有时候你不确定某个包是否已经安装,或者想确认某个文件属于哪个包,可以用这个命令:

# 查看deb包的内容列表 dpkg-deb -c package.deb # 查看某个已安装包的文件列表 dpkg -L package_name # 查看某个文件属于哪个包 dpkg -S /path/to/file

第四个技巧是保留一份完整的离线包仓库。把这次下载的所有.deb包整理好,按类别放到不同的目录里,下次再遇到类似需求时直接拿来用。我自己的离线包仓库里,Qt相关的包大概有80多个,覆盖了从Qt 5.9到5.15的多个版本,省去了很多重复下载的时间。

6. 进阶话题:交叉编译与自定义Qt版本

6.1 什么时候需要交叉编译

系统包方案虽然简单,但有两个局限:一是Qt版本受限于系统源,二是无法定制Qt的编译选项。如果你的项目需要Qt 5.15的新特性,或者需要裁剪Qt的功能以减小体积,那就得考虑交叉编译。

交叉编译的思路是在一台性能较强的x86机器上,用ARM交叉编译工具链编译Qt源码,生成ARM架构的库和工具,然后整体搬到目标机器上。这样做的好处是编译速度快(x86机器性能通常比ARM开发板强),而且可以完全控制编译选项。

6.2 交叉编译工具链的选择

ARM交叉编译工具链有几种选择:Linaro的gcc-linaro-aarch64-linux-gnu、ARM官方的arm compiler、以及各芯片厂商提供的定制工具链。对于麒麟系统,推荐使用Linaro的GCC工具链,兼容性最好。

下载工具链后,解压到/opt目录,然后把bin目录加入PATH:

export PATH=/opt/gcc-linaro-aarch64-linux-gnu/bin:$PATH export CROSS_COMPILE=aarch64-linux-gnu- export ARCH=arm64

验证工具链是否可用:

aarch64-linux-gnu-gcc --version

6.3 配置Qt的交叉编译选项

下载Qt源码后,进入源码目录,执行configure脚本。关键的配置参数包括:

./configure \ -prefix /opt/qt5-arm \ -opensource \ -confirm-license \ -release \ -xplatform linux-aarch64-gnu-g++ \ -no-opengl \ -no-xcb \ -qt-libjpeg \ -qt-libpng \ -qt-zlib \ -nomake examples \ -nomake tests \ -skip qtwebengine

这里重点解释几个参数:-xplatform指定目标平台的mkspec,需要根据你的工具链名称选择;-no-opengl和-no-xcb在无图形界面的嵌入式场景下可以去掉,但如果需要GUI就得保留;-skip qtwebengine跳过WebEngine模块的编译,因为这个模块编译极其耗时且依赖复杂。

配置完成后执行make -j$(nproc)开始编译。编译时间取决于机器性能,x86机器上通常1到2小时可以完成。

6.4 把交叉编译的Qt部署到目标机器

编译完成后,执行make install,Qt会被安装到-prefix指定的目录。把这个目录整体打包,传到目标机器上,然后设置环境变量指向这个目录:

export QT_DIR=/opt/qt5-arm export PATH=$QT_DIR/bin:$PATH export LD_LIBRARY_PATH=$QT_DIR/lib:$LD_LIBRARY_PATH export QT_PLUGIN_PATH=$QT_DIR/plugins

这种方式的优点是Qt版本和编译选项完全可控,缺点是需要自己处理所有依赖库的交叉编译。比如Qt的sqlite驱动依赖libsqlite3,你需要先用交叉工具链编译libsqlite3,再编译Qt的sqlite插件。依赖链越长,工作量越大。

实操心得:交叉编译Qt时,建议先用-no-opengl -no-xcb的最小配置编译一遍,确认工具链没问题,再逐步添加需要的模块。一次性开启所有模块,很容易因为某个依赖缺失导致配置失败,排查起来很麻烦。

7. 写在最后:一些个人体会

折腾麒麟ARM系统的离线Qt环境,最深的体会就是:准备工作比安装本身重要得多。我见过太多人拿到机器就开始装,装到一半发现缺包,然后又得回到联网机器上重新下载,来回折腾。如果一开始就花半小时把依赖分析清楚,把包下载齐全,后面的安装可能十分钟就搞定了。

另一个体会是,离线环境的包管理要有版本意识。麒麟系统的glibc版本、Qt版本、编译器版本之间是有对应关系的。比如麒麟V10 SP1的glibc是2.28,如果你下载的Qt包是在glibc 2.31环境下编译的,安装后可能会报GLIBC_2.31 not found。所以下载包的时候,尽量选择和目标系统版本接近的源。

最后分享一个我自己的习惯:每次做完离线部署,我都会把这次用到的所有包、配置文件、操作步骤整理成一个文档,存在项目的docs目录里。下次再遇到类似需求,直接翻文档就行,不用重新踩一遍坑。这个习惯帮我省下了大量重复劳动的时间,也推荐给你。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询