银河麒麟V10 ARM离线安装Qt5开发环境:从gcc到QtCreator全记录

发布时间:2026/9/25 8:16:52
银河麒麟V10 ARM离线安装Qt5开发环境:从gcc到QtCreator全记录 正干着活儿突然被塞来一台银河麒麟V10 ARM版机器还得在完全离线的情况下把Qt5开发环境搭起来这种场景我现在已经不太慌了——不是第一次踩了。可头一回遇到时我真是被结结实实上了一课。网上搜到的教程十有八九是x86 Ubuntu、apt在线安装、Qt官方离线包直接双击运行到了ARM麒麟这边全都对不上号。操作系统版本、CPU架构、包管理方式、glibc版本、QtCreator的Kit配置任何一个环节掉了链子后面的路就全堵死。这篇文章是我几轮折腾下来的完整记录从gcc到QtCreator把离线安装会踩的坑摊开讲。适合三类人看正在信创环境里做项目交付的、要给离线ARM设备搭开发环境的、以及在麒麟系统上被Qt各种诡异问题折磨的。我尽量把每一步的命令和判断依据写清楚你在自己环境里照着敲就行。1. 装之前先摸清系统底细架构、版本、包管理器1.1 别把x86的安装经验直接搬过来ARM版银河麒麟和普通x86 Ubuntu看起来都是Linux但软件包完全不通。很多人犯的第一个错误就是看到 .deb 就以为能直接装结果下载出来的包是 amd64 的安装时直接报cannot execute binary file或者干脆提示包架构不匹配。银河麒麟V10实际有两条分支一条走dpkg/apt体系另一条走rpm/yum体系。两者的安装命令、依赖管理逻辑完全不同。所以开干前必须先搞清楚目标机到底属于哪一边再决定后面的策略。我在文中以deb系为例因为目前遇到的银河麒麟V10桌面版大多是deb系命令也更贴近普通开发者习惯。1.2 用几个命令确认系统真实状态拿到机器后先不要急着找安装包把下面这几个命令挨个跑一遍cat /etc/os-release uname -m lscpu | grep -i architecture dpkg --print-architecture 2/dev/null || rpm --eval %{_arch} gcc --version ldd --version判断逻辑很简单uname -m输出aarch64说明是ARM64架构如果输出x86_64说明是x86架构。这一步决定了你后面下载的所有包都必须带arm64后缀。系统里有dpkg说明是deb系只有rpm说明是rpm系。两者选包策略完全不同。gcc --version能看到系统自带gcc版本如果已经存在记下来后面遇到“版本还是旧的”这种问题时会用上。ldd --version输出版本号其实是在告诉你glibc的版本。Qt5对glibc有最低版本要求不同发行版的Qt包也依赖glibc版本这一点在离线环境下特别要命。这些命令看起来基础但能避免后面百分之七八十的弯路。1.3 离线不等于盲装依赖收集的整体策略离线环境的本质不是“没有安装包”而是“没有可用软件源”。所以整体思路就一句话在另一台同架构、可联网的机器上把安装包和依赖全部收集好再搬到目标机安装。我最开始以为这是个笨办法试过后发现其实是最稳的。收集依赖有两条路简单粗暴型去源码或上游直接下载编译好的二进制包然后把缺失的依赖一个个补齐。缺点是容易漏依赖链长的时候非常痛苦。系统化管理型利用apt-get install --download-only或者apt-cache depends --recurse把依赖树整个拉下来装到U盘里。这个方式在deb系下尤其好用。另外如果你要给很多台机器装环境建议直接把离线包做成本地源后续每台机器指定file://源即可省去重复搬运。本地源的做法我放到文章最后专门讲。2. gcc离线安装依赖泥潭与“升级后还是旧版本”的真相2.1 最稳的gcc离线安装方式连同依赖一起打包很多人一上来就想从网上下载gcc源码包自己编译这个想法在离线环境下极其痛苦——gcc的依赖包括binutils、libgmp、libmpfr、libmpc等一堆东西缺一个就卡住而且编译gcc本身非常耗时。更务实的方式是用包管理器把依赖一网打尽。拿deb系举例如果目标机可以用apt安装但不允许在线更新你可以先在联网机器上执行sudo apt-get update sudo apt-get install --download-only gcc g make ls /var/cache/apt/archives/*.deb--download-only会把包和依赖全部下载到/var/cache/apt/archives/但不会执行安装。这时把所有 .deb 拷到U盘再到目标机上执行sudo dpkg -i /path/to/debs/*.deb如果目标机提示依赖不满足不要慌这是正常现象。把报错信息中提到的包名记下来回到联网机器上用apt-cache search 包名找到并下载再补一次。一般重复两三轮依赖就能全了。这里有个提高命中率的技巧用apt-cache depends --recurse一次性递归列出所有依赖再交给apt-get download批量下载apt-get download $(apt-cache depends --recurse --no-recommends --no-suggests \ --no-conflicts --no-breaks --no-replaces --no-enhances gcc g make 2/dev/null \ | grep ^\w | sort -u)这条命令会列出所有直接依赖和间接依赖然后全部下载到当前目录。缺点是下载量可能很大但确实省心。注意依赖列表里可能包含大量libc6-dev、linux-libc-dev、binutils这类底层包全都需要不要手软。2.2 “升级后怎么还是旧版本”的三个诊断步骤这个现象我猜很多人遇到过明明装了新版gcc执行gcc --version却还是旧版本。热词里也有“gcc升级后为啥还是旧版本”这其实不是没装上而是系统找到了另一个gcc。排查顺序固定三步which -a gcc ls -l $(which gcc) update-alternatives --config gccwhich -a gcc会列出 PATH 中能找到的所有gcc路径。如果同时出现/usr/local/bin/gcc和/usr/bin/gcc而终端默认用的是前面那个那版本就是你新装的那个如果你改的是/usr/bin/gcc但终端实际执行的是/usr/local/bin/gcc那看到的当然还是旧版本。还有一种情况是bash的哈希缓存。比如你之前执行过哪个目录下的gccbash会把路径缓存起来安装新版本后仍在用缓存。执行hash -r清理一下即可。对于多版本并存我建议用update-alternatives管理而不是直接删软链接。系统里很多脚本默认调用/usr/bin/gcc手动删除或修改容易把系统搞坏。用下面的命令把希望默认使用的版本加进去sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100多套几个版本后再用update-alternatives --config gcc切换优先级。另外一个跟“版本”相关的深坑如果系统里libstdc6比较老而你用新版g编译出的程序在旧库环境运行时会报GLIBCXX_3.4.29 not found之类的错误。这时候不是重新编译的问题而是需要把目标机的libstdc6也升级到配套版本或者编译时用-static-libstdc -static-libgcc把C运行库静态链进去。2.3 装完必须做编译验证顺手避开工具链误区gcc装好后不要急着进入下一步先写个最简程序验证整个工具链#include stdio.h int main(void) { printf(hello aarch64\n); return 0; }gcc test.c -o test ./test file ./testfile输出中应该能看到ARM aarch64说明编译器的目标架构正确。再写一个C程序验证 g 和标准库#include iostream int main() { std::cout hello c from aarch64 std::endl; return 0; }g test.cpp -o test_cpp ./test_cpp这里我要特意提醒一个容易混淆的点如果你之前是做ARM嵌入式开发、用过ARM Compiler 5.06这类工具链千万别把它的编译产物直接拿到Linux ARM环境跑。ARM Compiler 5armcc是给Cortex-M这类MCU预研用的面向的是裸机或RTOS环境银河麒麟上的Qt5应用用的是aarch64-linux-gnu-gcc体系两者目标文件格式、运行库都完全不同。在网上搜“arm compiler 5.06下载”的时候一定要确认自己是不是走错了方向。3. Qt5离线包的三条路线与依赖库补齐3.1 路线A用发行版Qt5系统包最不折腾如果在银河麒麟ARM版上开发常规Qt Widgets应用我的第一推荐永远是走系统包。因为发行版打包的时候已经把所有库依赖都处理好了qmake、Qt库、插件目录全部统一后续部署也方便。在deb系机器上核心的包是这几个qtbase5-devQt5核心开发包包含 qmake、头文件、基础库qttools5-dev-tools包含 Qt Designer、Linguist、qdbus 等工具qt5-qmakeqmake本体一般会被qtbase5-dev拉进来qtcreatorQt官方IDEqtbase5-dev-tools包含 uic、moc 等工具编译Qt工程必需收集方式还是老套路sudo apt-get install --download-only qtbase5-dev qttools5-dev-tools qtbase5-dev-tools qt5-qmake qtcreator然后拷贝/var/cache/apt/archives/里的全部 .deb 到目标机执行sudo dpkg -i /path/to/debs/*.deb装完后验证三件事qmake --version pkg-config --modversion Qt5Widgets which qtcreatorqmake --version会显示类似QMake version 3.1和 Qt版本号。如果能出现具体版本号说明Qt核心已经可用。3.2 路线B官方离线安装器在ARM桌面的硬伤很多新手喜欢从Qt官网下载qt-opensource-linux-x64-5.15.2.run这样的离线安装器然后带到麒麟上执行。在ARM版上这条路基本走不通因为Qt官方对Linux桌面的离线安装器到目前为止主要提供x86_64版本没有对应的arm64桌面版安装器。在aarch64机器上直接运行会得到cannot execute binary file或Exec format error。我知道这个结论会劝退很多人但早点接受现实反而省时间。官方安装器在ARM桌面上的空缺是一个长期存在的坑。所以如果你非要用官方Qt套件比如要 LTS 版本、要特定模块更现实的路线是走第3.3节的源码编译或者用Qt官方在嵌入式Linux维护的交叉编译资源——但那是另一套玩法暂不展开。3.3 路线C源码编译慢但可控源码编译适合对Qt版本有硬性要求、且能忍受编译耗时的情况。流程大致是tar xf qt-everywhere-opensource-src-5.15.2.tar.xz cd qt-everywhere-opensource-src-5.15.2 ./configure -prefix /opt/Qt5.15.2 \ -opensource -confirm-license \ -nomake examples -nomake tests make -j$(nproc) make install这里的关键是-prefix它决定Qt安装到哪个目录直接影响后面QtCreator里需要填写的qmake路径。源码编译最大的坎其实不是编译本身而是 configure 阶段对系统依赖的检查。Qt5编译前需要一堆开发库缺少任何一个都会在configure时报错。至少需要libxcb1-dev libxkbcommon-dev libxkbcommon-x11-dev libfontconfig1-dev libfreetype6-dev libgl1-mesa-dev libegl1-mesa-dev这些包同样可以用apt-get install --download-only收集后离线安装。编译时间没有固定值。在普通ARM桌面机器上只编译核心模块不编译webengine大约1到2小时性能差一些的可能更久。我的看法是如果只是为了能开发应用没必要走源码编译系统包已经完全够用如果有必须锁定的Qt版本再考虑这条路。3.4 启动崩溃三连GL、xcb 与 fontconfigQt5装完、工程也能编译结果程序一启动就崩溃这是离线环境下最让人崩溃的环节。不要慌按下面顺序排查。第一刀永远是ldd /usr/lib/aarch64-linux-gnu/libQt5Widgets.so.5 | grep not found ldd $(which qtcreator) 2/dev/null | grep not found只要not found里有内容说明缺动态库。我在实际环境里遇到过的典型缺失如下缺失的库需要安装的包影响libGL.so.1libgl1-mesa-dev、libgl1-mesa-driQt GUI无法初始化OpenGLlibxcb-xinerama.so.0libxcb-xinerama0xcb插件加载失败会闪退libxcb-icccm4.so.4libxcb-icccm4窗口与窗口管理器通信异常libxkbcommon-x11.so.0libxkbcommon-x11-0键盘输入失效libfontconfig.so.1libfontconfig1字体渲染崩溃如果依赖库都齐了程序还是闪退多留意 “嵌入式ARM GPU驱动” 这个场景。有些ARM板子没有完整的GPU驱动Qt默认走xcb GL会起不来。可以在启动程序前设置环境变量export QT_XCB_GL_INTEGRATIONnone export QT_OPENGLsoftware前者关闭xcb的GL集成后者让Qt走软件渲染。虽然性能不如硬件加速但至少能正常弹窗。银河麒麟V10桌面版一般集成了Mesa软件渲染默认问题不大但如果你是自己在板子上移植的桌面环境这个变量就常备着吧。4. QtCreator配置版本关系、构建套件与拖拽难题4.1 qmake、Qt 和 QtCreator 的版本对应关系“qtcreator对应qt版本”这个热搜词背后是大家默认IDE和库必须严格配对。实际情况没那么死QtCreator是IDEQt是库两者独立演进。新版本的QtCreator完全能用老版本的Qt5库比如QtCreator 8 打开 Qt 5.15 的工程编译、调试都没问题。但“能用”不等于“零问题”QtCreator版本和Qt库版本差距太大时代码高亮、自动补全的解析器可能与实际语法制式有偏差但一般不影响编译结果。所以我的建议是在发行版源里能装到什么就用什么没必要追求最新版。银河麒麟源里的QtCreator和Qt5版本是打包时测试过的组合直接拿来干活最稳。如果你后续非要换Qt版本再考虑源码编译或官方包路线。4.2 手动配置构建套件Kit的完整过程安装好QtCreator后打开工程时会提示“No suitable kits found”这是因为IDE没有自动识别到qmake和编译器。按下面步骤手动配打开菜单Tools - Options - Kits依次检查四个页签Compilers点击右侧Add - GCC - C路径填/usr/bin/gcc。再Add - GCC - C路径填/usr/bin/g。如果下拉里已经有确认ABI列显示的是aarch64 - generic - ELF - 64bit。Debuggers确认/usr/bin/gdb存在不存在就离线安装gdb包。Qt Versions点Add选择qmake路径。deb系通常在这里/usr/lib/aarch64-linux-gnu/qt5/bin/qmake验证方式/usr/lib/aarch64-linux-gnu/qt5/bin/qmake --versionCMake如果工程用CMake确认/usr/bin/cmake已配置。最后回到Kits页签点Add把刚才的Compiler、Qt Version组合起来命名成类似Kylin ARM64 Qt5选中保存即可。有个细节如果qmake路径填错或填成x86机器上的路径构建时会报“No qmake found”或“qmake: command not found”。先验证qmake可执行再填路径这是最快的定位方式。4.3 无法拖拽文件从代码层到平台层排查“qt5无法拖拽文件”这个热词有两种完全不同的场景很多人搜半天对不上号。场景一你自己写的Qt程序不支持从文件管理器拖文件打开。这不是环境问题是代码里没开启拖拽支持。需要在主窗口构造函数里加一行setAcceptDrops(true);然后重写两个事件函数void MainWindow::dragEnterEvent(QDragEnterEvent *event) { if (event-mimeData()-hasUrls()) { event-acceptProposedAction(); } } void MainWindow::dropEvent(QDropEvent *event) { const QListQUrl urls event-mimeData()-urls(); for (const QUrl url : urls) { openFile(url.toLocalFile()); } }注意如果拖放的目标是一个子控件比如文本编辑框、列表父窗口的setAcceptDrops(true)会被子控件拦截。你需要对子控件也调用setAcceptDrops(true)或者给子控件安装事件过滤器在过滤器里响应拖拽事件。另外在部分桌面环境下用root身份运行Qt程序文件管理器可能不会向root窗口提供拖拽数据。遇到这种情况切回普通用户试试往往立刻就好。场景二QtCreator本身没法从文件管理器拖文件进编辑区。这就不是代码问题了而是缺少Qt Creator运行时依赖的xcb拖拽协议相关库。最常见的就是libxcb-xinerama0、libxcb-icccm4、libxcb-render-util0缺失。补齐后重启QtCreator即可。如果还不行用调试模式启动QT_DEBUG_PLUGINS1 qtcreator日志里会打印所有插件加载情况。找到与xcb相关的报错按提示补库基本都能解决。这个方法对Qt程序启动闪退同样适用后面我还会提到。5. 交叉编译的边界什么时候做怎么做才会少翻车5.1 什么场景才需要交叉编译看到标题是“银河麒麟ARM版”很多人第一反应是要交叉编译。但你要先想清楚目标机器到底是哪一台。如果程序就是跑在这台ARM麒麟机器上那直接在机器上编译最省事交叉编译纯粹给自己找麻烦。真正需要交叉编译的典型场景是你的开发机是x86笔记本目标板是orangepi cm5、树莓派这类ARM设备且目标设备性能弱到没法原生编译大型Qt工程或者你希望编译时间尽可能短。这时候才考虑在x86开发机上安装交叉编译工具链sudo apt-get install gcc-aarch64-linux-gnu g-aarch64-linux-gnu安装后验证aarch64-linux-gnu-gcc --version再写个最简程序试编译即可确认工具链可用。5.2 一套最小可用的aarch64 CMake工具链文件用CMake管理Qt工程时交叉编译通常需要一个工具链文件。下面是一份我实际用过的可以直接当模板set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g) set(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)核心理解三个点CMAKE_C_COMPILER和CMAKE_CXX_COMPILER指定交叉编译器。CMAKE_FIND_ROOT_PATH告诉CMake去哪找target系统的库和头文件相当于指定sysroot。MODE_PROGRAM NEVER表示查找可执行程序时仍用宿主机的比如查找编译器本身MODE_LIBRARY和MODE_INCLUDE限定只查target路径下的库和头文件。使用方式cmake -DCMAKE_TOOLCHAIN_FILEtoolchain-aarch64.cmake .. make如果能正常编译通过说明工具链和sysroot配置基本正确。5.3 sysroot翻车现场与更省心的替代方案交叉编译最容易翻车的地方就是CMAKE_FIND_ROOT_PATH指向的sysroot目录里缺东西。表现为编译时找不到某个头文件链接时找不到某个库。常见的解决方案有两种方案一直接用开发板的根文件系统当sysroot。把板子上的整个根目录打包拷贝到开发机上然后在工具链文件里把它指定成CMAKE_FIND_ROOT_PATH。好处是与目标环境完全一致坏处是同步麻烦板子上的路径变动就得重新拷贝。方案二用apt的多架构支持在开发机上单独下载arm64库。执行dpkg --add-architecture arm64后可以安装libqt5widgets5:arm64这类针对arm64的库避免污染宿主环境。这个办法对deb系很好用但在离线环境下同样要先收集好 .deb。我的真实体会是如果目标设备是一个完整的ARM Linux系统而且设备上可以正常安装 .deb/.rpm 包那你直接在目标设备上装好Qt开发包再原生编译会比交叉编译顺畅得多。交叉编译更适合“目标设备是精简根文件系统、没法装完整编译工具链”的场景。别为了追求“高级”而选择一条更复杂的路。6. 离线现场收拾包收集、本地源与排错三板斧6.1 一个能自动拉全依赖的离线包收集方法离线安装最核心的能力其实是在联网机器上把依赖包收集全。我把常用的打包命令给全你可以直接循环使用。一次安装多个开发包的收集流程pkgsgcc g make qtbase5-dev qttools5-dev qttools5-dev-tools qtbase5-dev-tools qt5-qmake qtcreator sudo apt-get update sudo apt-get install --download-only $pkgs mkdir -p /tmp/offline_debs cp /var/cache/apt/archives/*.deb /tmp/offline_debs/在目标机上安装时如果dpkg -i *.deb报依赖缺失用下面方式把缺失依赖名打印出来再去联网机器补sudo dpkg -i /tmp/offline_debs/*.deb 21 | grep depends on如果团队环境需要多次重复安装建议把离线包做成本地源省去每次手动dpkg。deb系最短步骤cd /tmp mkdir -p localrepo/debs cp *.deb localrepo/debs/ sudo apt-get install -y dpkg-dev cd localrepo dpkg-scanpackages debs /dev/null | gzip debs/Packages.gz echo deb [trustedyes] file:///tmp/localrepo debs/ | sudo tee -a /etc/apt/sources.list sudo apt-get update之后随便用apt-get install 包名就能从本地源安装依赖关系也会自动解析。注意包必须是从同发行版同版本源里下载的否则可能出现库版本不兼容问题。6.2 排错三板斧ldd、QT_DEBUG_PLUGINS、update-alternatives整篇文章下来我几乎所有问题的排查最终都落在三个命令上这里统一说清楚使用时机第一斧ldd。只要程序启动报找不到共享库、启动闪退先跑ldd 可执行文件 | grep not found它会直接告诉你缺哪个.so文件再反查属于哪个包。这是最快的一步90%的问题在这是现形。第二斧QT_DEBUG_PLUGINS。当Qt程序连Qt插件库都加载不了时ldd可能看不出问题因为库文件存在但插件内部的依赖不满足。此时用QT_DEBUG_PLUGINS1 可执行文件启动Qt会把每个插件加载情况打印出来定位到具体插件后再补对应依赖库。第三斧update-alternatives。当你觉得“明明装了新版本系统就是不认”时不要反复安装覆盖先which -a 命令看真实路径再用update-alternatives --config 命令切换默认版本。这能省掉大量重装的时间。6.3 多人协作时把环境整理成可复现产物如果你是项目里唯一一个把环境装通的人后面还有同事要复现我强烈建议你做两件事。第一把离线包目录整体保存下来放到共享存储或内部文件服务器不要放在个人U盘的某个角落。第二写一个简单的README.md记录目标系统的版本、架构、包数量、安装顺序和验证命令。不要迷信记忆也不要迷信口头交接。我自己的做法是在所有工作收尾前把安装过的所有包名和版本号导出来和U盘里的离线包放在同一个目录dpkg -l installed_packages_backup.txt这样遇到完全相同的系统同事直接照着这个清单验证出现偏差也容易定位。离线环境的特点是“容错率低”留下可复现的操作记录比任何临时排查都重要。每次装完这套环境我都会再写一个最简Qt窗口程序确认它能正常弹窗才会开始正式工程。这个验证能筛掉80%的工具链问题值得养成习惯。如果你也碰到类似ARM麒麟离线装Qt5的情况建议从系统包这套走起踩坑最少。最后分享一个我自己的固定操作把所有离线包和版本号整理成一个清单文件跟着环境一起交付下次同事遇到同样问题时照着就能复现比自己重新摸索省太多时间了。