news 2026/10/20 18:58:32

麒麟ARM64系统源码编译Qt 5.12.8全流程与避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
麒麟ARM64系统源码编译Qt 5.12.8全流程与避坑指南

简介:本资源面向在国产化平台上进行桌面或嵌入式应用开发的工程师,提供在 Kylin-Server-10-SP2-Release-Build09-20210524-arm64 系统上编译完成的 Qt 5.12.8 头文件集合,可解决 ARM64 架构下麒麟系统缺少匹配 Qt 开发头文件、难以直接编译 Qt 程序的问题。压缩包为 gz 格式,共约 2000 个文件,全部为 .h 头文件,整体约 65.91MB,涵盖 QtCore、QtGui、QtOpenGL、QtNetwork 等模块的公开接口声明,以及 qopenglextensions、qopenglfunctions 系列 OpenGL 兼容层头文件,便于开发者直接引用或对照排查编译依赖。目前已有 251 人学习下载,适合需要快速搭建 Qt 交叉编译环境、核对 API 声明或补齐头文件依赖的开发者参考使用。

1. 麒麟系统上把 Qt 5.12.8 从源码啃下来:为什么值得折腾

在一台国产 ARM 服务器上,系统装的是 Kylin-Server-10-SP2-Release-Build09-20210524-arm64,自带软件源里的 Qt 版本要么太老、要么缺模块,而业务代码又必须锁死在 Qt 5.12.8 这个 LTS 版本上。这时候你只有两条路:要么改业务代码去迁就系统源,要么自己从源码把 Qt 5.12.8 编出来。我选后者,因为改代码的成本远高于一次编译。这篇笔记讲的就是在 aarch64 架构的麒麟服务器上,从零把 Qt 5.12.8 编译出来并跑通一个最小 GUI 程序的全过程,包括依赖怎么装、configure 参数怎么配、编译报错怎么查、装完之后环境变量怎么设。适合手里有 ARM 服务器、需要在国产化平台上做 Qt 桌面或嵌入式开发的人,也适合第一次在非 x86 架构上编大型 C++ 框架、想少走弯路的同行。整个过程最耗时的不是敲命令,而是踩依赖和架构的坑,下面把每一步都摊开讲。

2. 编译前的环境盘点与依赖准备:别让缺库毁掉三小时

2.1 先确认系统底子,别急着解压源码

动手之前先花五分钟把系统信息摸清楚,这一步能省掉后面大量「编译到一半报错」的时间。Kylin-Server-10-SP2 基于较新的内核和 glibc,aarch64 架构下很多 x86 上的经验会失效,所以先确认三件事:CPU 架构、glibc 版本、GCC 版本。Qt 5.12.8 对 GCC 的要求是 5.3 以上,麒麟自带的 GCC 一般能满足,但 glibc 太新有时反而会让老版本 Qt 的某些检测脚本出问题。

# 确认架构,必须是 aarch64 uname -m # 查看系统发行版信息 cat /etc/os-release # 查看 glibc 版本,Qt 5.12.8 建议 2.17 以上 ldd --version | head -n 1 # 查看 GCC 版本,需要 5.3+ gcc --version | head -n 1 # 查看 CPU 核心数,决定后面 make -j 的并行度 nproc

这几条命令的输出要记下来。nproc的结果直接决定后面make -j后面跟几,核多就并行高一点,核少就老老实实单线程,否则内存会被打爆。我一般留一到两个核给系统,比如 8 核就用-j6。另外确认磁盘空间,Qt 源码解压后加上编译中间产物,轻松吃掉 20GB 以上,df -h看一眼根分区和你要放源码的分区。

2.2 依赖包一次装齐,别等报错再补

Qt 的依赖分两类:编译工具链和功能模块依赖。工具链包括 make、g++、perl、python(部分脚本用)、pkg-config。功能模块依赖则取决于你要启用哪些 Qt 模块,比如要 GUI 就得有 X11 或 OpenGL 相关开发库,要网络就得有 OpenSSL 开发库。麒麟的包管理用的是 yum/dnf 体系,下面这组依赖是我在 aarch64 上实测能覆盖绝大多数模块的清单。

