A
Air官方
【Air 系列 · 鸿蒙 PC 适配全记录】13 / 56
■ 应用:AirEDA(from KiCad)(AirEDA)
■ 定位:KiCad 移植,电子设计 EDA 与器件库浏览
■ 上游:KiCad 8.0.8 | 路线:wxGTK3+GTK3 栈 | 版本:1.1.0
■ 开源: https://gitcode.com/Andy88/Harmony-KiCad
■ 市场状态:已上架 AGC 应用页: https://appgallery.huawei.com/app/6917614382376546372
■ 官网(免费下载): https://www.shunidc.cn/
————————————————————
开源鸿蒙 PC 社区: https://harmonypc.csdn.net/
PC 社区项目申请: https://atomgit.com/OpenHarmonyPCDeveloper
适配开源地址:https://gitcode.com/Andy88/Harmony-KiCad
环境搭建文章:https://blog.csdn.net/weixin_52908342/article/details/161343743
▍一、为什么要适配 AirEDA
KiCad 是开源电子设计自动化的旗舰项目,原理图编辑器 eeschema 与 PCB 编辑器覆盖了从符号库、网表到版图的完整设计流程。EDA 软件对窗口系统、图形渲染与字体文本的要求在桌面应用中属于最高一档,把它的原理图编辑主链路带到鸿蒙 PC,等于让系统的 GTK 兼容层、窗口管理与输入管线接受一次接近生产级强度的检验。
本工程当前版本 1.0.0,包名 com.aireda.app,deviceTypes 覆盖 phone、tablet 与 2in1。工程经历了一次明确的路线升级:早期实现是纯 ArkTS 的 KiCad 器件库浏览器——解析 KiCad 4.0.x 官方库的 109 个符号库、5199 个元器件符号与 18 套工程模板,自行完成 EESchema、kicad_pcb 格式解析与画布渲染;2026-08-19 起按用户需求转向 KiCad 8.0.8 真应用的全栈原生移植,采用 AirGimp 同款双层架构。原 ArkTS 查看器代码保留在 pages/*Viewer 相关页面,如今作为器件库与模板的浏览入口继续工作。
移植路线的关键决定有三条:GUI 栈选 wxWidgets 3.2.8 的 wxGTK3 后端加 AirGimp 工程沉淀的 GTK3 OHOS GDK 后端;渲染选 cairo GAL 软件渲染,GL GAL 走 stub(KiCad 配置预设 noaccel);入口选 eeschema,以官方 single_top 加 eeschema_kiface 模块机制运行,KIWAY 插件框架原样保留。仓库 PORTING.md 按选型、依赖矩阵、补丁登记、风险登记四张表完整记录了决策依据。
▍二、先划清边界:不把编译通过当成适配完成
KiCad 桌面版运行在完整的 Linux 桌面环境里:X11 窗口系统、桌面 WM 管理对话框、GTK 原生菜单栏、系统文件选择器与 XDG 目录约定,都是它默认存在的地基。鸿蒙侧没有 fork/exec、没有 X11、没有独立 WM,应用还生活在 el2 沙箱内。移植的实质是为每一层地基找一个鸿蒙等价物,找不到的以补丁显式裁剪,而不是留着一条走不通的路径伪装完整。
层次 原项目实现(KiCad 桌面版) 鸿蒙侧当前方案
应用入口 kicad 主程序 fork/exec 拉起 kiface 单进程 single_top(FRAME_SCH)+ kiface 运行时 dlopen,KIWAY 机制保留
窗口系统 X11 与桌面 WM GDK OHOS 后端(GTK3 栈)+ XComponent(TEXTURE)宿主
图形渲染 OpenGL GAL(wxGLCanvas) cairo GAL 软件渲染,kicad.yaml 预设 noaccel
菜单栏 GTK wxMenuBar 原生渲染 wxMenuBar 导出 JSON,ArkTS 顶栏 bindMenu 渲染与命令激活
文件对话框 GTK wxFileDialog/wxDirDialog ShowModal 拦截,经 TSFN 转 ArkTS 系统 Picker,staging 暂存回拷
对话框承载 WM 管理的顶级窗口 鸿蒙子窗口(kicad-dialog-id)+ ArkTS 模态遮罩与几何钳制
数据目录 XDG 系统目录约定 KICAD_STOCK_DATA_HOME 等环境变量指向沙箱,资源随 HAP 部署
帮助与外链 浏览器拉起帮助与数据手册 AddStandardHelpMenu 早退、GetAssociatedDocument 置为 no-op
这条边界的直接含义是:当前产物是能在鸿蒙设备上打开、编辑原理图并存盘的 eeschema 子集,PCB 编辑器、3D 查看器与电路仿真不在 v1 范围(ngspice 以 stub 满足 KiCad 8 的构建期硬依赖)。
▍三、鸿蒙版的整体架构
架构为 Air 系列标准的双层 GTK 变体。ArkTS 壳管理 Ability、顶栏菜单、对话框子窗与文件选择器;NAPI 薄壳 libkicadbridge.so 处理 XComponent 回调、按拓扑序 dlopen 依赖并建立线程安全函数通道;libkicad_core.so 在 KiCad 源码树内构建,聚合 wxGTK 全家、GTK3 栈与 kiface,宿主线程上完成环境变量前置、gtk_init、GDK 预绑定后进入 wxEntryStart 与 CallOnInit。
text
ArkTS 壳(EntryAbility / NativeHost.ets / DialogPage.ets)
│ NAPI
└── libkicadbridge.so(XComponent 回调 + 拓扑序 dlopen + TSFN 就绪协议)
└── libkicad_core.so(KiCad 树内 KICAD_OHOS_CORE 目标)
├── single_top.cpp(TOP_FRAME=FRAME_SCH)+ pgm_base.cpp
├── wxGTK 3.2.8 全家(base/net/core/adv/aui/html/propgrid/stc/gl)
├── GTK3 栈(native/gtk-stack,含 OHOS GDK 后端)
├── _eeschema.kiface(entry/libs 模块通道,运行时 dlopen)
└── OCCT / Python 3.11 / curl / libgit2 / boost / GLEW / gl4es 闭包
主要目录如下:
text
AirEDA/
├── AppScope/app.json5 # 包名 com.aireda.app、版本 1.0.0
├── PORTING.md # 选型/依赖矩阵/补丁/风险四表登记
├── native/
│ ├── patches/wx-ohos/ # wxWidgets 五补丁(-lX11、glcanvas、对话框…)
│ ├── patches/kicad-ohos/ # KiCad 行为补丁(连线/放置工具退出)
│ ├── scripts/ # env.sh 与 wx/KiCad/依赖构建脚本
│ ├── gtk-stack/ # GTK3 OHOS 栈(自 AirGimp 本地化)
│ ├── sources/ # kicad-ohos 与 wx-ohos 源码适配层
│ ├── install/ # AIREDA_PREFIX 安装前缀
│ └── stubs/ # ngspice stub 等
├── tools/ # prepare_data.py、deploy_closure.py、deploy.sh
├── signature/ # 自建 CA 调试签名脚本
└── entry/src/main/
├── cpp/napi_init.cpp # NAPI 桥与菜单/选择器/图纸标签导出
└── ets/
├── pages/NativeHost.ets # 主宿主:XComponent + ArkTS 顶栏 + 模态遮罩
├── pages/DialogPage.ets # 对话框子窗页面
├── pages/*Viewer.ets # 早期 ArkTS 库浏览器(保留)
├── model/ # LibParser/SchParser/PcbParser/DataManager
└── render/ # Symbol/Sch/Pcb 三个渲染器
▍四、核心适配过程
### 1. 跨项目复用的依赖矩阵
PORTING.md 把依赖矩阵称为"本移植的命脉"。GTK3 加 OHOS GDK 后端直接取自 AirGimp 沉淀的安装栈(现已本地化为 native/gtk-stack,重写 .pc 文件里的死前缀);OCCT 7.8.1、Python 3.11.9、gl4es 复用 AirCad 的安装前缀,静态 libcurl 复用 AirRaw 的 curl-min。需要自编的是 wxWidgets 3.2.8 交叉构建、Boost locale/system/thread、GLEW_EGL 与 libgit2,ngspice 以 no-op stub 满足构建期硬依赖。deploy_kicad.sh 做闭包收集并去除 NEEDED 版本号后缀,产物落入 entry/libs/arm64-v8a。
### 2. KIWAY 单进程化与路径重建
KiCad 桌面版通过 fork/exec 拉起 kiface 子进程,鸿蒙没有这条通道。工程复用官方 single_top 的单进程模式(TOP_FRAME=FRAME_SCH),kiface 改经 entry/libs 模块通道运行时 dlopen。这依赖两处路径补丁:common/paths.cpp 的 GetExecutablePath() 在 OHOS 下早退返回 bundle 的 libs 目录(/proc/self/exe 在 appspawn 拉起的进程中不可用),common/kiway.cpp 的 dso 搜索路径改用同一来源,使 _eeschema.kiface 能在同目录被找到。KICAD_STOCK_DATA_HOME 等四个环境变量在宿主线程启动前指向沙箱目录,接管 XDG 约定。
### 3. 菜单栏 ArkTS 化与全量中文化
GTK 菜单栏在触屏桌面形态下并非最优承载。新增的 aireda_menu.cpp 把 wxMenuBar 周期性导出为 JSON(id/label/checkable/enabled/submenu),同时隐藏 GTK 原生菜单条;ArkTS 顶栏用 bindMenu 渲染层级菜单,点击经 aireda_activate_menu_item 由 g_main_context_invoke 送回 GTK 线程,按 wxMenuBase::SendEvent 契约投递菜单事件。中文化走 wxLocale 标准链路:kicad-i18n 8.0 分支的 zh_CN.po 编译为 kicad.mo(12537 条)随 wxstd.mo 部署,musl 下 newlocale 直接成功,无需额外补丁;图标体系则把 4654 个 PNG 打成 images.tar.gz 供 BITMAP_STORE 读取。
### 4. 文件选择器桥与保存链路
wxFileDialog 的 ShowModal 在 OHOS 被拦截,转而 dlsym 运行期解析 aireda_ohos_pick_file——musl 的急切重定位不允许留下链接期未定义符号,所以桥接符号必须全部可选解析、失败不致命。Picker 桥以 TSFN 进入 ArkTS 的 DocumentViewPicker,打开模式把返回 URI 拷入沙箱 picker_in/ 副本,保存模式走 picker_out/ staging 加同步守护回拷 URI(800ms 轮询、两拍稳定即回拷)。QA 阶段根修了签名不匹配的严重缺陷:保存 mode=1 被当作 char* 传入 strlen 导致 SEGV,打开模式侥幸幸存,参数契约对齐后保存链路首次端到端实证通过。
### 5. 对话框子窗口化与输入路由
对话框治理分三步演进:先是几何服务(120ms 周期检查,超 94%×88% 宿主即钳制居中、越界搬回、Esc 注入链关闭);2026-08-25 升级为鸿蒙子窗口——backend ops 把对话框帧直投 kicad-dialog-<id> 子窗,ArkTS DialogWindowManager 负责创建与几何(API 26 上 Window 实例的 createSubWindowWithOptions 会静默返回 undefined,必须走 WindowStage 方法)。输入侧则修了四层叠加缺陷:对话框子窗触摸代理静默失效,改指针事件注入;装饰条 37vp 未避让导致点击下漂;DIALOG_SHIM 位置恢复漂移与负坐标异常;bind 成功值判断写反使子窗模式恒不生效,修正后补一次 gdk_window_raise 解决主窗覆盖全宿主的 z 序竞争。
▍五、适配中遇到的几个难点
### 难点1:wxGTK 的 X11 假设渗入构建与运行
wx 的 configure 无条件向 GTK_LIBS 追加 -lX11,glcanvas 依赖 GLX,Khronos 的 eglplatform.h 又会引 X11 头。三个补丁分别处理:去掉 -lX11;OHOS 下 IsAvailable() 早退 false(反正没有 GLX/EGL surface 环境,KiCad 用 cairo GAL);加 -DEGL_NO_X11 并伪造 egl.pc 指向 sysroot EGL。GL GAL 保留 stub 化的编译通路但运行期拒绝创建,避免半可用的路径。
### 难点2:ArkTS 顶栏标签"能点击不显示"
菜单 JSON 已刷新、区域可点击,但顶栏 Text 内容空白,hilog 显示 paragraph is not formatted。排查出四个叠加根因:ForEach key 含 menuVersion 导致标签全部重建、新建节点可能永不绘制;最小化恢复后 ForEach 区域绘制整体丢失;方法调用式 Text 内容在本 SDK 完全不绘制(探针实证:字面量 442 亮像素、方法内容 0);属性挂载位组合嫌疑。逐项修正后仍有个别场景丢标签,最终定位到状态管理层——V1 @State 的渲染更新路径在模态与窗口切换场景会丢 ForEach 绘制,迁移 @ComponentV2 加 @Local 后全场景免疫。结论已记入工程方法学:照搬成熟结构要抄全,UI 结构与状态管理装饰器一个都不能少。
### 难点3:/proc/self/exe 在鸿蒙进程模型下不可用
KiCad 多处依赖 GetExecutablePath 定位自身资源与插件。appspawn 拉起的应用进程读 /proc/self/exe 得不到有效路径(AirRaw 的 whereami 同因实证)。解法是 OHOS 编译分支直接早退返回 /data/storage/el1/bundle/libs/arm64/,并让 kiway 的 dso 搜索、数据目录推导全部接在这一个入口上,把路径重建收敛为单点。
### 难点4:对话框输入的四层叠加失效
子窗化后对话框概率性不可点击,四层根因各自成立又互相掩盖:触摸代理路径对 wx 对话框静默失效;XComponent 未避让装饰条导致坐标系下漂 81px;DIALOG_SHIM 的位置恢复在负坐标下抛异常;bind 返回值判断写反使指针注入从未真正挂上。四层全部修复并验证后,又发现主窗 GdkWindow 覆盖全宿主时 z 序竞争会禁用点击命中,补一次 gdk_window_raise 收口。
### 难点5:hvigor 打包对预编译 so 的默认行为
闭包里的 so 来自交叉编译与第三方预编译,hvigor 默认的 strip 与库压缩都可能破坏它们。工程在 debug 与 release 双配置下关 strip(debugSymbol.strip=false)并关闭 compressNativeLibs;部署脚本的 NEEDED 重写顺序也有讲究——libz.so.1 到 libz.so 的改写必须先于系统库跳过判断,否则 musl dlopen 直接失败。
▍六、编译、安装与启动
native 侧构建链在 native/scripts/ 下按序执行(依赖与 wx/KiCad 产物已随仓库就位时,可跳过中间步骤只跑部署):
bash
source native/scripts/env.sh
build_wx.sh # wxGTK 3.2.8 交叉构建,产物入 native/install
build_kicad.sh # KiCad configure+make(kicad_ohos_core + eeschema_kiface)
deploy_kicad.sh # 闭包收集 → entry/libs/arm64-v8a + NEEDED 去版本号
随后走标准 hvigor 打包:
bash
export JAVA_HOME=/Applications/DevEco-Studio.app/Contents/jbr/Contents/Home
export DEVECO_SDK_HOME=/Applications/DevEco-Studio.app/Contents/sdk
hvigorw --mode module -p module=entry assembleHap --no-daemon
产物位于 entry/build/default/outputs/default/entry-default-signed.hap。签名有两点说明:工程自带的 signature/generate_debug_sign.py 自建 CA 签名在模拟器直装可用;HarmonyOS 商用版真机拒绝自建 CA profile(错误 9568257 fail to verify pkcs7),需 IDE 一键自动签名或 devecocli auth login 后 devecocli signature generate --product default。安装与启动:
bash
hdc install -r entry/build/default/outputs/default/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b com.aireda.app
▍七、当前功能边界
按 PORTING.md 的真机实证清单(MateBook 2in1,2026-08-22)与第七轮 QA 遍历(2026-08-28)记录,当前版本已覆盖:
- eeschema 原理图编辑器主界面:GTK menubar 隐藏,ArkTS 顶栏(文件/编辑/视图/放置/检查/工具/偏好设置)全中文渲染与命令激活;
- 全量中文化(12537 条翻译)与 22 种语言 catalog 打包,中英德日热切换闭环;
- 图标体系完整(4654 个 PNG 随包分发,问号缺失问题根修);
- 系统文件选择器打开 .kicad_sch(后缀过滤生效),保存链路 picker→staging→回拷端到端实证;
- 图纸标签条显示与点击切换、active 高亮;
- 大对话框子窗化:几何钳制、模态遮罩、Esc 关闭链、按钮全部可达;
- 原理图编辑操作:连线工具、放置工具退出逻辑、ERC、网表/剪贴板/符号库导出;
- 软键盘输入(IME 桥修复后键盘显示与输入到 GTK 输入框实证);
- 早期 ArkTS 库浏览器保留:109 库 5199 符号浏览、全库检索、18 套模板的原理图与 PCB 双标签渲染。
尚未覆盖或登记为遗留的能力:偏好设置对话框指针失效(投递链正常、部件级不响应,疑与 wxTreeBook 相关,待 libgdk 源码级调试);系统标题栏关闭键无效果(Esc 链可靠);目录选择器的 URI 子项枚举受 fs API 限制,现返回沙箱空镜像;对话框打开期间顶栏点击可穿透误开新对话框;3D 查看器与电路仿真不启用(ngspice 为 stub,OCC 仅编译期满足);数据手册外链接 no-op 处理;prepare_kicad_data.py 的全量重建所需外部源已缺失,仅支持增量注入。
因此,当前版本更准确的定位是"eeschema 原理图编辑的鸿蒙原生基础版":菜单、中文化、文件进出、对话框治理与画布编辑的主链路已在 2in1 真机走通,PCB 编辑器与仿真属于后续阶段目标。
▍八、总结
AirEDA 的移植价值首先在方法层面:它证明了当共享栈足够成熟时,wxWidgets 体系应用的上屏成本可以被压到可控范围——GTK3 OHOS 后端、交叉 Python、OCCT、gl4es 全部来自兄弟工程沉淀,本工程真正要解决的只剩 wx 假设裁剪、KIWAY 单进程化与对话框治理这些 KiCad 特有问题。工程留下的补丁登记与风险表,是下一批 wxGTK 应用移植可以直接引用的检查清单。
后续工作的重心按遗留清单推进:偏好设置对话框的部件级调试、目录选择器的能力扩展、顶栏穿透与标题栏关闭键的收口,以及把 QA 机 API 24 的回归补齐。PCB 编辑器接入与 ngspice 仿真实化则构成 v1 之后的路线图,每一步仍以真机上的可点击、可保存、可复现作为验收口径。
■ 应用:AirEDA(from KiCad)(AirEDA)
■ 定位:KiCad 移植,电子设计 EDA 与器件库浏览
■ 上游:KiCad 8.0.8 | 路线:wxGTK3+GTK3 栈 | 版本:1.1.0
■ 开源: https://gitcode.com/Andy88/Harmony-KiCad
■ 市场状态:已上架 AGC 应用页: https://appgallery.huawei.com/app/6917614382376546372
■ 官网(免费下载): https://www.shunidc.cn/
————————————————————
开源鸿蒙 PC 社区: https://harmonypc.csdn.net/
PC 社区项目申请: https://atomgit.com/OpenHarmonyPCDeveloper
适配开源地址:https://gitcode.com/Andy88/Harmony-KiCad
环境搭建文章:https://blog.csdn.net/weixin_52908342/article/details/161343743
▍一、为什么要适配 AirEDA
KiCad 是开源电子设计自动化的旗舰项目,原理图编辑器 eeschema 与 PCB 编辑器覆盖了从符号库、网表到版图的完整设计流程。EDA 软件对窗口系统、图形渲染与字体文本的要求在桌面应用中属于最高一档,把它的原理图编辑主链路带到鸿蒙 PC,等于让系统的 GTK 兼容层、窗口管理与输入管线接受一次接近生产级强度的检验。
本工程当前版本 1.0.0,包名 com.aireda.app,deviceTypes 覆盖 phone、tablet 与 2in1。工程经历了一次明确的路线升级:早期实现是纯 ArkTS 的 KiCad 器件库浏览器——解析 KiCad 4.0.x 官方库的 109 个符号库、5199 个元器件符号与 18 套工程模板,自行完成 EESchema、kicad_pcb 格式解析与画布渲染;2026-08-19 起按用户需求转向 KiCad 8.0.8 真应用的全栈原生移植,采用 AirGimp 同款双层架构。原 ArkTS 查看器代码保留在 pages/*Viewer 相关页面,如今作为器件库与模板的浏览入口继续工作。
移植路线的关键决定有三条:GUI 栈选 wxWidgets 3.2.8 的 wxGTK3 后端加 AirGimp 工程沉淀的 GTK3 OHOS GDK 后端;渲染选 cairo GAL 软件渲染,GL GAL 走 stub(KiCad 配置预设 noaccel);入口选 eeschema,以官方 single_top 加 eeschema_kiface 模块机制运行,KIWAY 插件框架原样保留。仓库 PORTING.md 按选型、依赖矩阵、补丁登记、风险登记四张表完整记录了决策依据。
▍二、先划清边界:不把编译通过当成适配完成
KiCad 桌面版运行在完整的 Linux 桌面环境里:X11 窗口系统、桌面 WM 管理对话框、GTK 原生菜单栏、系统文件选择器与 XDG 目录约定,都是它默认存在的地基。鸿蒙侧没有 fork/exec、没有 X11、没有独立 WM,应用还生活在 el2 沙箱内。移植的实质是为每一层地基找一个鸿蒙等价物,找不到的以补丁显式裁剪,而不是留着一条走不通的路径伪装完整。
层次 原项目实现(KiCad 桌面版) 鸿蒙侧当前方案
应用入口 kicad 主程序 fork/exec 拉起 kiface 单进程 single_top(FRAME_SCH)+ kiface 运行时 dlopen,KIWAY 机制保留
窗口系统 X11 与桌面 WM GDK OHOS 后端(GTK3 栈)+ XComponent(TEXTURE)宿主
图形渲染 OpenGL GAL(wxGLCanvas) cairo GAL 软件渲染,kicad.yaml 预设 noaccel
菜单栏 GTK wxMenuBar 原生渲染 wxMenuBar 导出 JSON,ArkTS 顶栏 bindMenu 渲染与命令激活
文件对话框 GTK wxFileDialog/wxDirDialog ShowModal 拦截,经 TSFN 转 ArkTS 系统 Picker,staging 暂存回拷
对话框承载 WM 管理的顶级窗口 鸿蒙子窗口(kicad-dialog-id)+ ArkTS 模态遮罩与几何钳制
数据目录 XDG 系统目录约定 KICAD_STOCK_DATA_HOME 等环境变量指向沙箱,资源随 HAP 部署
帮助与外链 浏览器拉起帮助与数据手册 AddStandardHelpMenu 早退、GetAssociatedDocument 置为 no-op
这条边界的直接含义是:当前产物是能在鸿蒙设备上打开、编辑原理图并存盘的 eeschema 子集,PCB 编辑器、3D 查看器与电路仿真不在 v1 范围(ngspice 以 stub 满足 KiCad 8 的构建期硬依赖)。
▍三、鸿蒙版的整体架构
架构为 Air 系列标准的双层 GTK 变体。ArkTS 壳管理 Ability、顶栏菜单、对话框子窗与文件选择器;NAPI 薄壳 libkicadbridge.so 处理 XComponent 回调、按拓扑序 dlopen 依赖并建立线程安全函数通道;libkicad_core.so 在 KiCad 源码树内构建,聚合 wxGTK 全家、GTK3 栈与 kiface,宿主线程上完成环境变量前置、gtk_init、GDK 预绑定后进入 wxEntryStart 与 CallOnInit。
text
ArkTS 壳(EntryAbility / NativeHost.ets / DialogPage.ets)
│ NAPI
└── libkicadbridge.so(XComponent 回调 + 拓扑序 dlopen + TSFN 就绪协议)
└── libkicad_core.so(KiCad 树内 KICAD_OHOS_CORE 目标)
├── single_top.cpp(TOP_FRAME=FRAME_SCH)+ pgm_base.cpp
├── wxGTK 3.2.8 全家(base/net/core/adv/aui/html/propgrid/stc/gl)
├── GTK3 栈(native/gtk-stack,含 OHOS GDK 后端)
├── _eeschema.kiface(entry/libs 模块通道,运行时 dlopen)
└── OCCT / Python 3.11 / curl / libgit2 / boost / GLEW / gl4es 闭包
主要目录如下:
text
AirEDA/
├── AppScope/app.json5 # 包名 com.aireda.app、版本 1.0.0
├── PORTING.md # 选型/依赖矩阵/补丁/风险四表登记
├── native/
│ ├── patches/wx-ohos/ # wxWidgets 五补丁(-lX11、glcanvas、对话框…)
│ ├── patches/kicad-ohos/ # KiCad 行为补丁(连线/放置工具退出)
│ ├── scripts/ # env.sh 与 wx/KiCad/依赖构建脚本
│ ├── gtk-stack/ # GTK3 OHOS 栈(自 AirGimp 本地化)
│ ├── sources/ # kicad-ohos 与 wx-ohos 源码适配层
│ ├── install/ # AIREDA_PREFIX 安装前缀
│ └── stubs/ # ngspice stub 等
├── tools/ # prepare_data.py、deploy_closure.py、deploy.sh
├── signature/ # 自建 CA 调试签名脚本
└── entry/src/main/
├── cpp/napi_init.cpp # NAPI 桥与菜单/选择器/图纸标签导出
└── ets/
├── pages/NativeHost.ets # 主宿主:XComponent + ArkTS 顶栏 + 模态遮罩
├── pages/DialogPage.ets # 对话框子窗页面
├── pages/*Viewer.ets # 早期 ArkTS 库浏览器(保留)
├── model/ # LibParser/SchParser/PcbParser/DataManager
└── render/ # Symbol/Sch/Pcb 三个渲染器
▍四、核心适配过程
### 1. 跨项目复用的依赖矩阵
PORTING.md 把依赖矩阵称为"本移植的命脉"。GTK3 加 OHOS GDK 后端直接取自 AirGimp 沉淀的安装栈(现已本地化为 native/gtk-stack,重写 .pc 文件里的死前缀);OCCT 7.8.1、Python 3.11.9、gl4es 复用 AirCad 的安装前缀,静态 libcurl 复用 AirRaw 的 curl-min。需要自编的是 wxWidgets 3.2.8 交叉构建、Boost locale/system/thread、GLEW_EGL 与 libgit2,ngspice 以 no-op stub 满足构建期硬依赖。deploy_kicad.sh 做闭包收集并去除 NEEDED 版本号后缀,产物落入 entry/libs/arm64-v8a。
### 2. KIWAY 单进程化与路径重建
KiCad 桌面版通过 fork/exec 拉起 kiface 子进程,鸿蒙没有这条通道。工程复用官方 single_top 的单进程模式(TOP_FRAME=FRAME_SCH),kiface 改经 entry/libs 模块通道运行时 dlopen。这依赖两处路径补丁:common/paths.cpp 的 GetExecutablePath() 在 OHOS 下早退返回 bundle 的 libs 目录(/proc/self/exe 在 appspawn 拉起的进程中不可用),common/kiway.cpp 的 dso 搜索路径改用同一来源,使 _eeschema.kiface 能在同目录被找到。KICAD_STOCK_DATA_HOME 等四个环境变量在宿主线程启动前指向沙箱目录,接管 XDG 约定。
### 3. 菜单栏 ArkTS 化与全量中文化
GTK 菜单栏在触屏桌面形态下并非最优承载。新增的 aireda_menu.cpp 把 wxMenuBar 周期性导出为 JSON(id/label/checkable/enabled/submenu),同时隐藏 GTK 原生菜单条;ArkTS 顶栏用 bindMenu 渲染层级菜单,点击经 aireda_activate_menu_item 由 g_main_context_invoke 送回 GTK 线程,按 wxMenuBase::SendEvent 契约投递菜单事件。中文化走 wxLocale 标准链路:kicad-i18n 8.0 分支的 zh_CN.po 编译为 kicad.mo(12537 条)随 wxstd.mo 部署,musl 下 newlocale 直接成功,无需额外补丁;图标体系则把 4654 个 PNG 打成 images.tar.gz 供 BITMAP_STORE 读取。
### 4. 文件选择器桥与保存链路
wxFileDialog 的 ShowModal 在 OHOS 被拦截,转而 dlsym 运行期解析 aireda_ohos_pick_file——musl 的急切重定位不允许留下链接期未定义符号,所以桥接符号必须全部可选解析、失败不致命。Picker 桥以 TSFN 进入 ArkTS 的 DocumentViewPicker,打开模式把返回 URI 拷入沙箱 picker_in/ 副本,保存模式走 picker_out/ staging 加同步守护回拷 URI(800ms 轮询、两拍稳定即回拷)。QA 阶段根修了签名不匹配的严重缺陷:保存 mode=1 被当作 char* 传入 strlen 导致 SEGV,打开模式侥幸幸存,参数契约对齐后保存链路首次端到端实证通过。
### 5. 对话框子窗口化与输入路由
对话框治理分三步演进:先是几何服务(120ms 周期检查,超 94%×88% 宿主即钳制居中、越界搬回、Esc 注入链关闭);2026-08-25 升级为鸿蒙子窗口——backend ops 把对话框帧直投 kicad-dialog-<id> 子窗,ArkTS DialogWindowManager 负责创建与几何(API 26 上 Window 实例的 createSubWindowWithOptions 会静默返回 undefined,必须走 WindowStage 方法)。输入侧则修了四层叠加缺陷:对话框子窗触摸代理静默失效,改指针事件注入;装饰条 37vp 未避让导致点击下漂;DIALOG_SHIM 位置恢复漂移与负坐标异常;bind 成功值判断写反使子窗模式恒不生效,修正后补一次 gdk_window_raise 解决主窗覆盖全宿主的 z 序竞争。
▍五、适配中遇到的几个难点
### 难点1:wxGTK 的 X11 假设渗入构建与运行
wx 的 configure 无条件向 GTK_LIBS 追加 -lX11,glcanvas 依赖 GLX,Khronos 的 eglplatform.h 又会引 X11 头。三个补丁分别处理:去掉 -lX11;OHOS 下 IsAvailable() 早退 false(反正没有 GLX/EGL surface 环境,KiCad 用 cairo GAL);加 -DEGL_NO_X11 并伪造 egl.pc 指向 sysroot EGL。GL GAL 保留 stub 化的编译通路但运行期拒绝创建,避免半可用的路径。
### 难点2:ArkTS 顶栏标签"能点击不显示"
菜单 JSON 已刷新、区域可点击,但顶栏 Text 内容空白,hilog 显示 paragraph is not formatted。排查出四个叠加根因:ForEach key 含 menuVersion 导致标签全部重建、新建节点可能永不绘制;最小化恢复后 ForEach 区域绘制整体丢失;方法调用式 Text 内容在本 SDK 完全不绘制(探针实证:字面量 442 亮像素、方法内容 0);属性挂载位组合嫌疑。逐项修正后仍有个别场景丢标签,最终定位到状态管理层——V1 @State 的渲染更新路径在模态与窗口切换场景会丢 ForEach 绘制,迁移 @ComponentV2 加 @Local 后全场景免疫。结论已记入工程方法学:照搬成熟结构要抄全,UI 结构与状态管理装饰器一个都不能少。
### 难点3:/proc/self/exe 在鸿蒙进程模型下不可用
KiCad 多处依赖 GetExecutablePath 定位自身资源与插件。appspawn 拉起的应用进程读 /proc/self/exe 得不到有效路径(AirRaw 的 whereami 同因实证)。解法是 OHOS 编译分支直接早退返回 /data/storage/el1/bundle/libs/arm64/,并让 kiway 的 dso 搜索、数据目录推导全部接在这一个入口上,把路径重建收敛为单点。
### 难点4:对话框输入的四层叠加失效
子窗化后对话框概率性不可点击,四层根因各自成立又互相掩盖:触摸代理路径对 wx 对话框静默失效;XComponent 未避让装饰条导致坐标系下漂 81px;DIALOG_SHIM 的位置恢复在负坐标下抛异常;bind 返回值判断写反使指针注入从未真正挂上。四层全部修复并验证后,又发现主窗 GdkWindow 覆盖全宿主时 z 序竞争会禁用点击命中,补一次 gdk_window_raise 收口。
### 难点5:hvigor 打包对预编译 so 的默认行为
闭包里的 so 来自交叉编译与第三方预编译,hvigor 默认的 strip 与库压缩都可能破坏它们。工程在 debug 与 release 双配置下关 strip(debugSymbol.strip=false)并关闭 compressNativeLibs;部署脚本的 NEEDED 重写顺序也有讲究——libz.so.1 到 libz.so 的改写必须先于系统库跳过判断,否则 musl dlopen 直接失败。
▍六、编译、安装与启动
native 侧构建链在 native/scripts/ 下按序执行(依赖与 wx/KiCad 产物已随仓库就位时,可跳过中间步骤只跑部署):
bash
source native/scripts/env.sh
build_wx.sh # wxGTK 3.2.8 交叉构建,产物入 native/install
build_kicad.sh # KiCad configure+make(kicad_ohos_core + eeschema_kiface)
deploy_kicad.sh # 闭包收集 → entry/libs/arm64-v8a + NEEDED 去版本号
随后走标准 hvigor 打包:
bash
export JAVA_HOME=/Applications/DevEco-Studio.app/Contents/jbr/Contents/Home
export DEVECO_SDK_HOME=/Applications/DevEco-Studio.app/Contents/sdk
hvigorw --mode module -p module=entry assembleHap --no-daemon
产物位于 entry/build/default/outputs/default/entry-default-signed.hap。签名有两点说明:工程自带的 signature/generate_debug_sign.py 自建 CA 签名在模拟器直装可用;HarmonyOS 商用版真机拒绝自建 CA profile(错误 9568257 fail to verify pkcs7),需 IDE 一键自动签名或 devecocli auth login 后 devecocli signature generate --product default。安装与启动:
bash
hdc install -r entry/build/default/outputs/default/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b com.aireda.app
▍七、当前功能边界
按 PORTING.md 的真机实证清单(MateBook 2in1,2026-08-22)与第七轮 QA 遍历(2026-08-28)记录,当前版本已覆盖:
- eeschema 原理图编辑器主界面:GTK menubar 隐藏,ArkTS 顶栏(文件/编辑/视图/放置/检查/工具/偏好设置)全中文渲染与命令激活;
- 全量中文化(12537 条翻译)与 22 种语言 catalog 打包,中英德日热切换闭环;
- 图标体系完整(4654 个 PNG 随包分发,问号缺失问题根修);
- 系统文件选择器打开 .kicad_sch(后缀过滤生效),保存链路 picker→staging→回拷端到端实证;
- 图纸标签条显示与点击切换、active 高亮;
- 大对话框子窗化:几何钳制、模态遮罩、Esc 关闭链、按钮全部可达;
- 原理图编辑操作:连线工具、放置工具退出逻辑、ERC、网表/剪贴板/符号库导出;
- 软键盘输入(IME 桥修复后键盘显示与输入到 GTK 输入框实证);
- 早期 ArkTS 库浏览器保留:109 库 5199 符号浏览、全库检索、18 套模板的原理图与 PCB 双标签渲染。
尚未覆盖或登记为遗留的能力:偏好设置对话框指针失效(投递链正常、部件级不响应,疑与 wxTreeBook 相关,待 libgdk 源码级调试);系统标题栏关闭键无效果(Esc 链可靠);目录选择器的 URI 子项枚举受 fs API 限制,现返回沙箱空镜像;对话框打开期间顶栏点击可穿透误开新对话框;3D 查看器与电路仿真不启用(ngspice 为 stub,OCC 仅编译期满足);数据手册外链接 no-op 处理;prepare_kicad_data.py 的全量重建所需外部源已缺失,仅支持增量注入。
因此,当前版本更准确的定位是"eeschema 原理图编辑的鸿蒙原生基础版":菜单、中文化、文件进出、对话框治理与画布编辑的主链路已在 2in1 真机走通,PCB 编辑器与仿真属于后续阶段目标。
▍八、总结
AirEDA 的移植价值首先在方法层面:它证明了当共享栈足够成熟时,wxWidgets 体系应用的上屏成本可以被压到可控范围——GTK3 OHOS 后端、交叉 Python、OCCT、gl4es 全部来自兄弟工程沉淀,本工程真正要解决的只剩 wx 假设裁剪、KIWAY 单进程化与对话框治理这些 KiCad 特有问题。工程留下的补丁登记与风险表,是下一批 wxGTK 应用移植可以直接引用的检查清单。
后续工作的重心按遗留清单推进:偏好设置对话框的部件级调试、目录选择器的能力扩展、顶栏穿透与标题栏关闭键的收口,以及把 QA 机 API 24 的回归补齐。PCB 编辑器接入与 ngspice 仿真实化则构成 v1 之后的路线图,每一步仍以真机上的可点击、可保存、可复现作为验收口径。
楼主
8 天前