# 基础编译工具链 sudo yum install -y gcc gcc-c++ make perl python3 pkgconfig # X11 与 OpenGL 相关,GUI 模块必需 sudo yum install -y libX11-devel libXext-devel libXrender-devel \ libXtst-devel libXi-devel mesa-libGL-devel mesa-libGLU-devel # 字体与图形库 sudo yum install -y fontconfig-devel freetype-devel libpng-devel \ libjpeg-turbo-devel zlib-devel # 网络与安全 sudo yum install -y openssl-devel # 多媒体与数据库(按需,不用可省) sudo yum install -y alsa-lib-devel libsqlite3x-devel

装完依赖后建议用rpm -qa | grep devel扫一眼,确认关键库都在。这里有个血泪经验:aarch64 上某些-devel包的命名和 x86 不完全一致,比如有的系统里 OpenGL 开发包叫mesa-libGL-devel,有的叫libGL-devel,装不上就yum search找一下实际包名。依赖没装齐,configure 阶段会直接告诉你缺哪个,但有些是编译到一半才暴露,所以宁可一次装全。

2.3 源码获取与目录规划

Qt 5.12.8 的源码包是单个大压缩包,解压后是一个qt-everywhere-src-5.12.8目录。我习惯把源码放在/opt/src下,编译产物和安装目录分开,方便以后清理或重编。安装目录我选/opt/Qt5.12.8,不装到系统默认路径,避免和系统自带的 Qt 冲突,也方便多版本共存。

# 创建源码和安装目录 sudo mkdir -p /opt/src /opt/Qt5.12.8 # 把源码包放到 /opt/src 后解压 cd /opt/src tar -xf qt-everywhere-src-5.12.8.tar.xz # 进入源码目录 cd qt-everywhere-src-5.12.8

解压后先别急着 configure,看一眼顶层目录结构,确认configure脚本存在。Qt 5.12 用的是老式 configure 脚本,不是 CMake,所以参数写法是-prefix、-opensource这种风格。目录规划清楚之后,后面出问题要重来,直接删掉 build 目录重配即可,不用重新解压源码。

3. configure 参数怎么配:一次配对,少编两小时

3.1 关键参数逐条拆解

configure 是整场编译里最需要动脑的一步,参数配错要么编出来的库缺功能,要么直接编不过。Qt 5.12.8 的 configure 参数很多,但在 aarch64 麒麟服务器上真正需要你操心的就那么几个。下面这条是我实际用的命令,先贴出来再逐条解释。

./configure -prefix /opt/Qt5.12.8 \ -opensource -confirm-license \ -release \ -nomake examples -nomake tests \ -no-openssl \ -skip qtwebengine \ -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype \ -xcb \ -platform linux-g++

-prefix指定安装路径,必须和前面创建的目录一致。-opensource -confirm-license表示使用开源协议并自动确认,不加会卡在交互式提问。-release只编发布版,不编调试版,能省将近一半时间和磁盘。-nomake examples -nomake tests跳过示例和测试,除非你要研究示例代码,否则没必要编。-no-openssl是因为麒麟自带的 OpenSSL 版本和 Qt 5.12.8 的检测逻辑有时对不上,直接禁用,需要网络加密时再单独处理。-skip qtwebengine很关键,QtWebEngine 在 aarch64 上编译极其耗时且依赖 Chromium 那一套,除非业务必须用浏览器控件,否则一定跳过。-qt-zlib -qt-libpng -qt-libjpeg -qt-freetype表示用 Qt 自带的第三方库,避免和系统库版本打架,这在国产系统上尤其省心。-xcb启用 X11 后端,服务器上如果要跑 GUI 程序需要它。-platform linux-g++明确指定平台,aarch64 上一般能自动识别,但写死更稳。

3.2 参数取舍背后的判断逻辑

上面这些参数不是拍脑袋定的,每一条都对应一个实际约束。比如-no-openssl,很多人第一反应是「网络模块不要加密了?」其实不是,Qt 的网络模块本身能用,只是不链接系统 OpenSSL,等你真需要 HTTPS 时,可以单独编一个匹配的 OpenSSL 再重新 configure Qt 的 network 模块,或者用运行时动态加载的方式。在麒麟这种系统库版本和上游不完全同步的环境里,先禁用再按需补,比一开始就硬链要稳。

再比如-qt-zlib这一组,本质是让 Qt 用自己源码树里带的 zlib、libpng 等,而不是去链系统的-devel包。好处是版本可控,不会因为系统库升级导致 Qt 运行时报符号找不到;代价是编译时间略长、产物体积略大。在国产化平台上,可控性比省那点空间重要得多。-skip qtwebengine则是纯粹的性价比判断:这个模块编译动辄几小时,依赖 Node.js、Chromium 一堆东西,aarch64 上还容易挂,除非明确要做内嵌浏览器,否则跳过是理性选择。

3.3 configure 通过后的自检

configure 跑完会输出一份摘要,列出哪些模块启用、哪些跳过、哪些因为缺依赖被禁用。这份摘要必须逐行看,尤其是「These modules are disabled」那一段。如果发现你需要的模块被禁用了,比如qtmultimedia因为缺 ALSA 被关掉,那就回去补依赖再重新 configure。configure 本身不编译,重跑成本很低,但一旦开始 make 再发现模块缺失,就得从头再来。

# configure 完成后,把摘要存一份,方便对比 ./configure -prefix /opt/Qt5.12.8 -opensource -confirm-license \ -release -nomake examples -nomake tests -no-openssl \ -skip qtwebengine -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype \ -xcb -platform linux-g++ 2>&1 | tee /tmp/qt_configure.log # 检查被禁用的模块 grep -A 20 "disabled" /tmp/qt_configure.log

摘要里还会告诉你用的是哪个编译器、哪个 C++ 标准。Qt 5.12.8 默认用 C++11,如果系统 GCC 默认标准更高,一般也能兼容,但遇到奇怪的模板报错时,可以加-c++std c++11强制指定。确认摘要没问题,就可以进入编译阶段了。

4. 编译与安装:并行度、内存和报错排查

4.1 make 并行度与内存的平衡

编译 Qt 是个体力活,aarch64 服务器核数通常不少,但内存不一定跟得上。make -j的并行度不是越高越好,每个编译单元(尤其是 C++ 模板重的模块)可能吃掉几百 MB 到 1GB 内存,核多内存小的话,并行一高就触发 OOM,编译进程被系统杀掉,报错信息还很不直观。我的经验是:内存 16GB 以下,-j不超过核数的一半;32GB 以上可以接近核数。

# 假设 8 核 16GB 内存,用 -j4 比较稳 make -j4 2>&1 | tee /tmp/qt_make.log # 如果中途报错,日志里搜 "Error" 定位 grep -n "Error" /tmp/qt_make.log | head

编译时间取决于核数和跳过的模块,aarch64 上 8 核大概两到四小时,具体看机器。建议挂tee把日志存下来,一是方便出错回溯,二是万一终端断了还能看进度。如果编译中途因为内存被杀,dmesg | tail能看到 OOM killer 的记录,这时候降低-j重来即可,已经编好的目标文件不会丢,make 会接着编。

4.2 典型报错的定位思路

aarch64 上编 Qt 5.12.8 最常见的报错有三类。第一类是缺头文件或库,报错里会明确写fatal error: xxx.h: No such file or directory,对应去装那个-devel包。第二类是链接错误,undefined reference to xxx,通常是某个功能库没链上,回去检查 configure 摘要里对应模块是否启用。第三类是编译器内部错误或段错误,这种最玄学,往往是并行编译时内存不足或某个模块的代码在 aarch64 上有对齐问题,降低并行度或单独进那个模块目录make往往能过。

# 单独进某个出问题的模块目录编译,方便看详细报错 cd qtbase make -j1 2>&1 | tee /tmp/qtbase_make.log # 如果是链接错误,看具体缺哪个符号 grep "undefined reference" /tmp/qtbase_make.log | head

单独编某个模块时,注意它依赖的其他模块可能还没编完,所以一般是在整体 make 失败后,定位到具体模块再进去单编。单编通过后回到顶层再make一次,它会跳过已完成的,继续往下走。

4.3 安装与目录结构确认

编译全部通过后,make install把产物装到-prefix指定的目录。安装过程一般不会出错,但装完要确认目录结构对不对。Qt 5.12.8 装完后,/opt/Qt5.12.8下应该有bin、lib、include、plugins、mkspecs等目录,bin里能看到qmake、moc、uic这些工具。

# 安装 sudo make install 2>&1 | tee /tmp/qt_install.log # 确认 qmake 存在且可执行 /opt/Qt5.12.8/bin/qmake -v # 查看安装目录大小,确认没有明显缺失 du -sh /opt/Qt5.12.8

qmake -v的输出会显示 Qt 版本和安装路径,如果显示的是 5.12.8 且路径正确,说明安装成功。如果显示的是系统自带的 qmake,说明环境变量还没配,下一步处理。

5. 环境变量与最小验证程序:编完不算完,跑起来才算

5.1 环境变量怎么设才不污染系统

装完 Qt 后,要让编译和运行都能找到它,需要设几个环境变量。最省事的做法是写一个脚本,用的时候 source 一下,而不是直接写进/etc/profile全局污染。核心变量是PATH加 qmake 路径、LD_LIBRARY_PATH加 Qt 库路径、PKG_CONFIG_PATH加 pkgconfig 路径。

# 保存为 /opt/Qt5.12.8/qt_env.sh export QT_DIR=/opt/Qt5.12.8 export PATH=$QT_DIR/bin:$PATH export LD_LIBRARY_PATH=$QT_DIR/lib:$LD_LIBRARY_PATH export PKG_CONFIG_PATH=$QT_DIR/lib/pkgconfig:$PKG_CONFIG_PATH # 使用时 source 一下 source /opt/Qt5.12.8/qt_env.sh # 验证 qmake 指向正确 which qmake qmake -v

LD_LIBRARY_PATH这一条在运行时很关键,否则程序启动会报找不到libQt5Core.so.5。但要注意,LD_LIBRARY_PATH设太宽可能影响系统其他程序,所以只在开发终端里 source,不要全局设。如果要做成系统级,更规范的做法是在/etc/ld.so.conf.d/下加一个 conf 文件再ldconfig,但那样会影响所有程序,我一般不用。

5.2 一个最小 GUI 程序验证全链路

验证 Qt 是否真正可用,最直接的办法是编一个最小 GUI 程序。下面这个例子创建一个窗口,标题显示 Qt 版本,能编过、能弹出窗口,就说明编译、安装、环境变量、X11 后端这一整条链路都通了。

// main.cpp #include <QApplication> #include <QLabel> #include <QString> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 显示当前 Qt 版本,验证链接的是我们编的库 QString ver = QString("Qt version: %1").arg(QT_VERSION_STR); QLabel label(ver); label.setWindowTitle("Qt on Kylin ARM64"); label.resize(320, 120); label.show(); return app.exec(); }

配套的工程文件test.pro只需要三行:

QT += widgets SOURCES += main.cpp TARGET = qt_verify

编译和运行:

# 确保已 source 环境变量 source /opt/Qt5.12.8/qt_env.sh # 生成 Makefile 并编译 qmake test.pro make # 运行,需要当前有 X11 显示环境 ./qt_verify

如果程序能弹出窗口并显示版本号,说明整条链路打通。如果报cannot connect to X server,说明当前终端没有图形显示环境,用ssh -X或直接在服务器本地桌面跑。如果报找不到库,检查LD_LIBRARY_PATH是否生效。

5.3 无图形环境下的替代验证

服务器很多时候没有图形界面,这时候 GUI 程序跑不起来不代表 Qt 编坏了。可以用一个纯控制台的 Qt 程序验证核心库,只链接QtCore,打印版本和平台信息。

// console_test.cpp #include <QCoreApplication> #include <QString> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); qDebug() << "Qt version:" << QT_VERSION_STR; qDebug() << "Build platform:" << QSysInfo::buildCpuArchitecture(); return 0; }

工程文件把QT += widgets换成QT += core,编译运行后能看到版本和架构输出,就说明 QtCore 没问题。GUI 部分等有显示环境时再验证。这种分步验证的思路,在排查「到底是 Qt 编坏了还是环境没配好」时特别有用。

6. 避坑与排查:aarch64 上编 Qt 最容易翻车的五件事

6.1 坑一:configure 报找不到 OpenGL 库

现象是 configure 阶段提示OpenGL functionality tests failed,或者摘要里qtgui被禁用。原因通常是mesa-libGL-devel没装,或者装了但 pkg-config 找不到。解决是先确认包在不在,rpm -qa | grep -i mesa,不在就装;装了还报错,检查PKG_CONFIG_PATH是否包含系统默认路径,必要时手动指定-I和-L参数指向 GL 头文件和库目录。

6.2 坑二:make 到一半被 Killed

现象是编译进程突然消失,日志里没有 Error,只有Killed。原因是内存不足,OOM killer 把编译进程杀了。解决是降低make -j的并行度,或者加 swap。free -h看内存和 swap 使用情况,dmesg | grep -i oom确认是 OOM。aarch64 服务器内存配置差异大,别照搬 x86 上的-j经验。

6.3 坑三:链接时报 undefined reference 到某个 Qt 模块

现象是编业务程序时链接失败,提示找不到libQt5Xxx.so里的符号。原因是 configure 时那个模块被禁用了,或者安装后LD_LIBRARY_PATH没包含 Qt 库路径。解决是先看/opt/Qt5.12.8/lib下有没有对应的.so文件,没有就回去补依赖重新 configure 和 make;有的话检查环境变量和.pro文件里的QT +=是否写对。

6.4 坑四:qmake 生成 Makefile 时找不到 mkspecs

现象是运行 qmake 报Could not find qmake configuration file或类似错误。原因是mkspecs目录没装全,或者QMAKESPEC环境变量指向了错误位置。解决是确认/opt/Qt5.12.8/mkspecs存在且里面有linux-g++等目录,然后unset QMAKESPEC让 qmake 用内置默认值,或者显式export QMAKESPEC=/opt/Qt5.12.8/mkspecs/linux-g++。

6.5 坑五:程序运行时报 xcb 插件加载失败

现象是 GUI 程序启动时报This application failed to start because no Qt platform plugin could be initialized,或者明确说xcb插件找不到。原因是 Qt 的插件路径没被正确识别,或者libxcb相关库缺失。解决是设export QT_DEBUG_PLUGINS=1看插件加载详细日志,确认/opt/Qt5.12.8/plugins/platforms/libqxcb.so存在,并用ldd检查它依赖的 xcb 库是否都能找到。缺库就补装对应的libxcb-*-devel或运行时包。

7. 进阶技巧:把编译产物做成可复用的开发环境

7.1 用 qmake 的 cache 加速后续项目配置

Qt 编好之后,每次新建项目都手动 source 环境变量有点烦。可以在项目根目录放一个.qmake.cache或者在qmake命令里用-cache参数,把 Qt 安装路径、编译器选项缓存下来。更实用的做法是写一个qt_env.sh放在项目里,团队成员 clone 下来 source 一下就能用,路径用相对或环境变量推导,避免硬编码。

# 项目内 qt_env.sh,自动推导 Qt 路径 QT_DIR=${QT_DIR:-/opt/Qt5.12.8} if [ ! -x "$QT_DIR/bin/qmake" ]; then echo "Qt not found at $QT_DIR, please set QT_DIR" return 1 fi export PATH=$QT_DIR/bin:$PATH export LD_LIBRARY_PATH=$QT_DIR/lib:$LD_LIBRARY_PATH echo "Qt environment ready: $($QT_DIR/bin/qmake -v | tail -n 1)"

这个脚本的好处是路径可覆盖,换机器或换安装目录时不用改脚本内容,QT_DIR=/other/path source qt_env.sh即可。

7.2 交叉编译与本地编译的边界判断

有人会问,能不能在 x86 机器上交叉编译出 aarch64 的 Qt,再拷到麒麟服务器上用。技术上可行,但我不推荐在项目初期这么做。交叉编译需要一套完整的 aarch64 工具链和 sysroot,配置复杂度远高于本地编译,而且一旦 sysroot 里的库版本和实际服务器不一致,运行时会出各种玄学问题。本地编译虽然慢,但产物和运行环境天然一致,省去大量排查时间。等本地编译跑通、环境稳定后,再考虑用容器或交叉编译做 CI 加速,那才是合理的顺序。

7.3 验证编译产物完整性的一个习惯

每次编完 Qt,我都会跑一个「模块清单核对」:把 configure 摘要里启用的模块列出来,逐个检查/opt/Qt5.12.8/lib下有没有对应的.so,再用qmake -query看关键路径。这个习惯帮我提前发现过好几次「某个模块其实没编进去」的问题,避免等到业务程序链接时才暴露。

# 列出所有 Qt 库,和 configure 摘要对比 ls /opt/Qt5.12.8/lib/libQt5*.so | sed 's#.*/lib##; s#\.so$##' | sort # 查看 qmake 记录的关键路径 /opt/Qt5.12.8/bin/qmake -query

qmake -query会输出QT_INSTALL_PREFIX、QT_INSTALL_LIBS、QT_INSTALL_HEADERS等,确认这些路径都指向/opt/Qt5.12.8而不是系统路径。如果指向系统路径,说明环境变量或 qmake 本身有问题,得回头查。

我自己在 aarch64 上编 Qt 最大的教训是:别信「应该没问题」,每一步都验证。依赖装完验证一遍,configure 完看摘要,make 完看库文件,装完跑最小程序。这套流程看起来啰嗦,但比编到一半推倒重来省时间得多。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 18:57:24

Redis如何解决AI大模型记忆问题:短期、长期与语义记忆落地

Redis接上AI&#xff0c;听起来像两个世界的强强联手&#xff1a;一个号称最懂速度的内存数据库&#xff0c;一个天天发愁记不住事的智能对话系统。最近不管是社区讨论还是团队内部架构评审&#xff0c;Redis能承担什么AI角色&#xff0c;已经成了高频话题。我的判断是&#xf…

作者头像 李华
网站建设 2026/10/20 18:56:13

数据结构查找章节总结:ASL计算、B树与散列表核心考点

1. 为什么“查找”这一章值得单独拎出来总结如果你正在学《数据结构》&#xff0c;翻到第七章“查找”的时候&#xff0c;大概率会有一种错觉&#xff1a;前面线性表、树、图已经把人折腾得够呛&#xff0c;查找这章看起来好像就是“在一堆数据里找个东西”&#xff0c;能有多难…

作者头像 李华
网站建设 2026/10/20 18:55:30

FPGA工程师进阶实战:从基础到时序收敛的提升路径

做 FPGA 工程这行&#xff0c;时间越久越会有一个体会&#xff1a;这活儿不是“会写 Verilog”就完事的。早些年我刚入行的时候&#xff0c;以为搞定语法、仿真跑通、上板点个灯就算入门了&#xff0c;结果真到项目里&#xff0c;被时序收敛、跨时钟域、调试定位这些事儿反复教…

作者头像 李华
网站建设 2026/10/20 18:55:10

Qt记账本实战:从UI搭建到SQLite持久化的完整开发链

简介&#xff1a;本资源是一份面向Qt初学者与C桌面开发入门者的教学实践项目&#xff0c;聚焦个人财务管理场景&#xff0c;提供一套可运行、可调试的跨平台记账本完整源码。项目基于Qt 5.9.9 MinGW32构建&#xff0c;兼容Windows 10/11及Ubuntu 18.04&#xff0c;涵盖界面设计…

作者头像 李华
网站建设 2026/10/20 18:55:10

Hermes Agent轻量级消息代理部署实践:异步通信与定时任务调度全攻略

1. 项目概述与核心设计思路1.1 Hermes Agent到底解决什么问题Hermes Agent 是一个轻量级的消息代理与任务调度组件&#xff0c;专门用来解决服务之间异步通信、定时任务分发这类老生常谈的问题。我最初接触到它&#xff0c;是在维护一套内部系统时&#xff0c;服务之间的调用经…

作者头像 李华
网站建设 2026/10/20 18:55:01

微信历史版本大全:可运行源码与本地复现的工程化方案

简介&#xff1a;这份资源面向软件开发者、测试人员及对旧版微信有特定需求的用户&#xff0c;整理了安卓、Windows与MAC三大平台的历史版本下载地址&#xff0c;解决因版本迭代导致旧版安装包难以查找的问题。压缩包共3个文件&#xff0c;以html页面、inscode配置与gitignore为…

作者头像 李华